From 682f23e7bb4a52bedf46eff5c4859e1308eda124 Mon Sep 17 00:00:00 2001 From: Michał Cichoń Date: Tue, 25 Aug 2015 19:56:24 +0200 Subject: Update build ref --- build | 2 +- compatibility/stdbool.h | 11 - compatibility/stdint.h | 247 - compatibility/unistd.h | 42 - json-c/src/Android.configure.mk | 39 + json-c/src/README.md | 63 + json-c/src/configure.ac | 114 + json-c/src/json-c-uninstalled.pc.in | 11 + json-c/src/json-c.pc.in | 12 + json-c/src/json-c.vcproj | 185 + json-c/src/json-c.vcxproj | 165 + json-c/src/json-c.vcxproj.filters | 90 + json-c/src/json_c_version.c | 20 + json-c/src/json_c_version.h | 22 + json-c/src/json_config.h.win32 | 5 + json-c/src/libjson.c | 26 + json-c/src/math_compat.h | 31 + json-c/src/random_seed.c | 238 + json-c/src/random_seed.h | 25 + json-c/src/tests/Makefile.am | 41 + json-c/src/tests/parse_flags.c | 50 + json-c/src/tests/parse_flags.h | 4 + json-c/src/tests/test-defs.sh | 128 + json-c/src/tests/test1.c | 134 + json-c/src/tests/test1.expected | 36 + json-c/src/tests/test1.test | 22 + json-c/src/tests/test1Formatted_plain.expected | 36 + json-c/src/tests/test1Formatted_pretty.expected | 59 + json-c/src/tests/test1Formatted_spaced.expected | 36 + json-c/src/tests/test2.c | 34 + json-c/src/tests/test2.expected | 1 + json-c/src/tests/test2.test | 22 + json-c/src/tests/test2Formatted_plain.expected | 1 + json-c/src/tests/test2Formatted_pretty.expected | 23 + json-c/src/tests/test2Formatted_spaced.expected | 1 + json-c/src/tests/test4.c | 53 + json-c/src/tests/test4.expected | 3 + json-c/src/tests/test4.test | 12 + json-c/src/tests/testReplaceExisting.c | 78 + json-c/src/tests/testReplaceExisting.expected | 15 + json-c/src/tests/testReplaceExisting.test | 12 + json-c/src/tests/test_cast.c | 111 + json-c/src/tests/test_cast.expected | 56 + json-c/src/tests/test_cast.test | 12 + json-c/src/tests/test_charcase.c | 40 + json-c/src/tests/test_charcase.expected | 1 + json-c/src/tests/test_charcase.test | 12 + json-c/src/tests/test_locale.c | 31 + json-c/src/tests/test_locale.expected | 2 + json-c/src/tests/test_locale.test | 12 + json-c/src/tests/test_null.c | 57 + json-c/src/tests/test_null.expected | 3 + json-c/src/tests/test_null.test | 12 + json-c/src/tests/test_parse.c | 342 + json-c/src/tests/test_parse.expected | 70 + json-c/src/tests/test_parse.test | 12 + json-c/src/tests/test_parse_int64.c | 115 + json-c/src/tests/test_parse_int64.expected | 29 + json-c/src/tests/test_parse_int64.test | 12 + json-c/src/tests/test_printbuf.c | 166 + json-c/src/tests/test_printbuf.expected | 32 + json-c/src/tests/test_printbuf.test | 12 + json-c/src/tests/test_set_serializer.c | 71 + json-c/src/tests/test_set_serializer.expected | 10 + json-c/src/tests/test_set_serializer.test | 12 + libcurl/libcurl.vcxproj | 129 + libcurl/libcurl.vcxproj.filters | 49 + libcurl/src/include/curl/curl.h | 2364 ++++++ libcurl/src/include/curl/curlbuild.h | 599 ++ libcurl/src/include/curl/curlbuild.h.cmake | 197 + libcurl/src/include/curl/curlbuild.h.in | 197 + libcurl/src/include/curl/curlrules.h | 262 + libcurl/src/include/curl/curlver.h | 69 + libcurl/src/include/curl/easy.h | 102 + libcurl/src/include/curl/mprintf.h | 74 + libcurl/src/include/curl/multi.h | 400 ++ libcurl/src/include/curl/stdcheaders.h | 33 + libcurl/src/include/curl/typecheck-gcc.h | 610 ++ libcurl/src/lib/amigaos.c | 77 + libcurl/src/lib/amigaos.h | 39 + libcurl/src/lib/arpa_telnet.h | 104 + libcurl/src/lib/asyn-ares.c | 691 ++ libcurl/src/lib/asyn-thread.c | 698 ++ libcurl/src/lib/asyn.h | 168 + libcurl/src/lib/base64.c | 309 + libcurl/src/lib/bundles.c | 110 + libcurl/src/lib/bundles.h | 45 + libcurl/src/lib/config-amigaos.h | 166 + libcurl/src/lib/config-android-arm.h | 1019 +++ libcurl/src/lib/config-android-x86.h | 1019 +++ libcurl/src/lib/config-dos.h | 181 + libcurl/src/lib/config-emscripten.h | 1032 +++ libcurl/src/lib/config-ios-sim.h | 1019 +++ libcurl/src/lib/config-ios.h | 1019 +++ libcurl/src/lib/config-mac.h | 125 + libcurl/src/lib/config-os400.h | 563 ++ libcurl/src/lib/config-osx.h | 1019 +++ libcurl/src/lib/config-riscos.h | 513 ++ libcurl/src/lib/config-symbian.h | 811 +++ libcurl/src/lib/config-tpf.h | 772 ++ libcurl/src/lib/config-vxworks.h | 928 +++ libcurl/src/lib/config-win32.h | 734 ++ libcurl/src/lib/config-win32ce.h | 448 ++ libcurl/src/lib/config-winrt.h | 468 ++ libcurl/src/lib/conncache.c | 289 + libcurl/src/lib/conncache.h | 57 + libcurl/src/lib/connect.c | 1377 ++++ libcurl/src/lib/connect.h | 122 + libcurl/src/lib/content_encoding.c | 435 ++ libcurl/src/lib/content_encoding.h | 48 + libcurl/src/lib/cookie.c | 1365 ++++ libcurl/src/lib/cookie.h | 104 + libcurl/src/lib/curl_addrinfo.c | 558 ++ libcurl/src/lib/curl_addrinfo.h | 101 + libcurl/src/lib/curl_base64.h | 35 + libcurl/src/lib/curl_config.h.cmake | 952 +++ libcurl/src/lib/curl_config.h.in | 1024 +++ libcurl/src/lib/curl_des.c | 63 + libcurl/src/lib/curl_des.h | 34 + libcurl/src/lib/curl_endian.c | 236 + libcurl/src/lib/curl_endian.h | 70 + libcurl/src/lib/curl_fnmatch.c | 424 ++ libcurl/src/lib/curl_fnmatch.h | 44 + libcurl/src/lib/curl_gethostname.c | 100 + libcurl/src/lib/curl_gethostname.h | 31 + libcurl/src/lib/curl_gssapi.c | 120 + libcurl/src/lib/curl_gssapi.h | 75 + libcurl/src/lib/curl_hmac.h | 67 + libcurl/src/lib/curl_ldap.h | 35 + libcurl/src/lib/curl_md4.h | 35 + libcurl/src/lib/curl_md5.h | 63 + libcurl/src/lib/curl_memory.h | 180 + libcurl/src/lib/curl_memrchr.c | 58 + libcurl/src/lib/curl_memrchr.h | 44 + libcurl/src/lib/curl_multibyte.c | 82 + libcurl/src/lib/curl_multibyte.h | 92 + libcurl/src/lib/curl_ntlm.c | 232 + libcurl/src/lib/curl_ntlm.h | 40 + libcurl/src/lib/curl_ntlm_core.c | 765 ++ libcurl/src/lib/curl_ntlm_core.h | 106 + libcurl/src/lib/curl_ntlm_msgs.c | 819 +++ libcurl/src/lib/curl_ntlm_msgs.h | 143 + libcurl/src/lib/curl_ntlm_wb.c | 431 ++ libcurl/src/lib/curl_ntlm_wb.h | 38 + libcurl/src/lib/curl_printf.h | 56 + libcurl/src/lib/curl_rtmp.c | 306 + libcurl/src/lib/curl_rtmp.h | 33 + libcurl/src/lib/curl_sasl.c | 1667 +++++ libcurl/src/lib/curl_sasl.h | 245 + libcurl/src/lib/curl_sasl_gssapi.c | 392 + libcurl/src/lib/curl_sasl_sspi.c | 1207 ++++ libcurl/src/lib/curl_sec.h | 51 + libcurl/src/lib/curl_setup.h | 713 ++ libcurl/src/lib/curl_setup_once.h | 551 ++ libcurl/src/lib/curl_sspi.c | 252 + libcurl/src/lib/curl_sspi.h | 342 + libcurl/src/lib/curl_threads.c | 136 + libcurl/src/lib/curl_threads.h | 62 + libcurl/src/lib/curlx.h | 118 + libcurl/src/lib/dict.c | 279 + libcurl/src/lib/dict.h | 29 + libcurl/src/lib/dotdot.c | 170 + libcurl/src/lib/dotdot.h | 25 + libcurl/src/lib/easy.c | 1130 +++ libcurl/src/lib/easyif.h | 33 + libcurl/src/lib/escape.c | 231 + libcurl/src/lib/escape.h | 33 + libcurl/src/lib/file.c | 588 ++ libcurl/src/lib/file.h | 41 + libcurl/src/lib/fileinfo.c | 50 + libcurl/src/lib/fileinfo.h | 33 + libcurl/src/lib/formdata.c | 1551 ++++ libcurl/src/lib/formdata.h | 98 + libcurl/src/lib/ftp.c | 4586 ++++++++++++ libcurl/src/lib/ftp.h | 159 + libcurl/src/lib/ftplistparser.c | 1048 +++ libcurl/src/lib/ftplistparser.h | 41 + libcurl/src/lib/getenv.c | 53 + libcurl/src/lib/getinfo.c | 382 + libcurl/src/lib/getinfo.h | 27 + libcurl/src/lib/gopher.c | 165 + libcurl/src/lib/gopher.h | 29 + libcurl/src/lib/hash.c | 396 + libcurl/src/lib/hash.h | 106 + libcurl/src/lib/hmac.c | 129 + libcurl/src/lib/hostasyn.c | 153 + libcurl/src/lib/hostcheck.c | 147 + libcurl/src/lib/hostcheck.h | 32 + libcurl/src/lib/hostip.c | 879 +++ libcurl/src/lib/hostip.h | 250 + libcurl/src/lib/hostip4.c | 307 + libcurl/src/lib/hostip6.c | 221 + libcurl/src/lib/hostsyn.c | 107 + libcurl/src/lib/http.c | 3717 ++++++++++ libcurl/src/lib/http.h | 224 + libcurl/src/lib/http2.c | 1077 +++ libcurl/src/lib/http2.h | 51 + libcurl/src/lib/http_chunks.c | 382 + libcurl/src/lib/http_chunks.h | 91 + libcurl/src/lib/http_digest.c | 179 + libcurl/src/lib/http_digest.h | 42 + libcurl/src/lib/http_negotiate.c | 208 + libcurl/src/lib/http_negotiate.h | 42 + libcurl/src/lib/http_negotiate_sspi.c | 298 + libcurl/src/lib/http_proxy.c | 590 ++ libcurl/src/lib/http_proxy.h | 41 + libcurl/src/lib/idn_win32.c | 108 + libcurl/src/lib/if2ip.c | 271 + libcurl/src/lib/if2ip.h | 83 + libcurl/src/lib/imap.c | 2142 ++++++ libcurl/src/lib/imap.h | 96 + libcurl/src/lib/inet_ntop.c | 198 + libcurl/src/lib/inet_ntop.h | 38 + libcurl/src/lib/inet_pton.c | 234 + libcurl/src/lib/inet_pton.h | 37 + libcurl/src/lib/krb5.c | 332 + libcurl/src/lib/ldap.c | 1013 +++ libcurl/src/lib/libcurl.rc | 63 + libcurl/src/lib/llist.c | 212 + libcurl/src/lib/llist.h | 57 + libcurl/src/lib/md4.c | 304 + libcurl/src/lib/md5.c | 560 ++ libcurl/src/lib/memdebug.c | 489 ++ libcurl/src/lib/memdebug.h | 176 + libcurl/src/lib/mprintf.c | 1142 +++ libcurl/src/lib/multi.c | 2815 ++++++++ libcurl/src/lib/multihandle.h | 143 + libcurl/src/lib/multiif.h | 93 + libcurl/src/lib/netrc.c | 199 + libcurl/src/lib/netrc.h | 36 + libcurl/src/lib/non-ascii.c | 338 + libcurl/src/lib/non-ascii.h | 63 + libcurl/src/lib/nonblock.c | 91 + libcurl/src/lib/nonblock.h | 31 + libcurl/src/lib/nwlib.c | 325 + libcurl/src/lib/nwos.c | 88 + libcurl/src/lib/openldap.c | 684 ++ libcurl/src/lib/parsedate.c | 583 ++ libcurl/src/lib/parsedate.h | 31 + libcurl/src/lib/pingpong.c | 507 ++ libcurl/src/lib/pingpong.h | 150 + libcurl/src/lib/pipeline.c | 338 + libcurl/src/lib/pipeline.h | 44 + libcurl/src/lib/pop3.c | 1601 +++++ libcurl/src/lib/pop3.h | 95 + libcurl/src/lib/progress.c | 492 ++ libcurl/src/lib/progress.h | 73 + libcurl/src/lib/rawstr.c | 142 + libcurl/src/lib/rawstr.h | 47 + libcurl/src/lib/rtsp.c | 807 +++ libcurl/src/lib/rtsp.h | 69 + libcurl/src/lib/security.c | 597 ++ libcurl/src/lib/select.c | 578 ++ libcurl/src/lib/select.h | 114 + libcurl/src/lib/sendf.c | 710 ++ libcurl/src/lib/sendf.h | 93 + libcurl/src/lib/setup-os400.h | 223 + libcurl/src/lib/setup-vms.h | 430 ++ libcurl/src/lib/share.c | 253 + libcurl/src/lib/share.h | 61 + libcurl/src/lib/sigpipe.h | 78 + libcurl/src/lib/slist.c | 143 + libcurl/src/lib/slist.h | 40 + libcurl/src/lib/smb.c | 970 +++ libcurl/src/lib/smb.h | 271 + libcurl/src/lib/smtp.c | 1671 +++++ libcurl/src/lib/smtp.h | 91 + libcurl/src/lib/sockaddr.h | 43 + libcurl/src/lib/socks.c | 755 ++ libcurl/src/lib/socks.h | 77 + libcurl/src/lib/socks_gssapi.c | 522 ++ libcurl/src/lib/socks_sspi.c | 601 ++ libcurl/src/lib/speedcheck.c | 74 + libcurl/src/lib/speedcheck.h | 33 + libcurl/src/lib/splay.c | 288 + libcurl/src/lib/splay.h | 66 + libcurl/src/lib/ssh.c | 3341 +++++++++ libcurl/src/lib/ssh.h | 195 + libcurl/src/lib/strdup.c | 73 + libcurl/src/lib/strdup.h | 31 + libcurl/src/lib/strequal.c | 79 + libcurl/src/lib/strequal.h | 31 + libcurl/src/lib/strerror.c | 1139 +++ libcurl/src/lib/strerror.h | 37 + libcurl/src/lib/strtok.c | 66 + libcurl/src/lib/strtok.h | 34 + libcurl/src/lib/strtoofft.c | 188 + libcurl/src/lib/strtoofft.h | 75 + libcurl/src/lib/telnet.c | 1674 +++++ libcurl/src/lib/telnet.h | 29 + libcurl/src/lib/tftp.c | 1376 ++++ libcurl/src/lib/tftp.h | 29 + libcurl/src/lib/timeval.c | 142 + libcurl/src/lib/timeval.h | 58 + libcurl/src/lib/transfer.c | 2004 ++++++ libcurl/src/lib/transfer.h | 70 + libcurl/src/lib/url.c | 6164 ++++++++++++++++ libcurl/src/lib/url.h | 82 + libcurl/src/lib/urldata.h | 1695 +++++ libcurl/src/lib/version.c | 362 + libcurl/src/lib/vtls/axtls.c | 696 ++ libcurl/src/lib/vtls/axtls.h | 71 + libcurl/src/lib/vtls/cyassl.c | 734 ++ libcurl/src/lib/vtls/cyassl.h | 70 + libcurl/src/lib/vtls/darwinssl.c | 2484 +++++++ libcurl/src/lib/vtls/darwinssl.h | 76 + libcurl/src/lib/vtls/gskit.c | 1069 +++ libcurl/src/lib/vtls/gskit.h | 71 + libcurl/src/lib/vtls/gtls.c | 1480 ++++ libcurl/src/lib/vtls/gtls.h | 83 + libcurl/src/lib/vtls/nss.c | 2006 ++++++ libcurl/src/lib/vtls/nssg.h | 96 + libcurl/src/lib/vtls/openssl.c | 3226 +++++++++ libcurl/src/lib/vtls/openssl.h | 113 + libcurl/src/lib/vtls/polarssl.c | 753 ++ libcurl/src/lib/vtls/polarssl.h | 75 + libcurl/src/lib/vtls/polarssl_threadlock.c | 153 + libcurl/src/lib/vtls/polarssl_threadlock.h | 53 + libcurl/src/lib/vtls/schannel.c | 1364 ++++ libcurl/src/lib/vtls/schannel.h | 117 + libcurl/src/lib/vtls/vtls.c | 895 +++ libcurl/src/lib/vtls/vtls.h | 153 + libcurl/src/lib/warnless.c | 486 ++ libcurl/src/lib/warnless.h | 107 + libcurl/src/lib/wildcard.c | 69 + libcurl/src/lib/wildcard.h | 58 + libcurl/src/lib/x509asn1.c | 1187 +++ libcurl/src/lib/x509asn1.h | 131 + libcurl/src/libcurl_unified.c | 172 + libmad/configured/config.h | 130 - libmad/configured/mad.h | 948 --- libmad/libmad.vcxproj | 141 - libmad/libmad.vcxproj.filters | 105 - libmad/src/CHANGES | 338 - libmad/src/COPYING | 340 - libmad/src/COPYRIGHT | 21 - libmad/src/CREDITS | 116 - libmad/src/D.dat | 607 -- libmad/src/README | 241 - libmad/src/bit.c | 237 - libmad/src/bit.h | 47 - libmad/src/decoder.c | 582 -- libmad/src/decoder.h | 91 - libmad/src/fixed.c | 90 - libmad/src/fixed.h | 499 -- libmad/src/frame.c | 512 -- libmad/src/frame.h | 118 - libmad/src/global.h | 58 - libmad/src/huffman.c | 3109 -------- libmad/src/huffman.h | 66 - libmad/src/imdct_s.dat | 62 - libmad/src/layer12.c | 543 -- libmad/src/layer12.h | 31 - libmad/src/layer3.c | 2707 ------- libmad/src/layer3.h | 30 - libmad/src/qc_table.dat | 77 - libmad/src/rq_table.dat | 8747 ----------------------- libmad/src/sf_table.dat | 106 - libmad/src/stream.c | 161 - libmad/src/stream.h | 108 - libmad/src/synth.c | 866 --- libmad/src/synth.h | 69 - libmad/src/timer.c | 485 -- libmad/src/timer.h | 100 - libmad/src/version.c | 91 - libmad/src/version.h | 47 - pianobar/resources/pianobar.ico | Bin 0 -> 90566 bytes pianobar/resources/pianobar.rc | 36 + polarssl/polarssl.vcxproj | 271 - polarssl/polarssl.vcxproj.filters | 258 - polarssl/src/LICENSE | 339 - polarssl/src/include/polarssl/aes.h | 176 - polarssl/src/include/polarssl/arc4.h | 80 - polarssl/src/include/polarssl/asn1.h | 246 - polarssl/src/include/polarssl/asn1write.h | 46 - polarssl/src/include/polarssl/base64.h | 87 - polarssl/src/include/polarssl/bignum.h | 632 -- polarssl/src/include/polarssl/bn_mul.h | 742 -- polarssl/src/include/polarssl/camellia.h | 182 - polarssl/src/include/polarssl/certs.h | 47 - polarssl/src/include/polarssl/cipher.h | 459 -- polarssl/src/include/polarssl/cipher_wrap.h | 95 - polarssl/src/include/polarssl/config.h | 744 -- polarssl/src/include/polarssl/ctr_drbg.h | 228 - polarssl/src/include/polarssl/debug.h | 89 - polarssl/src/include/polarssl/des.h | 227 - polarssl/src/include/polarssl/dhm.h | 153 - polarssl/src/include/polarssl/entropy.h | 150 - polarssl/src/include/polarssl/entropy_poll.h | 75 - polarssl/src/include/polarssl/error.h | 102 - polarssl/src/include/polarssl/gcm.h | 142 - polarssl/src/include/polarssl/havege.h | 71 - polarssl/src/include/polarssl/md.h | 354 - polarssl/src/include/polarssl/md2.h | 153 - polarssl/src/include/polarssl/md4.h | 152 - polarssl/src/include/polarssl/md5.h | 154 - polarssl/src/include/polarssl/md_wrap.h | 64 - polarssl/src/include/polarssl/net.h | 159 - polarssl/src/include/polarssl/openssl.h | 136 - polarssl/src/include/polarssl/padlock.h | 100 - polarssl/src/include/polarssl/pem.h | 100 - polarssl/src/include/polarssl/pkcs11.h | 126 - polarssl/src/include/polarssl/rsa.h | 379 - polarssl/src/include/polarssl/sha1.h | 152 - polarssl/src/include/polarssl/sha2.h | 160 - polarssl/src/include/polarssl/sha4.h | 168 - polarssl/src/include/polarssl/ssl.h | 766 -- polarssl/src/include/polarssl/timing.h | 75 - polarssl/src/include/polarssl/version.h | 81 - polarssl/src/include/polarssl/x509.h | 733 -- polarssl/src/include/polarssl/x509write.h | 46 - polarssl/src/include/polarssl/xtea.h | 111 - polarssl/src/library/aes.c | 1346 ---- polarssl/src/library/arc4.c | 169 - polarssl/src/library/asn1parse.c | 260 - polarssl/src/library/asn1write.c | 241 - polarssl/src/library/base64.c | 254 - polarssl/src/library/bignum.c | 2111 ------ polarssl/src/library/camellia.c | 1032 --- polarssl/src/library/certs.c | 196 - polarssl/src/library/cipher.c | 557 -- polarssl/src/library/cipher_wrap.c | 595 -- polarssl/src/library/ctr_drbg.c | 562 -- polarssl/src/library/debug.c | 238 - polarssl/src/library/des.c | 993 --- polarssl/src/library/dhm.c | 296 - polarssl/src/library/entropy.c | 204 - polarssl/src/library/entropy_poll.c | 136 - polarssl/src/library/error.c | 525 -- polarssl/src/library/gcm.c | 653 -- polarssl/src/library/havege.c | 231 - polarssl/src/library/md.c | 297 - polarssl/src/library/md2.c | 364 - polarssl/src/library/md4.c | 460 -- polarssl/src/library/md5.c | 583 -- polarssl/src/library/md_wrap.c | 733 -- polarssl/src/library/net.c | 358 - polarssl/src/library/padlock.c | 162 - polarssl/src/library/pem.c | 352 - polarssl/src/library/pkcs11.c | 238 - polarssl/src/library/rsa.c | 1219 ---- polarssl/src/library/sha1.c | 624 -- polarssl/src/library/sha2.c | 705 -- polarssl/src/library/sha4.c | 760 -- polarssl/src/library/ssl_cli.c | 1130 --- polarssl/src/library/ssl_srv.c | 1080 --- polarssl/src/library/ssl_tls.c | 3166 -------- polarssl/src/library/timing.c | 271 - polarssl/src/library/version.c | 50 - polarssl/src/library/x509parse.c | 3425 --------- polarssl/src/library/x509write.c | 287 - polarssl/src/library/xtea.c | 248 - pthreads/pthread-win32.vcxproj | 122 - pthreads/pthread-win32.vcxproj.filters | 33 - pthreads/src/COPYING.LIB | 504 -- pthreads/src/README | 601 -- pthreads/src/attr.c | 53 - pthreads/src/autostatic.c | 69 - pthreads/src/barrier.c | 47 - pthreads/src/cancel.c | 44 - pthreads/src/cleanup.c | 148 - pthreads/src/condvar.c | 50 - pthreads/src/config.h | 153 - pthreads/src/context.h | 74 - pthreads/src/create.c | 308 - pthreads/src/dll.c | 92 - pthreads/src/errno.c | 94 - pthreads/src/exit.c | 44 - pthreads/src/fork.c | 39 - pthreads/src/global.c | 107 - pthreads/src/implement.h | 943 --- pthreads/src/misc.c | 51 - pthreads/src/mutex.c | 62 - pthreads/src/need_errno.h | 145 - pthreads/src/nonportable.c | 47 - pthreads/src/private.c | 52 - pthreads/src/pthread.c | 66 - pthreads/src/pthread.h | 1368 ---- pthreads/src/pthread_attr_destroy.c | 79 - pthreads/src/pthread_attr_getdetachstate.c | 86 - pthreads/src/pthread_attr_getinheritsched.c | 51 - pthreads/src/pthread_attr_getschedparam.c | 52 - pthreads/src/pthread_attr_getschedpolicy.c | 61 - pthreads/src/pthread_attr_getscope.c | 54 - pthreads/src/pthread_attr_getstackaddr.c | 97 - pthreads/src/pthread_attr_getstacksize.c | 100 - pthreads/src/pthread_attr_init.c | 117 - pthreads/src/pthread_attr_setdetachstate.c | 91 - pthreads/src/pthread_attr_setinheritsched.c | 57 - pthreads/src/pthread_attr_setschedparam.c | 63 - pthreads/src/pthread_attr_setschedpolicy.c | 55 - pthreads/src/pthread_attr_setscope.c | 62 - pthreads/src/pthread_attr_setstackaddr.c | 97 - pthreads/src/pthread_attr_setstacksize.c | 110 - pthreads/src/pthread_barrier_destroy.c | 103 - pthreads/src/pthread_barrier_init.c | 69 - pthreads/src/pthread_barrier_wait.c | 104 - pthreads/src/pthread_barrierattr_destroy.c | 83 - pthreads/src/pthread_barrierattr_getpshared.c | 95 - pthreads/src/pthread_barrierattr_init.c | 85 - pthreads/src/pthread_barrierattr_setpshared.c | 119 - pthreads/src/pthread_cancel.c | 189 - pthreads/src/pthread_cond_destroy.c | 253 - pthreads/src/pthread_cond_init.c | 167 - pthreads/src/pthread_cond_signal.c | 231 - pthreads/src/pthread_cond_wait.c | 567 -- pthreads/src/pthread_condattr_destroy.c | 86 - pthreads/src/pthread_condattr_getpshared.c | 97 - pthreads/src/pthread_condattr_init.c | 87 - pthreads/src/pthread_condattr_setpshared.c | 117 - pthreads/src/pthread_delay_np.c | 172 - pthreads/src/pthread_detach.c | 136 - pthreads/src/pthread_equal.c | 76 - pthreads/src/pthread_exit.c | 106 - pthreads/src/pthread_getconcurrency.c | 45 - pthreads/src/pthread_getschedparam.c | 75 - pthreads/src/pthread_getspecific.c | 87 - pthreads/src/pthread_getunique_np.c | 47 - pthreads/src/pthread_getw32threadhandle_np.c | 65 - pthreads/src/pthread_join.c | 157 - pthreads/src/pthread_key_create.c | 108 - pthreads/src/pthread_key_delete.c | 125 - pthreads/src/pthread_kill.c | 105 - pthreads/src/pthread_mutex_consistent.c | 190 - pthreads/src/pthread_mutex_destroy.c | 148 - pthreads/src/pthread_mutex_init.c | 130 - pthreads/src/pthread_mutex_lock.c | 269 - pthreads/src/pthread_mutex_timedlock.c | 324 - pthreads/src/pthread_mutex_trylock.c | 154 - pthreads/src/pthread_mutex_unlock.c | 175 - pthreads/src/pthread_mutexattr_destroy.c | 83 - pthreads/src/pthread_mutexattr_getkind_np.c | 44 - pthreads/src/pthread_mutexattr_getpshared.c | 95 - pthreads/src/pthread_mutexattr_getrobust.c | 113 - pthreads/src/pthread_mutexattr_gettype.c | 56 - pthreads/src/pthread_mutexattr_init.c | 86 - pthreads/src/pthread_mutexattr_setkind_np.c | 44 - pthreads/src/pthread_mutexattr_setpshared.c | 119 - pthreads/src/pthread_mutexattr_setrobust.c | 119 - pthreads/src/pthread_mutexattr_settype.c | 143 - pthreads/src/pthread_num_processors_np.c | 56 - pthreads/src/pthread_once.c | 79 - pthreads/src/pthread_rwlock_destroy.c | 143 - pthreads/src/pthread_rwlock_init.c | 109 - pthreads/src/pthread_rwlock_rdlock.c | 102 - pthreads/src/pthread_rwlock_timedrdlock.c | 109 - pthreads/src/pthread_rwlock_timedwrlock.c | 139 - pthreads/src/pthread_rwlock_tryrdlock.c | 102 - pthreads/src/pthread_rwlock_trywrlock.c | 122 - pthreads/src/pthread_rwlock_unlock.c | 93 - pthreads/src/pthread_rwlock_wrlock.c | 133 - pthreads/src/pthread_rwlockattr_destroy.c | 84 - pthreads/src/pthread_rwlockattr_getpshared.c | 97 - pthreads/src/pthread_rwlockattr_init.c | 83 - pthreads/src/pthread_rwlockattr_setpshared.c | 120 - pthreads/src/pthread_self.c | 141 - pthreads/src/pthread_setcancelstate.c | 125 - pthreads/src/pthread_setcanceltype.c | 126 - pthreads/src/pthread_setconcurrency.c | 53 - pthreads/src/pthread_setschedparam.c | 123 - pthreads/src/pthread_setspecific.c | 167 - pthreads/src/pthread_spin_destroy.c | 111 - pthreads/src/pthread_spin_init.c | 123 - pthreads/src/pthread_spin_lock.c | 80 - pthreads/src/pthread_spin_trylock.c | 77 - pthreads/src/pthread_spin_unlock.c | 71 - pthreads/src/pthread_testcancel.c | 103 - pthreads/src/pthread_timechange_handler_np.c | 108 - pthreads/src/pthread_win32_attach_detach_np.c | 256 - pthreads/src/ptw32_MCS_lock.c | 278 - pthreads/src/ptw32_callUserDestroyRoutines.c | 232 - pthreads/src/ptw32_calloc.c | 56 - pthreads/src/ptw32_cond_check_need_init.c | 78 - pthreads/src/ptw32_getprocessors.c | 91 - pthreads/src/ptw32_is_attr.c | 47 - pthreads/src/ptw32_mutex_check_need_init.c | 92 - pthreads/src/ptw32_new.c | 94 - pthreads/src/ptw32_processInitialize.c | 92 - pthreads/src/ptw32_processTerminate.c | 105 - pthreads/src/ptw32_relmillisecs.c | 132 - pthreads/src/ptw32_reuse.c | 151 - pthreads/src/ptw32_rwlock_cancelwrwait.c | 50 - pthreads/src/ptw32_rwlock_check_need_init.c | 77 - pthreads/src/ptw32_semwait.c | 135 - pthreads/src/ptw32_spinlock_check_need_init.c | 78 - pthreads/src/ptw32_threadDestroy.c | 79 - pthreads/src/ptw32_threadStart.c | 357 - pthreads/src/ptw32_throw.c | 189 - pthreads/src/ptw32_timespec.c | 83 - pthreads/src/ptw32_tkAssocCreate.c | 118 - pthreads/src/ptw32_tkAssocDestroy.c | 114 - pthreads/src/rwlock.c | 51 - pthreads/src/sched.c | 53 - pthreads/src/sched.h | 183 - pthreads/src/sched_get_priority_max.c | 134 - pthreads/src/sched_get_priority_min.c | 135 - pthreads/src/sched_getscheduler.c | 71 - pthreads/src/sched_setscheduler.c | 83 - pthreads/src/sched_yield.c | 71 - pthreads/src/sem_close.c | 58 - pthreads/src/sem_destroy.c | 144 - pthreads/src/sem_getvalue.c | 110 - pthreads/src/sem_init.c | 169 - pthreads/src/sem_open.c | 58 - pthreads/src/sem_post.c | 128 - pthreads/src/sem_post_multiple.c | 142 - pthreads/src/sem_timedwait.c | 238 - pthreads/src/sem_trywait.c | 117 - pthreads/src/sem_unlink.c | 58 - pthreads/src/sem_wait.c | 187 - pthreads/src/semaphore.c | 69 - pthreads/src/semaphore.h | 169 - pthreads/src/signal.c | 179 - pthreads/src/spin.c | 46 - pthreads/src/sync.c | 43 - pthreads/src/tsd.c | 44 - pthreads/src/w32_CancelableWait.c | 161 - vtparse/src/Makefile | 19 + vtparse/src/README | 67 + vtparse/src/vtparse.c | 152 + vtparse/src/vtparse.h | 31 + vtparse/src/vtparse_check_tables.rb | 24 + vtparse/src/vtparse_gen_c_tables.rb | 95 + vtparse/src/vtparse_table.c | 2657 +++++++ vtparse/src/vtparse_table.h | 43 + vtparse/src/vtparse_tables.rb | 269 + vtparse/src/vtparse_test.c | 37 + vtparse/vtparse.vcxproj | 118 + vtparse/vtparse.vcxproj.filters | 11 + 629 files changed, 126520 insertions(+), 81308 deletions(-) delete mode 100644 compatibility/stdbool.h delete mode 100644 compatibility/stdint.h delete mode 100644 compatibility/unistd.h create mode 100644 json-c/src/Android.configure.mk create mode 100644 json-c/src/README.md create mode 100644 json-c/src/configure.ac create mode 100644 json-c/src/json-c-uninstalled.pc.in create mode 100644 json-c/src/json-c.pc.in create mode 100644 json-c/src/json-c.vcproj create mode 100644 json-c/src/json-c.vcxproj create mode 100644 json-c/src/json-c.vcxproj.filters create mode 100644 json-c/src/json_c_version.c create mode 100644 json-c/src/json_c_version.h create mode 100644 json-c/src/json_config.h.win32 create mode 100644 json-c/src/libjson.c create mode 100644 json-c/src/math_compat.h create mode 100644 json-c/src/random_seed.c create mode 100644 json-c/src/random_seed.h create mode 100644 json-c/src/tests/Makefile.am create mode 100644 json-c/src/tests/parse_flags.c create mode 100644 json-c/src/tests/parse_flags.h create mode 100644 json-c/src/tests/test-defs.sh create mode 100644 json-c/src/tests/test1.c create mode 100644 json-c/src/tests/test1.expected create mode 100644 json-c/src/tests/test1.test create mode 100644 json-c/src/tests/test1Formatted_plain.expected create mode 100644 json-c/src/tests/test1Formatted_pretty.expected create mode 100644 json-c/src/tests/test1Formatted_spaced.expected create mode 100644 json-c/src/tests/test2.c create mode 100644 json-c/src/tests/test2.expected create mode 100644 json-c/src/tests/test2.test create mode 100644 json-c/src/tests/test2Formatted_plain.expected create mode 100644 json-c/src/tests/test2Formatted_pretty.expected create mode 100644 json-c/src/tests/test2Formatted_spaced.expected create mode 100644 json-c/src/tests/test4.c create mode 100644 json-c/src/tests/test4.expected create mode 100644 json-c/src/tests/test4.test create mode 100644 json-c/src/tests/testReplaceExisting.c create mode 100644 json-c/src/tests/testReplaceExisting.expected create mode 100644 json-c/src/tests/testReplaceExisting.test create mode 100644 json-c/src/tests/test_cast.c create mode 100644 json-c/src/tests/test_cast.expected create mode 100644 json-c/src/tests/test_cast.test create mode 100644 json-c/src/tests/test_charcase.c create mode 100644 json-c/src/tests/test_charcase.expected create mode 100644 json-c/src/tests/test_charcase.test create mode 100644 json-c/src/tests/test_locale.c create mode 100644 json-c/src/tests/test_locale.expected create mode 100644 json-c/src/tests/test_locale.test create mode 100644 json-c/src/tests/test_null.c create mode 100644 json-c/src/tests/test_null.expected create mode 100644 json-c/src/tests/test_null.test create mode 100644 json-c/src/tests/test_parse.c create mode 100644 json-c/src/tests/test_parse.expected create mode 100644 json-c/src/tests/test_parse.test create mode 100644 json-c/src/tests/test_parse_int64.c create mode 100644 json-c/src/tests/test_parse_int64.expected create mode 100644 json-c/src/tests/test_parse_int64.test create mode 100644 json-c/src/tests/test_printbuf.c create mode 100644 json-c/src/tests/test_printbuf.expected create mode 100644 json-c/src/tests/test_printbuf.test create mode 100644 json-c/src/tests/test_set_serializer.c create mode 100644 json-c/src/tests/test_set_serializer.expected create mode 100644 json-c/src/tests/test_set_serializer.test create mode 100644 libcurl/libcurl.vcxproj create mode 100644 libcurl/libcurl.vcxproj.filters create mode 100644 libcurl/src/include/curl/curl.h create mode 100644 libcurl/src/include/curl/curlbuild.h create mode 100644 libcurl/src/include/curl/curlbuild.h.cmake create mode 100644 libcurl/src/include/curl/curlbuild.h.in create mode 100644 libcurl/src/include/curl/curlrules.h create mode 100644 libcurl/src/include/curl/curlver.h create mode 100644 libcurl/src/include/curl/easy.h create mode 100644 libcurl/src/include/curl/mprintf.h create mode 100644 libcurl/src/include/curl/multi.h create mode 100644 libcurl/src/include/curl/stdcheaders.h create mode 100644 libcurl/src/include/curl/typecheck-gcc.h create mode 100644 libcurl/src/lib/amigaos.c create mode 100644 libcurl/src/lib/amigaos.h create mode 100644 libcurl/src/lib/arpa_telnet.h create mode 100644 libcurl/src/lib/asyn-ares.c create mode 100644 libcurl/src/lib/asyn-thread.c create mode 100644 libcurl/src/lib/asyn.h create mode 100644 libcurl/src/lib/base64.c create mode 100644 libcurl/src/lib/bundles.c create mode 100644 libcurl/src/lib/bundles.h create mode 100644 libcurl/src/lib/config-amigaos.h create mode 100644 libcurl/src/lib/config-android-arm.h create mode 100644 libcurl/src/lib/config-android-x86.h create mode 100644 libcurl/src/lib/config-dos.h create mode 100644 libcurl/src/lib/config-emscripten.h create mode 100644 libcurl/src/lib/config-ios-sim.h create mode 100644 libcurl/src/lib/config-ios.h create mode 100644 libcurl/src/lib/config-mac.h create mode 100644 libcurl/src/lib/config-os400.h create mode 100644 libcurl/src/lib/config-osx.h create mode 100644 libcurl/src/lib/config-riscos.h create mode 100644 libcurl/src/lib/config-symbian.h create mode 100644 libcurl/src/lib/config-tpf.h create mode 100644 libcurl/src/lib/config-vxworks.h create mode 100644 libcurl/src/lib/config-win32.h create mode 100644 libcurl/src/lib/config-win32ce.h create mode 100644 libcurl/src/lib/config-winrt.h create mode 100644 libcurl/src/lib/conncache.c create mode 100644 libcurl/src/lib/conncache.h create mode 100644 libcurl/src/lib/connect.c create mode 100644 libcurl/src/lib/connect.h create mode 100644 libcurl/src/lib/content_encoding.c create mode 100644 libcurl/src/lib/content_encoding.h create mode 100644 libcurl/src/lib/cookie.c create mode 100644 libcurl/src/lib/cookie.h create mode 100644 libcurl/src/lib/curl_addrinfo.c create mode 100644 libcurl/src/lib/curl_addrinfo.h create mode 100644 libcurl/src/lib/curl_base64.h create mode 100644 libcurl/src/lib/curl_config.h.cmake create mode 100644 libcurl/src/lib/curl_config.h.in create mode 100644 libcurl/src/lib/curl_des.c create mode 100644 libcurl/src/lib/curl_des.h create mode 100644 libcurl/src/lib/curl_endian.c create mode 100644 libcurl/src/lib/curl_endian.h create mode 100644 libcurl/src/lib/curl_fnmatch.c create mode 100644 libcurl/src/lib/curl_fnmatch.h create mode 100644 libcurl/src/lib/curl_gethostname.c create mode 100644 libcurl/src/lib/curl_gethostname.h create mode 100644 libcurl/src/lib/curl_gssapi.c create mode 100644 libcurl/src/lib/curl_gssapi.h create mode 100644 libcurl/src/lib/curl_hmac.h create mode 100644 libcurl/src/lib/curl_ldap.h create mode 100644 libcurl/src/lib/curl_md4.h create mode 100644 libcurl/src/lib/curl_md5.h create mode 100644 libcurl/src/lib/curl_memory.h create mode 100644 libcurl/src/lib/curl_memrchr.c create mode 100644 libcurl/src/lib/curl_memrchr.h create mode 100644 libcurl/src/lib/curl_multibyte.c create mode 100644 libcurl/src/lib/curl_multibyte.h create mode 100644 libcurl/src/lib/curl_ntlm.c create mode 100644 libcurl/src/lib/curl_ntlm.h create mode 100644 libcurl/src/lib/curl_ntlm_core.c create mode 100644 libcurl/src/lib/curl_ntlm_core.h create mode 100644 libcurl/src/lib/curl_ntlm_msgs.c create mode 100644 libcurl/src/lib/curl_ntlm_msgs.h create mode 100644 libcurl/src/lib/curl_ntlm_wb.c create mode 100644 libcurl/src/lib/curl_ntlm_wb.h create mode 100644 libcurl/src/lib/curl_printf.h create mode 100644 libcurl/src/lib/curl_rtmp.c create mode 100644 libcurl/src/lib/curl_rtmp.h create mode 100644 libcurl/src/lib/curl_sasl.c create mode 100644 libcurl/src/lib/curl_sasl.h create mode 100644 libcurl/src/lib/curl_sasl_gssapi.c create mode 100644 libcurl/src/lib/curl_sasl_sspi.c create mode 100644 libcurl/src/lib/curl_sec.h create mode 100644 libcurl/src/lib/curl_setup.h create mode 100644 libcurl/src/lib/curl_setup_once.h create mode 100644 libcurl/src/lib/curl_sspi.c create mode 100644 libcurl/src/lib/curl_sspi.h create mode 100644 libcurl/src/lib/curl_threads.c create mode 100644 libcurl/src/lib/curl_threads.h create mode 100644 libcurl/src/lib/curlx.h create mode 100644 libcurl/src/lib/dict.c create mode 100644 libcurl/src/lib/dict.h create mode 100644 libcurl/src/lib/dotdot.c create mode 100644 libcurl/src/lib/dotdot.h create mode 100644 libcurl/src/lib/easy.c create mode 100644 libcurl/src/lib/easyif.h create mode 100644 libcurl/src/lib/escape.c create mode 100644 libcurl/src/lib/escape.h create mode 100644 libcurl/src/lib/file.c create mode 100644 libcurl/src/lib/file.h create mode 100644 libcurl/src/lib/fileinfo.c create mode 100644 libcurl/src/lib/fileinfo.h create mode 100644 libcurl/src/lib/formdata.c create mode 100644 libcurl/src/lib/formdata.h create mode 100644 libcurl/src/lib/ftp.c create mode 100644 libcurl/src/lib/ftp.h create mode 100644 libcurl/src/lib/ftplistparser.c create mode 100644 libcurl/src/lib/ftplistparser.h create mode 100644 libcurl/src/lib/getenv.c create mode 100644 libcurl/src/lib/getinfo.c create mode 100644 libcurl/src/lib/getinfo.h create mode 100644 libcurl/src/lib/gopher.c create mode 100644 libcurl/src/lib/gopher.h create mode 100644 libcurl/src/lib/hash.c create mode 100644 libcurl/src/lib/hash.h create mode 100644 libcurl/src/lib/hmac.c create mode 100644 libcurl/src/lib/hostasyn.c create mode 100644 libcurl/src/lib/hostcheck.c create mode 100644 libcurl/src/lib/hostcheck.h create mode 100644 libcurl/src/lib/hostip.c create mode 100644 libcurl/src/lib/hostip.h create mode 100644 libcurl/src/lib/hostip4.c create mode 100644 libcurl/src/lib/hostip6.c create mode 100644 libcurl/src/lib/hostsyn.c create mode 100644 libcurl/src/lib/http.c create mode 100644 libcurl/src/lib/http.h create mode 100644 libcurl/src/lib/http2.c create mode 100644 libcurl/src/lib/http2.h create mode 100644 libcurl/src/lib/http_chunks.c create mode 100644 libcurl/src/lib/http_chunks.h create mode 100644 libcurl/src/lib/http_digest.c create mode 100644 libcurl/src/lib/http_digest.h create mode 100644 libcurl/src/lib/http_negotiate.c create mode 100644 libcurl/src/lib/http_negotiate.h create mode 100644 libcurl/src/lib/http_negotiate_sspi.c create mode 100644 libcurl/src/lib/http_proxy.c create mode 100644 libcurl/src/lib/http_proxy.h create mode 100644 libcurl/src/lib/idn_win32.c create mode 100644 libcurl/src/lib/if2ip.c create mode 100644 libcurl/src/lib/if2ip.h create mode 100644 libcurl/src/lib/imap.c create mode 100644 libcurl/src/lib/imap.h create mode 100644 libcurl/src/lib/inet_ntop.c create mode 100644 libcurl/src/lib/inet_ntop.h create mode 100644 libcurl/src/lib/inet_pton.c create mode 100644 libcurl/src/lib/inet_pton.h create mode 100644 libcurl/src/lib/krb5.c create mode 100644 libcurl/src/lib/ldap.c create mode 100644 libcurl/src/lib/libcurl.rc create mode 100644 libcurl/src/lib/llist.c create mode 100644 libcurl/src/lib/llist.h create mode 100644 libcurl/src/lib/md4.c create mode 100644 libcurl/src/lib/md5.c create mode 100644 libcurl/src/lib/memdebug.c create mode 100644 libcurl/src/lib/memdebug.h create mode 100644 libcurl/src/lib/mprintf.c create mode 100644 libcurl/src/lib/multi.c create mode 100644 libcurl/src/lib/multihandle.h create mode 100644 libcurl/src/lib/multiif.h create mode 100644 libcurl/src/lib/netrc.c create mode 100644 libcurl/src/lib/netrc.h create mode 100644 libcurl/src/lib/non-ascii.c create mode 100644 libcurl/src/lib/non-ascii.h create mode 100644 libcurl/src/lib/nonblock.c create mode 100644 libcurl/src/lib/nonblock.h create mode 100644 libcurl/src/lib/nwlib.c create mode 100644 libcurl/src/lib/nwos.c create mode 100644 libcurl/src/lib/openldap.c create mode 100644 libcurl/src/lib/parsedate.c create mode 100644 libcurl/src/lib/parsedate.h create mode 100644 libcurl/src/lib/pingpong.c create mode 100644 libcurl/src/lib/pingpong.h create mode 100644 libcurl/src/lib/pipeline.c create mode 100644 libcurl/src/lib/pipeline.h create mode 100644 libcurl/src/lib/pop3.c create mode 100644 libcurl/src/lib/pop3.h create mode 100644 libcurl/src/lib/progress.c create mode 100644 libcurl/src/lib/progress.h create mode 100644 libcurl/src/lib/rawstr.c create mode 100644 libcurl/src/lib/rawstr.h create mode 100644 libcurl/src/lib/rtsp.c create mode 100644 libcurl/src/lib/rtsp.h create mode 100644 libcurl/src/lib/security.c create mode 100644 libcurl/src/lib/select.c create mode 100644 libcurl/src/lib/select.h create mode 100644 libcurl/src/lib/sendf.c create mode 100644 libcurl/src/lib/sendf.h create mode 100644 libcurl/src/lib/setup-os400.h create mode 100644 libcurl/src/lib/setup-vms.h create mode 100644 libcurl/src/lib/share.c create mode 100644 libcurl/src/lib/share.h create mode 100644 libcurl/src/lib/sigpipe.h create mode 100644 libcurl/src/lib/slist.c create mode 100644 libcurl/src/lib/slist.h create mode 100644 libcurl/src/lib/smb.c create mode 100644 libcurl/src/lib/smb.h create mode 100644 libcurl/src/lib/smtp.c create mode 100644 libcurl/src/lib/smtp.h create mode 100644 libcurl/src/lib/sockaddr.h create mode 100644 libcurl/src/lib/socks.c create mode 100644 libcurl/src/lib/socks.h create mode 100644 libcurl/src/lib/socks_gssapi.c create mode 100644 libcurl/src/lib/socks_sspi.c create mode 100644 libcurl/src/lib/speedcheck.c create mode 100644 libcurl/src/lib/speedcheck.h create mode 100644 libcurl/src/lib/splay.c create mode 100644 libcurl/src/lib/splay.h create mode 100644 libcurl/src/lib/ssh.c create mode 100644 libcurl/src/lib/ssh.h create mode 100644 libcurl/src/lib/strdup.c create mode 100644 libcurl/src/lib/strdup.h create mode 100644 libcurl/src/lib/strequal.c create mode 100644 libcurl/src/lib/strequal.h create mode 100644 libcurl/src/lib/strerror.c create mode 100644 libcurl/src/lib/strerror.h create mode 100644 libcurl/src/lib/strtok.c create mode 100644 libcurl/src/lib/strtok.h create mode 100644 libcurl/src/lib/strtoofft.c create mode 100644 libcurl/src/lib/strtoofft.h create mode 100644 libcurl/src/lib/telnet.c create mode 100644 libcurl/src/lib/telnet.h create mode 100644 libcurl/src/lib/tftp.c create mode 100644 libcurl/src/lib/tftp.h create mode 100644 libcurl/src/lib/timeval.c create mode 100644 libcurl/src/lib/timeval.h create mode 100644 libcurl/src/lib/transfer.c create mode 100644 libcurl/src/lib/transfer.h create mode 100644 libcurl/src/lib/url.c create mode 100644 libcurl/src/lib/url.h create mode 100644 libcurl/src/lib/urldata.h create mode 100644 libcurl/src/lib/version.c create mode 100644 libcurl/src/lib/vtls/axtls.c create mode 100644 libcurl/src/lib/vtls/axtls.h create mode 100644 libcurl/src/lib/vtls/cyassl.c create mode 100644 libcurl/src/lib/vtls/cyassl.h create mode 100644 libcurl/src/lib/vtls/darwinssl.c create mode 100644 libcurl/src/lib/vtls/darwinssl.h create mode 100644 libcurl/src/lib/vtls/gskit.c create mode 100644 libcurl/src/lib/vtls/gskit.h create mode 100644 libcurl/src/lib/vtls/gtls.c create mode 100644 libcurl/src/lib/vtls/gtls.h create mode 100644 libcurl/src/lib/vtls/nss.c create mode 100644 libcurl/src/lib/vtls/nssg.h create mode 100644 libcurl/src/lib/vtls/openssl.c create mode 100644 libcurl/src/lib/vtls/openssl.h create mode 100644 libcurl/src/lib/vtls/polarssl.c create mode 100644 libcurl/src/lib/vtls/polarssl.h create mode 100644 libcurl/src/lib/vtls/polarssl_threadlock.c create mode 100644 libcurl/src/lib/vtls/polarssl_threadlock.h create mode 100644 libcurl/src/lib/vtls/schannel.c create mode 100644 libcurl/src/lib/vtls/schannel.h create mode 100644 libcurl/src/lib/vtls/vtls.c create mode 100644 libcurl/src/lib/vtls/vtls.h create mode 100644 libcurl/src/lib/warnless.c create mode 100644 libcurl/src/lib/warnless.h create mode 100644 libcurl/src/lib/wildcard.c create mode 100644 libcurl/src/lib/wildcard.h create mode 100644 libcurl/src/lib/x509asn1.c create mode 100644 libcurl/src/lib/x509asn1.h create mode 100644 libcurl/src/libcurl_unified.c delete mode 100644 libmad/configured/config.h delete mode 100644 libmad/configured/mad.h delete mode 100644 libmad/libmad.vcxproj delete mode 100644 libmad/libmad.vcxproj.filters delete mode 100644 libmad/src/CHANGES delete mode 100644 libmad/src/COPYING delete mode 100644 libmad/src/COPYRIGHT delete mode 100644 libmad/src/CREDITS delete mode 100644 libmad/src/D.dat delete mode 100644 libmad/src/README delete mode 100644 libmad/src/bit.c delete mode 100644 libmad/src/bit.h delete mode 100644 libmad/src/decoder.c delete mode 100644 libmad/src/decoder.h delete mode 100644 libmad/src/fixed.c delete mode 100644 libmad/src/fixed.h delete mode 100644 libmad/src/frame.c delete mode 100644 libmad/src/frame.h delete mode 100644 libmad/src/global.h delete mode 100644 libmad/src/huffman.c delete mode 100644 libmad/src/huffman.h delete mode 100644 libmad/src/imdct_s.dat delete mode 100644 libmad/src/layer12.c delete mode 100644 libmad/src/layer12.h delete mode 100644 libmad/src/layer3.c delete mode 100644 libmad/src/layer3.h delete mode 100644 libmad/src/qc_table.dat delete mode 100644 libmad/src/rq_table.dat delete mode 100644 libmad/src/sf_table.dat delete mode 100644 libmad/src/stream.c delete mode 100644 libmad/src/stream.h delete mode 100644 libmad/src/synth.c delete mode 100644 libmad/src/synth.h delete mode 100644 libmad/src/timer.c delete mode 100644 libmad/src/timer.h delete mode 100644 libmad/src/version.c delete mode 100644 libmad/src/version.h create mode 100644 pianobar/resources/pianobar.ico create mode 100644 pianobar/resources/pianobar.rc delete mode 100644 polarssl/polarssl.vcxproj delete mode 100644 polarssl/polarssl.vcxproj.filters delete mode 100644 polarssl/src/LICENSE delete mode 100644 polarssl/src/include/polarssl/aes.h delete mode 100644 polarssl/src/include/polarssl/arc4.h delete mode 100644 polarssl/src/include/polarssl/asn1.h delete mode 100644 polarssl/src/include/polarssl/asn1write.h delete mode 100644 polarssl/src/include/polarssl/base64.h delete mode 100644 polarssl/src/include/polarssl/bignum.h delete mode 100644 polarssl/src/include/polarssl/bn_mul.h delete mode 100644 polarssl/src/include/polarssl/camellia.h delete mode 100644 polarssl/src/include/polarssl/certs.h delete mode 100644 polarssl/src/include/polarssl/cipher.h delete mode 100644 polarssl/src/include/polarssl/cipher_wrap.h delete mode 100644 polarssl/src/include/polarssl/config.h delete mode 100644 polarssl/src/include/polarssl/ctr_drbg.h delete mode 100644 polarssl/src/include/polarssl/debug.h delete mode 100644 polarssl/src/include/polarssl/des.h delete mode 100644 polarssl/src/include/polarssl/dhm.h delete mode 100644 polarssl/src/include/polarssl/entropy.h delete mode 100644 polarssl/src/include/polarssl/entropy_poll.h delete mode 100644 polarssl/src/include/polarssl/error.h delete mode 100644 polarssl/src/include/polarssl/gcm.h delete mode 100644 polarssl/src/include/polarssl/havege.h delete mode 100644 polarssl/src/include/polarssl/md.h delete mode 100644 polarssl/src/include/polarssl/md2.h delete mode 100644 polarssl/src/include/polarssl/md4.h delete mode 100644 polarssl/src/include/polarssl/md5.h delete mode 100644 polarssl/src/include/polarssl/md_wrap.h delete mode 100644 polarssl/src/include/polarssl/net.h delete mode 100644 polarssl/src/include/polarssl/openssl.h delete mode 100644 polarssl/src/include/polarssl/padlock.h delete mode 100644 polarssl/src/include/polarssl/pem.h delete mode 100644 polarssl/src/include/polarssl/pkcs11.h delete mode 100644 polarssl/src/include/polarssl/rsa.h delete mode 100644 polarssl/src/include/polarssl/sha1.h delete mode 100644 polarssl/src/include/polarssl/sha2.h delete mode 100644 polarssl/src/include/polarssl/sha4.h delete mode 100644 polarssl/src/include/polarssl/ssl.h delete mode 100644 polarssl/src/include/polarssl/timing.h delete mode 100644 polarssl/src/include/polarssl/version.h delete mode 100644 polarssl/src/include/polarssl/x509.h delete mode 100644 polarssl/src/include/polarssl/x509write.h delete mode 100644 polarssl/src/include/polarssl/xtea.h delete mode 100644 polarssl/src/library/aes.c delete mode 100644 polarssl/src/library/arc4.c delete mode 100644 polarssl/src/library/asn1parse.c delete mode 100644 polarssl/src/library/asn1write.c delete mode 100644 polarssl/src/library/base64.c delete mode 100644 polarssl/src/library/bignum.c delete mode 100644 polarssl/src/library/camellia.c delete mode 100644 polarssl/src/library/certs.c delete mode 100644 polarssl/src/library/cipher.c delete mode 100644 polarssl/src/library/cipher_wrap.c delete mode 100644 polarssl/src/library/ctr_drbg.c delete mode 100644 polarssl/src/library/debug.c delete mode 100644 polarssl/src/library/des.c delete mode 100644 polarssl/src/library/dhm.c delete mode 100644 polarssl/src/library/entropy.c delete mode 100644 polarssl/src/library/entropy_poll.c delete mode 100644 polarssl/src/library/error.c delete mode 100644 polarssl/src/library/gcm.c delete mode 100644 polarssl/src/library/havege.c delete mode 100644 polarssl/src/library/md.c delete mode 100644 polarssl/src/library/md2.c delete mode 100644 polarssl/src/library/md4.c delete mode 100644 polarssl/src/library/md5.c delete mode 100644 polarssl/src/library/md_wrap.c delete mode 100644 polarssl/src/library/net.c delete mode 100644 polarssl/src/library/padlock.c delete mode 100644 polarssl/src/library/pem.c delete mode 100644 polarssl/src/library/pkcs11.c delete mode 100644 polarssl/src/library/rsa.c delete mode 100644 polarssl/src/library/sha1.c delete mode 100644 polarssl/src/library/sha2.c delete mode 100644 polarssl/src/library/sha4.c delete mode 100644 polarssl/src/library/ssl_cli.c delete mode 100644 polarssl/src/library/ssl_srv.c delete mode 100644 polarssl/src/library/ssl_tls.c delete mode 100644 polarssl/src/library/timing.c delete mode 100644 polarssl/src/library/version.c delete mode 100644 polarssl/src/library/x509parse.c delete mode 100644 polarssl/src/library/x509write.c delete mode 100644 polarssl/src/library/xtea.c delete mode 100644 pthreads/pthread-win32.vcxproj delete mode 100644 pthreads/pthread-win32.vcxproj.filters delete mode 100644 pthreads/src/COPYING.LIB delete mode 100644 pthreads/src/README delete mode 100644 pthreads/src/attr.c delete mode 100644 pthreads/src/autostatic.c delete mode 100644 pthreads/src/barrier.c delete mode 100644 pthreads/src/cancel.c delete mode 100644 pthreads/src/cleanup.c delete mode 100644 pthreads/src/condvar.c delete mode 100644 pthreads/src/config.h delete mode 100644 pthreads/src/context.h delete mode 100644 pthreads/src/create.c delete mode 100644 pthreads/src/dll.c delete mode 100644 pthreads/src/errno.c delete mode 100644 pthreads/src/exit.c delete mode 100644 pthreads/src/fork.c delete mode 100644 pthreads/src/global.c delete mode 100644 pthreads/src/implement.h delete mode 100644 pthreads/src/misc.c delete mode 100644 pthreads/src/mutex.c delete mode 100644 pthreads/src/need_errno.h delete mode 100644 pthreads/src/nonportable.c delete mode 100644 pthreads/src/private.c delete mode 100644 pthreads/src/pthread.c delete mode 100644 pthreads/src/pthread.h delete mode 100644 pthreads/src/pthread_attr_destroy.c delete mode 100644 pthreads/src/pthread_attr_getdetachstate.c delete mode 100644 pthreads/src/pthread_attr_getinheritsched.c delete mode 100644 pthreads/src/pthread_attr_getschedparam.c delete mode 100644 pthreads/src/pthread_attr_getschedpolicy.c delete mode 100644 pthreads/src/pthread_attr_getscope.c delete mode 100644 pthreads/src/pthread_attr_getstackaddr.c delete mode 100644 pthreads/src/pthread_attr_getstacksize.c delete mode 100644 pthreads/src/pthread_attr_init.c delete mode 100644 pthreads/src/pthread_attr_setdetachstate.c delete mode 100644 pthreads/src/pthread_attr_setinheritsched.c delete mode 100644 pthreads/src/pthread_attr_setschedparam.c delete mode 100644 pthreads/src/pthread_attr_setschedpolicy.c delete mode 100644 pthreads/src/pthread_attr_setscope.c delete mode 100644 pthreads/src/pthread_attr_setstackaddr.c delete mode 100644 pthreads/src/pthread_attr_setstacksize.c delete mode 100644 pthreads/src/pthread_barrier_destroy.c delete mode 100644 pthreads/src/pthread_barrier_init.c delete mode 100644 pthreads/src/pthread_barrier_wait.c delete mode 100644 pthreads/src/pthread_barrierattr_destroy.c delete mode 100644 pthreads/src/pthread_barrierattr_getpshared.c delete mode 100644 pthreads/src/pthread_barrierattr_init.c delete mode 100644 pthreads/src/pthread_barrierattr_setpshared.c delete mode 100644 pthreads/src/pthread_cancel.c delete mode 100644 pthreads/src/pthread_cond_destroy.c delete mode 100644 pthreads/src/pthread_cond_init.c delete mode 100644 pthreads/src/pthread_cond_signal.c delete mode 100644 pthreads/src/pthread_cond_wait.c delete mode 100644 pthreads/src/pthread_condattr_destroy.c delete mode 100644 pthreads/src/pthread_condattr_getpshared.c delete mode 100644 pthreads/src/pthread_condattr_init.c delete mode 100644 pthreads/src/pthread_condattr_setpshared.c delete mode 100644 pthreads/src/pthread_delay_np.c delete mode 100644 pthreads/src/pthread_detach.c delete mode 100644 pthreads/src/pthread_equal.c delete mode 100644 pthreads/src/pthread_exit.c delete mode 100644 pthreads/src/pthread_getconcurrency.c delete mode 100644 pthreads/src/pthread_getschedparam.c delete mode 100644 pthreads/src/pthread_getspecific.c delete mode 100644 pthreads/src/pthread_getunique_np.c delete mode 100644 pthreads/src/pthread_getw32threadhandle_np.c delete mode 100644 pthreads/src/pthread_join.c delete mode 100644 pthreads/src/pthread_key_create.c delete mode 100644 pthreads/src/pthread_key_delete.c delete mode 100644 pthreads/src/pthread_kill.c delete mode 100644 pthreads/src/pthread_mutex_consistent.c delete mode 100644 pthreads/src/pthread_mutex_destroy.c delete mode 100644 pthreads/src/pthread_mutex_init.c delete mode 100644 pthreads/src/pthread_mutex_lock.c delete mode 100644 pthreads/src/pthread_mutex_timedlock.c delete mode 100644 pthreads/src/pthread_mutex_trylock.c delete mode 100644 pthreads/src/pthread_mutex_unlock.c delete mode 100644 pthreads/src/pthread_mutexattr_destroy.c delete mode 100644 pthreads/src/pthread_mutexattr_getkind_np.c delete mode 100644 pthreads/src/pthread_mutexattr_getpshared.c delete mode 100644 pthreads/src/pthread_mutexattr_getrobust.c delete mode 100644 pthreads/src/pthread_mutexattr_gettype.c delete mode 100644 pthreads/src/pthread_mutexattr_init.c delete mode 100644 pthreads/src/pthread_mutexattr_setkind_np.c delete mode 100644 pthreads/src/pthread_mutexattr_setpshared.c delete mode 100644 pthreads/src/pthread_mutexattr_setrobust.c delete mode 100644 pthreads/src/pthread_mutexattr_settype.c delete mode 100644 pthreads/src/pthread_num_processors_np.c delete mode 100644 pthreads/src/pthread_once.c delete mode 100644 pthreads/src/pthread_rwlock_destroy.c delete mode 100644 pthreads/src/pthread_rwlock_init.c delete mode 100644 pthreads/src/pthread_rwlock_rdlock.c delete mode 100644 pthreads/src/pthread_rwlock_timedrdlock.c delete mode 100644 pthreads/src/pthread_rwlock_timedwrlock.c delete mode 100644 pthreads/src/pthread_rwlock_tryrdlock.c delete mode 100644 pthreads/src/pthread_rwlock_trywrlock.c delete mode 100644 pthreads/src/pthread_rwlock_unlock.c delete mode 100644 pthreads/src/pthread_rwlock_wrlock.c delete mode 100644 pthreads/src/pthread_rwlockattr_destroy.c delete mode 100644 pthreads/src/pthread_rwlockattr_getpshared.c delete mode 100644 pthreads/src/pthread_rwlockattr_init.c delete mode 100644 pthreads/src/pthread_rwlockattr_setpshared.c delete mode 100644 pthreads/src/pthread_self.c delete mode 100644 pthreads/src/pthread_setcancelstate.c delete mode 100644 pthreads/src/pthread_setcanceltype.c delete mode 100644 pthreads/src/pthread_setconcurrency.c delete mode 100644 pthreads/src/pthread_setschedparam.c delete mode 100644 pthreads/src/pthread_setspecific.c delete mode 100644 pthreads/src/pthread_spin_destroy.c delete mode 100644 pthreads/src/pthread_spin_init.c delete mode 100644 pthreads/src/pthread_spin_lock.c delete mode 100644 pthreads/src/pthread_spin_trylock.c delete mode 100644 pthreads/src/pthread_spin_unlock.c delete mode 100644 pthreads/src/pthread_testcancel.c delete mode 100644 pthreads/src/pthread_timechange_handler_np.c delete mode 100644 pthreads/src/pthread_win32_attach_detach_np.c delete mode 100644 pthreads/src/ptw32_MCS_lock.c delete mode 100644 pthreads/src/ptw32_callUserDestroyRoutines.c delete mode 100644 pthreads/src/ptw32_calloc.c delete mode 100644 pthreads/src/ptw32_cond_check_need_init.c delete mode 100644 pthreads/src/ptw32_getprocessors.c delete mode 100644 pthreads/src/ptw32_is_attr.c delete mode 100644 pthreads/src/ptw32_mutex_check_need_init.c delete mode 100644 pthreads/src/ptw32_new.c delete mode 100644 pthreads/src/ptw32_processInitialize.c delete mode 100644 pthreads/src/ptw32_processTerminate.c delete mode 100644 pthreads/src/ptw32_relmillisecs.c delete mode 100644 pthreads/src/ptw32_reuse.c delete mode 100644 pthreads/src/ptw32_rwlock_cancelwrwait.c delete mode 100644 pthreads/src/ptw32_rwlock_check_need_init.c delete mode 100644 pthreads/src/ptw32_semwait.c delete mode 100644 pthreads/src/ptw32_spinlock_check_need_init.c delete mode 100644 pthreads/src/ptw32_threadDestroy.c delete mode 100644 pthreads/src/ptw32_threadStart.c delete mode 100644 pthreads/src/ptw32_throw.c delete mode 100644 pthreads/src/ptw32_timespec.c delete mode 100644 pthreads/src/ptw32_tkAssocCreate.c delete mode 100644 pthreads/src/ptw32_tkAssocDestroy.c delete mode 100644 pthreads/src/rwlock.c delete mode 100644 pthreads/src/sched.c delete mode 100644 pthreads/src/sched.h delete mode 100644 pthreads/src/sched_get_priority_max.c delete mode 100644 pthreads/src/sched_get_priority_min.c delete mode 100644 pthreads/src/sched_getscheduler.c delete mode 100644 pthreads/src/sched_setscheduler.c delete mode 100644 pthreads/src/sched_yield.c delete mode 100644 pthreads/src/sem_close.c delete mode 100644 pthreads/src/sem_destroy.c delete mode 100644 pthreads/src/sem_getvalue.c delete mode 100644 pthreads/src/sem_init.c delete mode 100644 pthreads/src/sem_open.c delete mode 100644 pthreads/src/sem_post.c delete mode 100644 pthreads/src/sem_post_multiple.c delete mode 100644 pthreads/src/sem_timedwait.c delete mode 100644 pthreads/src/sem_trywait.c delete mode 100644 pthreads/src/sem_unlink.c delete mode 100644 pthreads/src/sem_wait.c delete mode 100644 pthreads/src/semaphore.c delete mode 100644 pthreads/src/semaphore.h delete mode 100644 pthreads/src/signal.c delete mode 100644 pthreads/src/spin.c delete mode 100644 pthreads/src/sync.c delete mode 100644 pthreads/src/tsd.c delete mode 100644 pthreads/src/w32_CancelableWait.c create mode 100644 vtparse/src/Makefile create mode 100644 vtparse/src/README create mode 100644 vtparse/src/vtparse.c create mode 100644 vtparse/src/vtparse.h create mode 100644 vtparse/src/vtparse_check_tables.rb create mode 100644 vtparse/src/vtparse_gen_c_tables.rb create mode 100644 vtparse/src/vtparse_table.c create mode 100644 vtparse/src/vtparse_table.h create mode 100644 vtparse/src/vtparse_tables.rb create mode 100644 vtparse/src/vtparse_test.c create mode 100644 vtparse/vtparse.vcxproj create mode 100644 vtparse/vtparse.vcxproj.filters diff --git a/build b/build index d1924ec..58b2c56 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit d1924ec4fd379f5f906bb4be4f9654d79db9d74b +Subproject commit 58b2c56f0d96a54497f13fc295298dccd6e6ca9a diff --git a/compatibility/stdbool.h b/compatibility/stdbool.h deleted file mode 100644 index 1ea9bb1..0000000 --- a/compatibility/stdbool.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __STDBOOL_REPLACEMENT__H__ -#define __STDBOOL_REPLACEMENT__H__ - -#ifdef _MSC_VER -typedef enum { __bool_must_promote_to_int = -1, false = 0, true = 1 } __bool; -#define bool __bool -#define false 0 -#define true 1 -#endif - -#endif /* __STDBOOL_REPLACEMENT__H__ */ diff --git a/compatibility/stdint.h b/compatibility/stdint.h deleted file mode 100644 index 59d0673..0000000 --- a/compatibility/stdint.h +++ /dev/null @@ -1,247 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -# include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/compatibility/unistd.h b/compatibility/unistd.h deleted file mode 100644 index 3360ae2..0000000 --- a/compatibility/unistd.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _UNISTD_H -#define _UNISTD_H 1 - -/* This file intended to serve as a drop-in replacement for - * unistd.h on Windows - * Please add functionality as neeeded - */ - -#include -#include -//#include /* getopt from: http://www.pwilson.net/sample.html. */ - -#define srandom srand -#define random rand - -static const W_OK = 2; -static const R_OK = 4; - -#define access _access -#define ftruncate _chsize - -#undef ssize_t -#ifdef _WIN64 -typedef __int64 ssize_t; -#else -typedef _W64 int ssize_t; -#endif - -#define STDIN_FILENO 0 -#define STDOUT_FILENO 1 -#define STDERR_FILENO 2 -/* should be in some equivalent to */ -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; - -#endif /* unistd.h */ diff --git a/json-c/src/Android.configure.mk b/json-c/src/Android.configure.mk new file mode 100644 index 0000000..c52c220 --- /dev/null +++ b/json-c/src/Android.configure.mk @@ -0,0 +1,39 @@ +# This file is the top android makefile for all sub-modules. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +json_c_TOP := $(LOCAL_PATH) + +JSON_C_BUILT_SOURCES := Android.mk + +JSON_C_BUILT_SOURCES := $(patsubst %, $(abspath $(json_c_TOP))/%, $(JSON_C_BUILT_SOURCES)) + +.PHONY: json-c-configure json-c-configure-real +json-c-configure-real: + echo $(JSON_C_BUILT_SOURCES) + cd $(json_c_TOP) ; \ + $(abspath $(json_c_TOP))/autogen.sh && \ + CC="$(CONFIGURE_CC)" \ + CFLAGS="$(CONFIGURE_CFLAGS)" \ + LD=$(TARGET_LD) \ + LDFLAGS="$(CONFIGURE_LDFLAGS)" \ + CPP=$(CONFIGURE_CPP) \ + CPPFLAGS="$(CONFIGURE_CPPFLAGS)" \ + PKG_CONFIG_LIBDIR=$(CONFIGURE_PKG_CONFIG_LIBDIR) \ + PKG_CONFIG_TOP_BUILD_DIR=/ \ + ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + $(abspath $(json_c_TOP))/$(CONFIGURE) --host=$(CONFIGURE_HOST) \ + --prefix=/system \ + && \ + for file in $(JSON_C_BUILT_SOURCES); do \ + rm -f $$file && \ + make -C $$(dirname $$file) $$(basename $$file) ; \ + done + +json-c-configure: json-c-configure-real + +PA_CONFIGURE_TARGETS += json-c-configure + +-include $(json_c_TOP)/Android.mk diff --git a/json-c/src/README.md b/json-c/src/README.md new file mode 100644 index 0000000..3d009b5 --- /dev/null +++ b/json-c/src/README.md @@ -0,0 +1,63 @@ +`json-c` +======== + +Building on Unix with `git`, `gcc` and `autotools` +-------------------------------------------------- + +Home page for json-c: https://github.com/json-c/json-c/wiki + +Caution: do **NOT** use sources from svn.metaparadigm.com, +they are old. + +Prerequisites: + + - `gcc`, `clang`, or another C compiler + - `libtool` + +If you're not using a release tarball, you'll also need: + + - `autoconf` (`autoreconf`) + - `automake` + +Make sure you have a complete `libtool` install, including `libtoolize`. + +`json-c` GitHub repo: https://github.com/json-c/json-c + +```bash +$ git clone https://github.com/json-c/json-c.git +$ cd json-c +$ sh autogen.sh +``` + +followed by + +```bash +$ ./configure +$ make +$ make install +``` + +To build and run the test programs: + +```bash +$ make check +``` + +Linking to `libjson-c` +---------------------- + +If your system has `pkgconfig`, +then you can just add this to your `makefile`: + +```make +CFLAGS += $(shell pkg-config --cflags json-c) +LDFLAGS += $(shell pkg-config --libs json-c) +``` + +Without `pkgconfig`, you would do something like this: + +```make +JSON_C_DIR=/path/to/json_c/install +CFLAGS += -I$(JSON_C_DIR)/include/json-c +LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c +``` diff --git a/json-c/src/configure.ac b/json-c/src/configure.ac new file mode 100644 index 0000000..94b0d0c --- /dev/null +++ b/json-c/src/configure.ac @@ -0,0 +1,114 @@ +AC_PREREQ(2.52) + +# Process this file with autoconf to produce a configure script. +AC_INIT([json-c], 0.12.99, [json-c@googlegroups.com]) + +AM_INIT_AUTOMAKE + +AC_PROG_MAKE_SET + +AC_ARG_ENABLE(rdrand, + AS_HELP_STRING([--enable-rdrand], + [Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms.]), +[if test x$enableval = xyes; then + enable_rdrand=yes + AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRANR Hardware RNG Hash Seed]) +fi]) + +if test "x$enable_rdrand" = "xyes"; then + AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed enabled on supported x86/x64 platforms]) +else + AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed disabled. Use --enable-rdrand to enable]) +fi + +# enable silent build by default +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Checks for programs. + +# Checks for libraries. + +# Checks for header files. +AM_PROG_CC_C_O +AC_CONFIG_HEADER(config.h) +AC_CONFIG_HEADER(json_config.h) +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/cdefs.h] [sys/param.h] stdarg.h locale.h endian.h) +AC_CHECK_HEADER(inttypes.h,[AC_DEFINE([JSON_C_HAVE_INTTYPES_H],[1],[Public define for json_inttypes.h])]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_VPRINTF +AC_FUNC_MEMCMP +AC_FUNC_MALLOC +AC_FUNC_REALLOC +AC_CHECK_FUNCS(strcasecmp strdup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale) +AC_CHECK_DECLS([INFINITY], [], [], [[#include ]]) +AC_CHECK_DECLS([nan], [], [], [[#include ]]) +AC_CHECK_DECLS([isnan], [], [], [[#include ]]) +AC_CHECK_DECLS([isinf], [], [], [[#include ]]) +AC_CHECK_DECLS([_isnan], [], [], [[#include ]]) +AC_CHECK_DECLS([_finite], [], [], [[#include ]]) + +if test "$ac_cv_have_decl_isnan" = "yes" ; then + AC_TRY_LINK([#include ], [float f = 0.0; return isnan(f)], [], [LIBS="$LIBS -lm"]) +fi + +#check if .section.gnu.warning accepts long strings (for __warn_references) +AC_LANG_PUSH([C]) + +AC_MSG_CHECKING([if .gnu.warning accepts long strings]) +AC_LINK_IFELSE([AC_LANG_SOURCE([[ +extern void json_object_get(); +__asm__(".section .gnu.json_object_get,\n\t.ascii \"Please link against libjson-c instead of libjson\"\n\t.text"); + +int main(int c,char* v) {return 0;} +]])], [ + AC_DEFINE(HAS_GNU_WARNING_LONG, 1, [Define if .gnu.warning accepts long strings.]) + AC_MSG_RESULT(yes) +], [ + AC_MSG_RESULT(no) +]) + +AC_LANG_POP([C]) + +AM_PROG_LIBTOOL + +# Check for the -Bsymbolic-functions linker flag +AC_ARG_ENABLE([Bsymbolic], + [AS_HELP_STRING([--disable-Bsymbolic], [Avoid linking with -Bsymbolic-function])], + [], + [enable_Bsymbolic=check]) + +AS_IF([test "x$enable_Bsymbolic" = "xcheck"], + [ + saved_LDFLAGS="${LDFLAGS}" + AC_MSG_CHECKING([for -Bsymbolic-functions linker flag]) + LDFLAGS=-Wl,-Bsymbolic-functions + AC_TRY_LINK([], [int main (void) { return 0; }], + [ + AC_MSG_RESULT([yes]) + enable_Bsymbolic=yes + ], + [ + AC_MSG_RESULT([no]) + enable_Bsymbolic=no + ]) + LDFLAGS="${saved_LDFLAGS}" + ]) + +AS_IF([test "x$enable_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions]) +AC_SUBST(JSON_BSYMBOLIC_LDFLAGS) + +AC_CONFIG_FILES([ +Makefile +json-c.pc +tests/Makefile +json-c-uninstalled.pc +]) + +AC_OUTPUT + diff --git a/json-c/src/json-c-uninstalled.pc.in b/json-c/src/json-c-uninstalled.pc.in new file mode 100644 index 0000000..288f29c --- /dev/null +++ b/json-c/src/json-c-uninstalled.pc.in @@ -0,0 +1,11 @@ +prefix= +exec_prefix= +libdir=@abs_top_builddir@ +includedir=@abs_top_srcdir@ + +Name: json +Description: JSON implementation in C +Version: @VERSION@ +Requires: +Libs: -L@abs_top_builddir@ -ljson-c +Cflags: -I@abs_top_srcdir@ diff --git a/json-c/src/json-c.pc.in b/json-c/src/json-c.pc.in new file mode 100644 index 0000000..54b65e6 --- /dev/null +++ b/json-c/src/json-c.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: json-c +Description: JSON implementation in C +Version: @VERSION@ +Requires: +Libs.private: @LIBS@ +Libs: -L${libdir} -ljson-c +Cflags: -I${includedir}/json-c diff --git a/json-c/src/json-c.vcproj b/json-c/src/json-c.vcproj new file mode 100644 index 0000000..55a579f --- /dev/null +++ b/json-c/src/json-c.vcproj @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/json-c/src/json-c.vcxproj b/json-c/src/json-c.vcxproj new file mode 100644 index 0000000..d9ec767 --- /dev/null +++ b/json-c/src/json-c.vcxproj @@ -0,0 +1,165 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {04D8CDBE-FB3E-4362-87E6-07DC3C0083B2} + jsonc + + + + StaticLibrary + v120 + MultiByte + + + StaticLibrary + v120 + MultiByte + + + StaticLibrary + v120 + MultiByte + + + StaticLibrary + v120 + MultiByte + + + + + + + + + + + + + + + + + + + + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + Level3 + EditAndContinue + CompileAsCpp + + + copy config.h.win32 config.h +copy json_config.h.win32 json_config.h + + + + copy config.h from Windows template instead of calling configure + + + + + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + Level3 + EditAndContinue + CompileAsCpp + + + copy config.h.win32 config.h +copy json_config.h.win32 json_config.h + + + + copy config.h from Windows template instead of calling configure + + + + + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + Level3 + ProgramDatabase + CompileAsCpp + + + copy config.h.win32 config.h +copy json_config.h.win32 json_config.h + + + + copy config.h from Windows template instead of calling configure + + + + + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + Level3 + ProgramDatabase + CompileAsCpp + + + copy config.h.win32 config.h +copy json_config.h.win32 json_config.h + + + + copy config.h from Windows template instead of calling configure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/json-c/src/json-c.vcxproj.filters b/json-c/src/json-c.vcxproj.filters new file mode 100644 index 0000000..b199efb --- /dev/null +++ b/json-c/src/json-c.vcxproj.filters @@ -0,0 +1,90 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + {8c5a59ed-4639-4361-9b7c-ecdcd09b953c} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Documentation + + + + + + + \ No newline at end of file diff --git a/json-c/src/json_c_version.c b/json-c/src/json_c_version.c new file mode 100644 index 0000000..b6ded48 --- /dev/null +++ b/json-c/src/json_c_version.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2012 Eric Haszlakiewicz + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + */ +#include "config.h" + +#include "json_c_version.h" + +const char *json_c_version(void) +{ + return JSON_C_VERSION; +} + +int json_c_version_num(void) +{ + return JSON_C_VERSION_NUM; +} + diff --git a/json-c/src/json_c_version.h b/json-c/src/json_c_version.h new file mode 100644 index 0000000..617e7f2 --- /dev/null +++ b/json-c/src/json_c_version.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2012 Eric Haszlakiewicz + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + */ + +#ifndef _json_c_version_h_ +#define _json_c_version_h_ + +#define JSON_C_MAJOR_VERSION 0 +#define JSON_C_MINOR_VERSION 12 +#define JSON_C_MICRO_VERSION 99 +#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \ + (JSON_C_MINOR_VERSION << 8) | \ + JSON_C_MICRO_VERSION) +#define JSON_C_VERSION "0.12.99" + +const char *json_c_version(void); /* Returns JSON_C_VERSION */ +int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */ + +#endif diff --git a/json-c/src/json_config.h.win32 b/json-c/src/json_config.h.win32 new file mode 100644 index 0000000..00f55bb --- /dev/null +++ b/json-c/src/json_config.h.win32 @@ -0,0 +1,5 @@ + +/* Define to 1 if you have the header file. */ +#if defined(_MSC_VER) && _MSC_VER >= 1800 +#define JSON_C_HAVE_INTTYPES_H 1 +#endif diff --git a/json-c/src/libjson.c b/json-c/src/libjson.c new file mode 100644 index 0000000..1e2bab5 --- /dev/null +++ b/json-c/src/libjson.c @@ -0,0 +1,26 @@ + +/* dummy source file for compatibility purposes */ + +#if defined(HAVE_CDEFS_H) +#include +#endif + +#ifndef __warn_references + +#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG) + +#define __warn_references(sym,msg) \ + __asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text"); + +#else +#define __warn_references(sym,msg) /* nothing */ +#endif + +#endif + +#include "json_object.h" + +__warn_references(json_object_get, "Warning: please link against libjson-c instead of libjson"); + +/* __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") */ diff --git a/json-c/src/math_compat.h b/json-c/src/math_compat.h new file mode 100644 index 0000000..6506bd9 --- /dev/null +++ b/json-c/src/math_compat.h @@ -0,0 +1,31 @@ +#ifndef __math_compat_h +#define __math_compat_h + +/* Define isnan, isinf, infinity and nan on Windows/MSVC */ + +#ifndef HAVE_DECL_ISNAN +# ifdef HAVE_DECL__ISNAN +#include +#define isnan(x) _isnan(x) +# endif +#endif + +#ifndef HAVE_DECL_ISINF +# ifdef HAVE_DECL__FINITE +#include +#define isinf(x) (!_finite(x)) +# endif +#endif + +#ifndef HAVE_DECL_INFINITY +#include +#define INFINITY (DBL_MAX + DBL_MAX) +#define HAVE_DECL_INFINITY +#endif + +#ifndef HAVE_DECL_NAN +#define NAN (INFINITY - INFINITY) +#define HAVE_DECL_NAN +#endif + +#endif diff --git a/json-c/src/random_seed.c b/json-c/src/random_seed.c new file mode 100644 index 0000000..7fe538d --- /dev/null +++ b/json-c/src/random_seed.c @@ -0,0 +1,238 @@ +/* + * random_seed.c + * + * Copyright (c) 2013 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include +#include "config.h" +#include "random_seed.h" + +#define DEBUG_SEED(s) + + +#if defined ENABLE_RDRAND + +/* cpuid */ + +#if defined __GNUC__ && (defined __i386__ || defined __x86_64__) +#define HAS_X86_CPUID 1 + +static void do_cpuid(int regs[], int h) +{ + __asm__ __volatile__( +#if defined __x86_64__ + "pushq %%rbx;\n" +#else + "pushl %%ebx;\n" +#endif + "cpuid;\n" +#if defined __x86_64__ + "popq %%rbx;\n" +#else + "popl %%ebx;\n" +#endif + : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) + : "a"(h)); +} + +#elif defined _MSC_VER + +#define HAS_X86_CPUID 1 +#define do_cpuid __cpuid + +#endif + +/* has_rdrand */ + +#if HAS_X86_CPUID + +static int has_rdrand() +{ + // CPUID.01H:ECX.RDRAND[bit 30] == 1 + int regs[4]; + do_cpuid(regs, 1); + return (regs[2] & (1 << 30)) != 0; +} + +#endif + +/* get_rdrand_seed - GCC x86 and X64 */ + +#if defined __GNUC__ && (defined __i386__ || defined __x86_64__) + +#define HAVE_RDRAND 1 + +static int get_rdrand_seed() +{ + DEBUG_SEED("get_rdrand_seed"); + int _eax; + // rdrand eax + __asm__ __volatile__("1: .byte 0x0F\n" + " .byte 0xC7\n" + " .byte 0xF0\n" + " jnc 1b;\n" + : "=a" (_eax)); + return _eax; +} + +#endif + +#if defined _MSC_VER + +#if _MSC_VER >= 1700 +#define HAVE_RDRAND 1 + +/* get_rdrand_seed - Visual Studio 2012 and above */ + +static int get_rdrand_seed() +{ + DEBUG_SEED("get_rdrand_seed"); + int r; + while (_rdrand32_step(&r) == 0); + return r; +} + +#elif defined _M_IX86 +#define HAVE_RDRAND 1 + +/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */ + +static int get_rdrand_seed() +{ + DEBUG_SEED("get_rdrand_seed"); + int _eax; +retry: + // rdrand eax + __asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0 + __asm jnc retry + __asm mov _eax, eax + return _eax; +} + +#endif +#endif + +#endif /* defined ENABLE_RDRAND */ + + +/* has_dev_urandom */ + +#if defined (__APPLE__) || defined(__unix__) || defined(__linux__) + +#include +#include +#include +#include +#include +#include + +#define HAVE_DEV_RANDOM 1 + +static const char *dev_random_file = "/dev/urandom"; + +static int has_dev_urandom() +{ + struct stat buf; + if (stat(dev_random_file, &buf)) { + return 0; + } + return ((buf.st_mode & S_IFCHR) != 0); +} + + +/* get_dev_random_seed */ + +static int get_dev_random_seed() +{ + DEBUG_SEED("get_dev_random_seed"); + + int fd = open(dev_random_file, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno)); + exit(1); + } + + int r; + ssize_t nread = read(fd, &r, sizeof(r)); + if (nread != sizeof(r)) { + fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno)); + exit(1); + } + + close(fd); + return r; +} + +#endif + + +/* get_cryptgenrandom_seed */ + +#ifdef WIN32 + +#define HAVE_CRYPTGENRANDOM 1 + +#include +#include +#ifndef __GNUC__ +#pragma comment(lib, "advapi32.lib") +#endif + +static int get_cryptgenrandom_seed() +{ + DEBUG_SEED("get_cryptgenrandom_seed"); + + HCRYPTPROV hProvider = 0; + int r; + + if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { + fprintf(stderr, "error CryptAcquireContextW"); + exit(1); + } + + if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) { + fprintf(stderr, "error CryptGenRandom"); + exit(1); + } + + CryptReleaseContext(hProvider, 0); + + return r; +} + +#endif + + +/* get_time_seed */ + +#include + +static int get_time_seed() +{ + DEBUG_SEED("get_time_seed"); + + return (int)time(NULL) * 433494437; +} + + +/* json_c_get_random_seed */ + +int json_c_get_random_seed() +{ +#if HAVE_RDRAND + if (has_rdrand()) return get_rdrand_seed(); +#endif +#if HAVE_DEV_RANDOM + if (has_dev_urandom()) return get_dev_random_seed(); +#endif +#if HAVE_CRYPTGENRANDOM + return get_cryptgenrandom_seed(); +#endif + return get_time_seed(); +} diff --git a/json-c/src/random_seed.h b/json-c/src/random_seed.h new file mode 100644 index 0000000..6d1e268 --- /dev/null +++ b/json-c/src/random_seed.h @@ -0,0 +1,25 @@ +/* + * random_seed.h + * + * Copyright (c) 2013 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef seed_h +#define seed_h + +#ifdef __cplusplus +extern "C" { +#endif + +extern int json_c_get_random_seed(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/tests/Makefile.am b/json-c/src/tests/Makefile.am new file mode 100644 index 0000000..ea4b051 --- /dev/null +++ b/json-c/src/tests/Makefile.am @@ -0,0 +1,41 @@ + +include ../Makefile.am.inc +LDADD= $(LIBJSON_LA) + +LIBJSON_LA=$(top_builddir)/libjson-c.la + +TESTS= +TESTS+= test1.test +TESTS+= test2.test +TESTS+= test4.test +TESTS+= testReplaceExisting.test +TESTS+= test_parse_int64.test +TESTS+= test_null.test +TESTS+= test_cast.test +TESTS+= test_parse.test +TESTS+= test_locale.test +TESTS+= test_charcase.test +TESTS+= test_printbuf.test +TESTS+= test_set_serializer.test + +check_PROGRAMS= +check_PROGRAMS += $(TESTS:.test=) + +# Note: handled by test1.test +check_PROGRAMS += test1Formatted +test1Formatted_SOURCES = test1.c parse_flags.c +test1Formatted_CPPFLAGS = -DTEST_FORMATTED + +# Note: handled by test2.test +check_PROGRAMS += test2Formatted +test2Formatted_SOURCES = test2.c parse_flags.c +test2Formatted_CPPFLAGS = -DTEST_FORMATTED + +EXTRA_DIST= +EXTRA_DIST += $(TESTS) + +testsubdir=testSubDir +TESTS_ENVIRONMENT = top_builddir=$(top_builddir) + +distclean-local: + -rm -rf $(testsubdir) diff --git a/json-c/src/tests/parse_flags.c b/json-c/src/tests/parse_flags.c new file mode 100644 index 0000000..06910e6 --- /dev/null +++ b/json-c/src/tests/parse_flags.c @@ -0,0 +1,50 @@ +#include "config.h" + +#include +#include + +#include "json.h" +#include "parse_flags.h" + +#if !defined(HAVE_STRCASECMP) && defined(_MSC_VER) +# define strcasecmp _stricmp +#elif !defined(HAVE_STRCASECMP) +# error You do not have strcasecmp on your system. +#endif /* HAVE_STRNCASECMP */ + +static struct { + const char *arg; + int flag; +} format_args[] = { + { "plain", JSON_C_TO_STRING_PLAIN }, + { "spaced", JSON_C_TO_STRING_SPACED }, + { "pretty", JSON_C_TO_STRING_PRETTY }, +}; + +#ifndef NELEM +#define NELEM(x) (sizeof(x) / sizeof(&x[0])) +#endif + +int parse_flags(int argc, char **argv) +{ + int arg_idx; + int sflags = 0; + for (arg_idx = 1; arg_idx < argc ; arg_idx++) + { + int jj; + for (jj = 0; jj < (int)NELEM(format_args); jj++) + { + if (strcasecmp(argv[arg_idx], format_args[jj].arg) == 0) + { + sflags |= format_args[jj].flag; + break; + } + } + if (jj == NELEM(format_args)) + { + printf("Unknown arg: %s\n", argv[arg_idx]); + exit(1); + } + } + return sflags; +} diff --git a/json-c/src/tests/parse_flags.h b/json-c/src/tests/parse_flags.h new file mode 100644 index 0000000..dd5149d --- /dev/null +++ b/json-c/src/tests/parse_flags.h @@ -0,0 +1,4 @@ +#ifndef __parse_flags_h +#define __parse_flags_h +int parse_flags(int argc, char **argv); +#endif diff --git a/json-c/src/tests/test-defs.sh b/json-c/src/tests/test-defs.sh new file mode 100644 index 0000000..062170a --- /dev/null +++ b/json-c/src/tests/test-defs.sh @@ -0,0 +1,128 @@ +#!/bin/sh + +# Make sure srcdir is an absolute path. Supply the variable +# if it does not exist. We want to be able to run the tests +# stand-alone!! +# +srcdir=${srcdir-.} +if test ! -d $srcdir ; then + echo "test-defs.sh: installation error" 1>&2 + exit 1 +fi + +# Use absolute paths +case "$srcdir" in + /* | [A-Za-z]:\\*) ;; + *) srcdir=`\cd $srcdir && pwd` ;; +esac + +case "$top_builddir" in + /* | [A-Za-z]:\\*) ;; + *) top_builddir=`\cd ${top_builddir-..} && pwd` ;; +esac + +top_builddir=${top_builddir}/tests + +progname=`echo "$0" | sed 's,^.*/,,'` +testname=`echo "$progname" | sed 's,-.*$,,'` +testsubdir=${testsubdir-testSubDir} +testsubdir=${testsubdir}/${progname} + +# User can set VERBOSE to cause output redirection +case "$VERBOSE" in +[Nn]|[Nn][Oo]|0|"") + VERBOSE=0 + exec > /dev/null + ;; +[Yy]|[Yy][Ee][Ss]) + VERBOSE=1 + ;; +esac + +rm -rf "$testsubdir" > /dev/null 2>&1 +mkdir -p "$testsubdir" +CURDIR=$(pwd) +cd "$testsubdir" \ + || { echo "Cannot make or change into $testsubdir"; exit 1; } + +echo "=== Running test $progname" + +CMP="${CMP-cmp}" + +use_valgrind=${USE_VALGRIND-1} +valgrind_path=$(which valgrind 2> /dev/null) +if [ -z "${valgrind_path}" -o ! -x "${valgrind_path}" ] ; then + use_valgrind=0 +fi + +# +# This is a common function to check the results of a test program +# that is intended to generate consistent output across runs. +# +# ${top_builddir} must be set to the top level build directory. +# +# Output will be written to the current directory. +# +# It must be passed the name of the test command to run, which must be present +# in the ${top_builddir} directory. +# +# It will compare the output of running that against .expected +# +run_output_test() +{ + if [ "$1" = "-o" ] ; then + TEST_OUTPUT="$2" + shift + shift + fi + TEST_COMMAND="$1" + shift + if [ -z "${TEST_OUTPUT}" ] ; then + TEST_OUTPUT=${TEST_COMMAND} + fi + + REDIR_OUTPUT="> \"${TEST_OUTPUT}.out\"" + if [ $VERBOSE -gt 1 ] ; then + REDIR_OUTPUT="| tee \"${TEST_OUTPUT}.out\"" + fi + + if [ $use_valgrind -eq 1 ] ; then + eval valgrind --tool=memcheck \ + --trace-children=yes \ + --demangle=yes \ + --log-file="${TEST_OUTPUT}.vg.out" \ + --leak-check=full \ + --show-reachable=yes \ + --run-libc-freeres=yes \ + "\"${top_builddir}/${TEST_COMMAND}\"" \"\$@\" ${REDIR_OUTPUT} + err=$? + + else + eval "\"${top_builddir}/${TEST_COMMAND}"\" \"\$@\" ${REDIR_OUTPUT} + err=$? + fi + + if [ $err -ne 0 ] ; then + echo "ERROR: \"${TEST_COMMAND} $@\" exited with non-zero exit status: $err" 1>&2 + fi + + if [ $use_valgrind -eq 1 ] ; then + if ! tail -1 "${TEST_OUTPUT}.vg.out" | grep -q "ERROR SUMMARY: 0 errors" ; then + echo "ERROR: valgrind found errors during execution:" 1>&2 + cat "${TEST_OUTPUT}.vg.out" + err=1 + fi + fi + + if ! "$CMP" -s "${top_builddir}/${TEST_OUTPUT}.expected" "${TEST_OUTPUT}.out" ; then + echo "ERROR: \"${TEST_COMMAND} $@\" (${TEST_OUTPUT}) failed (set VERBOSE=1 to see full output):" 1>&2 + (cd "${CURDIR}" ; set -x ; diff "${top_builddir}/${TEST_OUTPUT}.expected" "$testsubdir/${TEST_OUTPUT}.out") + echo "cp \"$testsubdir/${TEST_OUTPUT}.out\" \"${top_builddir}/${TEST_OUTPUT}.expected\"" 1>&2 + + err=1 + fi + + return $err +} + + diff --git a/json-c/src/tests/test1.c b/json-c/src/tests/test1.c new file mode 100644 index 0000000..8136227 --- /dev/null +++ b/json-c/src/tests/test1.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include + +#include "json.h" +#include "parse_flags.h" + +static int sort_fn (const void *j1, const void *j2) +{ + json_object * const *jso1, * const *jso2; + int i1, i2; + + jso1 = (json_object* const*)j1; + jso2 = (json_object* const*)j2; + if (!*jso1 && !*jso2) + return 0; + if (!*jso1) + return -1; + if (!*jso2) + return 1; + + i1 = json_object_get_int(*jso1); + i2 = json_object_get_int(*jso2); + + return i1 - i2; +} + +#ifdef TEST_FORMATTED +#define json_object_to_json_string(obj) json_object_to_json_string_ext(obj,sflags) +#else +/* no special define */ +#endif + +int main(int argc, char **argv) +{ + json_object *my_string, *my_int, *my_object, *my_array; + int i; +#ifdef TEST_FORMATTED + int sflags = 0; +#endif + + MC_SET_DEBUG(1); + +#ifdef TEST_FORMATTED + sflags = parse_flags(argc, argv); +#endif + + my_string = json_object_new_string("\t"); + printf("my_string=%s\n", json_object_get_string(my_string)); + printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); + json_object_put(my_string); + + my_string = json_object_new_string("\\"); + printf("my_string=%s\n", json_object_get_string(my_string)); + printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); + json_object_put(my_string); + + my_string = json_object_new_string("foo"); + printf("my_string=%s\n", json_object_get_string(my_string)); + printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); + + my_int = json_object_new_int(9); + printf("my_int=%d\n", json_object_get_int(my_int)); + printf("my_int.to_string()=%s\n", json_object_to_json_string(my_int)); + + my_array = json_object_new_array(); + json_object_array_add(my_array, json_object_new_int(1)); + json_object_array_add(my_array, json_object_new_int(2)); + json_object_array_add(my_array, json_object_new_int(3)); + json_object_array_put_idx(my_array, 4, json_object_new_int(5)); + printf("my_array=\n"); + for(i=0; i < json_object_array_length(my_array); i++) + { + json_object *obj = json_object_array_get_idx(my_array, i); + printf("\t[%d]=%s\n", i, json_object_to_json_string(obj)); + } + printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array)); + + json_object_put(my_array); + + my_array = json_object_new_array(); + json_object_array_add(my_array, json_object_new_int(3)); + json_object_array_add(my_array, json_object_new_int(1)); + json_object_array_add(my_array, json_object_new_int(2)); + json_object_array_put_idx(my_array, 4, json_object_new_int(0)); + printf("my_array=\n"); + for(i=0; i < json_object_array_length(my_array); i++) + { + json_object *obj = json_object_array_get_idx(my_array, i); + printf("\t[%d]=%s\n", i, json_object_to_json_string(obj)); + } + printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array)); + json_object_array_sort(my_array, sort_fn); + printf("my_array=\n"); + for(i=0; i < json_object_array_length(my_array); i++) + { + json_object *obj = json_object_array_get_idx(my_array, i); + printf("\t[%d]=%s\n", i, json_object_to_json_string(obj)); + } + printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array)); + + my_object = json_object_new_object(); + json_object_object_add(my_object, "abc", json_object_new_int(12)); + json_object_object_add(my_object, "foo", json_object_new_string("bar")); + json_object_object_add(my_object, "bool0", json_object_new_boolean(0)); + json_object_object_add(my_object, "bool1", json_object_new_boolean(1)); + json_object_object_add(my_object, "baz", json_object_new_string("bang")); + + json_object *baz_obj = json_object_new_string("fark"); + json_object_get(baz_obj); + json_object_object_add(my_object, "baz", baz_obj); + json_object_object_del(my_object, "baz"); + + /* baz_obj should still be valid */ + printf("baz_obj.to_string()=%s\n", json_object_to_json_string(baz_obj)); + json_object_put(baz_obj); + + /*json_object_object_add(my_object, "arr", my_array);*/ + printf("my_object=\n"); + json_object_object_foreach(my_object, key, val) + { + printf("\t%s: %s\n", key, json_object_to_json_string(val)); + } + printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object)); + + json_object_put(my_string); + json_object_put(my_int); + json_object_put(my_object); + json_object_put(my_array); + + return 0; +} diff --git a/json-c/src/tests/test1.expected b/json-c/src/tests/test1.expected new file mode 100644 index 0000000..4aaf6cc --- /dev/null +++ b/json-c/src/tests/test1.expected @@ -0,0 +1,36 @@ +my_string= +my_string.to_string()="\t" +my_string=\ +my_string.to_string()="\\" +my_string=foo +my_string.to_string()="foo" +my_int=9 +my_int.to_string()=9 +my_array= + [0]=1 + [1]=2 + [2]=3 + [3]=null + [4]=5 +my_array.to_string()=[ 1, 2, 3, null, 5 ] +my_array= + [0]=3 + [1]=1 + [2]=2 + [3]=null + [4]=0 +my_array.to_string()=[ 3, 1, 2, null, 0 ] +my_array= + [0]=null + [1]=0 + [2]=1 + [3]=2 + [4]=3 +my_array.to_string()=[ null, 0, 1, 2, 3 ] +baz_obj.to_string()="fark" +my_object= + abc: 12 + foo: "bar" + bool0: false + bool1: true +my_object.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true } diff --git a/json-c/src/tests/test1.test b/json-c/src/tests/test1.test new file mode 100644 index 0000000..bf9d75e --- /dev/null +++ b/json-c/src/tests/test1.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test1 +_err=$? + +for flag in plain spaced pretty ; do + run_output_test -o test1Formatted_${flag} test1Formatted ${flag} + _err2=$? + if [ $_err -eq 0 ] ; then + _err=$_err2 + fi +done + +exit $_err diff --git a/json-c/src/tests/test1Formatted_plain.expected b/json-c/src/tests/test1Formatted_plain.expected new file mode 100644 index 0000000..843f55a --- /dev/null +++ b/json-c/src/tests/test1Formatted_plain.expected @@ -0,0 +1,36 @@ +my_string= +my_string.to_string()="\t" +my_string=\ +my_string.to_string()="\\" +my_string=foo +my_string.to_string()="foo" +my_int=9 +my_int.to_string()=9 +my_array= + [0]=1 + [1]=2 + [2]=3 + [3]=null + [4]=5 +my_array.to_string()=[1,2,3,null,5] +my_array= + [0]=3 + [1]=1 + [2]=2 + [3]=null + [4]=0 +my_array.to_string()=[3,1,2,null,0] +my_array= + [0]=null + [1]=0 + [2]=1 + [3]=2 + [4]=3 +my_array.to_string()=[null,0,1,2,3] +baz_obj.to_string()="fark" +my_object= + abc: 12 + foo: "bar" + bool0: false + bool1: true +my_object.to_string()={"abc":12,"foo":"bar","bool0":false,"bool1":true} diff --git a/json-c/src/tests/test1Formatted_pretty.expected b/json-c/src/tests/test1Formatted_pretty.expected new file mode 100644 index 0000000..ca4ff67 --- /dev/null +++ b/json-c/src/tests/test1Formatted_pretty.expected @@ -0,0 +1,59 @@ +my_string= +my_string.to_string()="\t" +my_string=\ +my_string.to_string()="\\" +my_string=foo +my_string.to_string()="foo" +my_int=9 +my_int.to_string()=9 +my_array= + [0]=1 + [1]=2 + [2]=3 + [3]=null + [4]=5 +my_array.to_string()=[ + 1, + 2, + 3, + null, + 5 +] +my_array= + [0]=3 + [1]=1 + [2]=2 + [3]=null + [4]=0 +my_array.to_string()=[ + 3, + 1, + 2, + null, + 0 +] +my_array= + [0]=null + [1]=0 + [2]=1 + [3]=2 + [4]=3 +my_array.to_string()=[ + null, + 0, + 1, + 2, + 3 +] +baz_obj.to_string()="fark" +my_object= + abc: 12 + foo: "bar" + bool0: false + bool1: true +my_object.to_string()={ + "abc":12, + "foo":"bar", + "bool0":false, + "bool1":true +} diff --git a/json-c/src/tests/test1Formatted_spaced.expected b/json-c/src/tests/test1Formatted_spaced.expected new file mode 100644 index 0000000..4aaf6cc --- /dev/null +++ b/json-c/src/tests/test1Formatted_spaced.expected @@ -0,0 +1,36 @@ +my_string= +my_string.to_string()="\t" +my_string=\ +my_string.to_string()="\\" +my_string=foo +my_string.to_string()="foo" +my_int=9 +my_int.to_string()=9 +my_array= + [0]=1 + [1]=2 + [2]=3 + [3]=null + [4]=5 +my_array.to_string()=[ 1, 2, 3, null, 5 ] +my_array= + [0]=3 + [1]=1 + [2]=2 + [3]=null + [4]=0 +my_array.to_string()=[ 3, 1, 2, null, 0 ] +my_array= + [0]=null + [1]=0 + [2]=1 + [3]=2 + [4]=3 +my_array.to_string()=[ null, 0, 1, 2, 3 ] +baz_obj.to_string()="fark" +my_object= + abc: 12 + foo: "bar" + bool0: false + bool1: true +my_object.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true } diff --git a/json-c/src/tests/test2.c b/json-c/src/tests/test2.c new file mode 100644 index 0000000..9b30c62 --- /dev/null +++ b/json-c/src/tests/test2.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#include "json.h" +#include "parse_flags.h" + +#ifdef TEST_FORMATTED +#define json_object_to_json_string(obj) json_object_to_json_string_ext(obj,sflags) +#else +/* no special define */ +#endif + + +int main(int argc, char **argv) +{ + json_object *new_obj; +#ifdef TEST_FORMATTED + int sflags = 0; +#endif + + MC_SET_DEBUG(1); + +#ifdef TEST_FORMATTED + sflags = parse_flags(argc, argv); +#endif + + new_obj = json_tokener_parse("/* more difficult test case */ { \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", \"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + return 0; +} diff --git a/json-c/src/tests/test2.expected b/json-c/src/tests/test2.expected new file mode 100644 index 0000000..ac404e0 --- /dev/null +++ b/json-c/src/tests/test2.expected @@ -0,0 +1 @@ +new_obj.to_string()={ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": [ { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": [ "GML", "XML", "markup" ] } ] } } } diff --git a/json-c/src/tests/test2.test b/json-c/src/tests/test2.test new file mode 100644 index 0000000..0b5fc87 --- /dev/null +++ b/json-c/src/tests/test2.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test2 +_err=$? + +for flag in plain spaced pretty ; do + run_output_test -o test2Formatted_${flag} test2Formatted ${flag} + _err2=$? + if [ $_err -eq 0 ] ; then + _err=$_err2 + fi +done + +exit $_err diff --git a/json-c/src/tests/test2Formatted_plain.expected b/json-c/src/tests/test2Formatted_plain.expected new file mode 100644 index 0000000..8b2053d --- /dev/null +++ b/json-c/src/tests/test2Formatted_plain.expected @@ -0,0 +1 @@ +new_obj.to_string()={"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":[{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML","markup"]}]}}} diff --git a/json-c/src/tests/test2Formatted_pretty.expected b/json-c/src/tests/test2Formatted_pretty.expected new file mode 100644 index 0000000..c311691 --- /dev/null +++ b/json-c/src/tests/test2Formatted_pretty.expected @@ -0,0 +1,23 @@ +new_obj.to_string()={ + "glossary":{ + "title":"example glossary", + "GlossDiv":{ + "title":"S", + "GlossList":[ + { + "ID":"SGML", + "SortAs":"SGML", + "GlossTerm":"Standard Generalized Markup Language", + "Acronym":"SGML", + "Abbrev":"ISO 8879:1986", + "GlossDef":"A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso":[ + "GML", + "XML", + "markup" + ] + } + ] + } + } +} diff --git a/json-c/src/tests/test2Formatted_spaced.expected b/json-c/src/tests/test2Formatted_spaced.expected new file mode 100644 index 0000000..ac404e0 --- /dev/null +++ b/json-c/src/tests/test2Formatted_spaced.expected @@ -0,0 +1 @@ +new_obj.to_string()={ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": [ { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": [ "GML", "XML", "markup" ] } ] } } } diff --git a/json-c/src/tests/test4.c b/json-c/src/tests/test4.c new file mode 100644 index 0000000..99331bb --- /dev/null +++ b/json-c/src/tests/test4.c @@ -0,0 +1,53 @@ +/* + * gcc -o utf8 utf8.c -I/home/y/include -L./.libs -ljson + */ + +#include +#include +#include "config.h" + +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" + +void print_hex( const char* s) +{ + const char *iter = s; + unsigned char ch; + while ((ch = *iter++) != 0) + { + if( ',' != ch) + printf("%x ", ch); + else + printf( ","); + } + printf("\n"); +} + +int main() +{ + const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\""; + const char *expected = "\xF0\xA0\x84\xA6,\xF0\xA0\x84\xA7,\xF0\x90\x84\xA6,\xF0\x90\x84\xA7"; + struct json_object *parse_result = json_tokener_parse((char*)input); + const char *unjson = json_object_get_string(parse_result); + + printf("input: %s\n", input); + + int strings_match = !strcmp( expected, unjson); + int retval = 0; + if (strings_match) + { + printf("JSON parse result is correct: %s\n", unjson); + printf("PASS\n"); + } else { + printf("JSON parse result doesn't match expected string\n"); + printf("expected string bytes: "); + print_hex( expected); + printf("parsed string bytes: "); + print_hex( unjson); + printf("FAIL\n"); + retval = 1; + } + json_object_put(parse_result); + return retval; +} diff --git a/json-c/src/tests/test4.expected b/json-c/src/tests/test4.expected new file mode 100644 index 0000000..932761d --- /dev/null +++ b/json-c/src/tests/test4.expected @@ -0,0 +1,3 @@ +input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27" +JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧 +PASS diff --git a/json-c/src/tests/test4.test b/json-c/src/tests/test4.test new file mode 100644 index 0000000..4e8147e --- /dev/null +++ b/json-c/src/tests/test4.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test4 +exit $? diff --git a/json-c/src/tests/testReplaceExisting.c b/json-c/src/tests/testReplaceExisting.c new file mode 100644 index 0000000..0534cf9 --- /dev/null +++ b/json-c/src/tests/testReplaceExisting.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include "json.h" + +int main(int argc, char **argv) +{ + MC_SET_DEBUG(1); + + /* + * Check that replacing an existing object keeps the key valid, + * and that it keeps the order the same. + */ + json_object *my_object = json_object_new_object(); + json_object_object_add(my_object, "foo1", json_object_new_string("bar1")); + json_object_object_add(my_object, "foo2", json_object_new_string("bar2")); + json_object_object_add(my_object, "deleteme", json_object_new_string("bar2")); + json_object_object_add(my_object, "foo3", json_object_new_string("bar3")); + + printf("==== delete-in-loop test starting ====\n"); + + int orig_count = 0; + json_object_object_foreach(my_object, key0, val0) + { + printf("Key at index %d is [%s]", orig_count, key0); + if (strcmp(key0, "deleteme") == 0) + { + json_object_object_del(my_object, key0); + printf(" (deleted)\n"); + } + else + printf(" (kept)\n"); + orig_count++; + } + + printf("==== replace-value first loop starting ====\n"); + + const char *original_key = NULL; + orig_count = 0; + json_object_object_foreach(my_object, key, val) + { + printf("Key at index %d is [%s]\n", orig_count, key); + orig_count++; + if (strcmp(key, "foo2") != 0) + continue; + printf("replacing value for key [%s]\n", key); + original_key = key; + json_object_object_add(my_object, key, json_object_new_string("zzz")); + } + + printf("==== second loop starting ====\n"); + + int new_count = 0; + int retval = 0; + json_object_object_foreach(my_object, key2, val2) + { + printf("Key at index %d is [%s]\n", new_count, key2); + new_count++; + if (strcmp(key2, "foo2") != 0) + continue; + printf("pointer for key [%s] does %smatch\n", key2, + (key2 == original_key) ? "" : "NOT "); + if (key2 != original_key) + retval = 1; + } + if (new_count != orig_count) + { + printf("mismatch between original count (%d) and new count (%d)\n", + orig_count, new_count); + retval = 1; + } + + json_object_put( my_object ); + + return retval; +} diff --git a/json-c/src/tests/testReplaceExisting.expected b/json-c/src/tests/testReplaceExisting.expected new file mode 100644 index 0000000..2b6e532 --- /dev/null +++ b/json-c/src/tests/testReplaceExisting.expected @@ -0,0 +1,15 @@ +==== delete-in-loop test starting ==== +Key at index 0 is [foo1] (kept) +Key at index 1 is [foo2] (kept) +Key at index 2 is [deleteme] (deleted) +Key at index 3 is [foo3] (kept) +==== replace-value first loop starting ==== +Key at index 0 is [foo1] +Key at index 1 is [foo2] +replacing value for key [foo2] +Key at index 2 is [foo3] +==== second loop starting ==== +Key at index 0 is [foo1] +Key at index 1 is [foo2] +pointer for key [foo2] does match +Key at index 2 is [foo3] diff --git a/json-c/src/tests/testReplaceExisting.test b/json-c/src/tests/testReplaceExisting.test new file mode 100644 index 0000000..8ac7674 --- /dev/null +++ b/json-c/src/tests/testReplaceExisting.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test testReplaceExisting +exit $? diff --git a/json-c/src/tests/test_cast.c b/json-c/src/tests/test_cast.c new file mode 100644 index 0000000..edbb348 --- /dev/null +++ b/json-c/src/tests/test_cast.c @@ -0,0 +1,111 @@ +/* + * Tests if casting within the json_object_get_* functions work correctly. + * Also checks the json_object_get_type and json_object_is_type functions. + */ + +#include +#include +#include +#include "config.h" + +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" +#include "json_util.h" + +static void getit(struct json_object *new_obj, const char *field); +static void checktype_header(void); +static void checktype(struct json_object *new_obj, const char *field); + +int main(int argc, char **argv) +{ + const char *input = "{\n\ + \"string_of_digits\": \"123\",\n\ + \"regular_number\": 222,\n\ + \"decimal_number\": 99.55,\n\ + \"boolean_true\": true,\n\ + \"boolean_false\": false,\n\ + \"big_number\": 2147483649,\n\ + \"a_null\": null,\n\ + }"; + /* Note: 2147483649 = INT_MAX + 2 */ + + struct json_object *new_obj; + + new_obj = json_tokener_parse(input); + printf("Parsed input: %s\n", input); + printf("Result is %s\n", (new_obj == NULL) ? "NULL (error!)" : "not NULL"); + if (!new_obj) + return 1; // oops, we failed. + + getit(new_obj, "string_of_digits"); + getit(new_obj, "regular_number"); + getit(new_obj, "decimal_number"); + getit(new_obj, "boolean_true"); + getit(new_obj, "boolean_false"); + getit(new_obj, "big_number"); + getit(new_obj, "a_null"); + + // Now check the behaviour of the json_object_is_type() function. + printf("\n================================\n"); + checktype_header(); + checktype(new_obj, NULL); + checktype(new_obj, "string_of_digits"); + checktype(new_obj, "regular_number"); + checktype(new_obj, "decimal_number"); + checktype(new_obj, "boolean_true"); + checktype(new_obj, "boolean_false"); + checktype(new_obj, "big_number"); + checktype(new_obj, "a_null"); + + json_object_put(new_obj); + + return 0; +} + +static void getit(struct json_object *new_obj, const char *field) +{ + struct json_object *o = NULL; + if (!json_object_object_get_ex(new_obj, field, &o)) + printf("Field %s does not exist\n", field); + + enum json_type o_type = json_object_get_type(o); + printf("new_obj.%s json_object_get_type()=%s\n", field, + json_type_to_name(o_type)); + printf("new_obj.%s json_object_get_int()=%d\n", field, + json_object_get_int(o)); + printf("new_obj.%s json_object_get_int64()=%" PRId64 "\n", field, + json_object_get_int64(o)); + printf("new_obj.%s json_object_get_boolean()=%d\n", field, + json_object_get_boolean(o)); + printf("new_obj.%s json_object_get_double()=%f\n", field, + json_object_get_double(o)); +} + +static void checktype_header() +{ + printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s\n", + json_type_to_name(json_type_null), + json_type_to_name(json_type_boolean), + json_type_to_name(json_type_double), + json_type_to_name(json_type_int), + json_type_to_name(json_type_object), + json_type_to_name(json_type_array), + json_type_to_name(json_type_string)); +} +static void checktype(struct json_object *new_obj, const char *field) +{ + struct json_object *o = new_obj; + if (field && !json_object_object_get_ex(new_obj, field, &o)) + printf("Field %s does not exist\n", field); + + printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d\n", + field ? "." : " ", field ? field : "", + json_object_is_type(o, json_type_null), + json_object_is_type(o, json_type_boolean), + json_object_is_type(o, json_type_double), + json_object_is_type(o, json_type_int), + json_object_is_type(o, json_type_object), + json_object_is_type(o, json_type_array), + json_object_is_type(o, json_type_string)); +} diff --git a/json-c/src/tests/test_cast.expected b/json-c/src/tests/test_cast.expected new file mode 100644 index 0000000..abf8924 --- /dev/null +++ b/json-c/src/tests/test_cast.expected @@ -0,0 +1,56 @@ +Parsed input: { + "string_of_digits": "123", + "regular_number": 222, + "decimal_number": 99.55, + "boolean_true": true, + "boolean_false": false, + "big_number": 2147483649, + "a_null": null, + } +Result is not NULL +new_obj.string_of_digits json_object_get_type()=string +new_obj.string_of_digits json_object_get_int()=123 +new_obj.string_of_digits json_object_get_int64()=123 +new_obj.string_of_digits json_object_get_boolean()=1 +new_obj.string_of_digits json_object_get_double()=123.000000 +new_obj.regular_number json_object_get_type()=int +new_obj.regular_number json_object_get_int()=222 +new_obj.regular_number json_object_get_int64()=222 +new_obj.regular_number json_object_get_boolean()=1 +new_obj.regular_number json_object_get_double()=222.000000 +new_obj.decimal_number json_object_get_type()=double +new_obj.decimal_number json_object_get_int()=99 +new_obj.decimal_number json_object_get_int64()=99 +new_obj.decimal_number json_object_get_boolean()=1 +new_obj.decimal_number json_object_get_double()=99.550000 +new_obj.boolean_true json_object_get_type()=boolean +new_obj.boolean_true json_object_get_int()=1 +new_obj.boolean_true json_object_get_int64()=1 +new_obj.boolean_true json_object_get_boolean()=1 +new_obj.boolean_true json_object_get_double()=1.000000 +new_obj.boolean_false json_object_get_type()=boolean +new_obj.boolean_false json_object_get_int()=0 +new_obj.boolean_false json_object_get_int64()=0 +new_obj.boolean_false json_object_get_boolean()=0 +new_obj.boolean_false json_object_get_double()=0.000000 +new_obj.big_number json_object_get_type()=int +new_obj.big_number json_object_get_int()=2147483647 +new_obj.big_number json_object_get_int64()=2147483649 +new_obj.big_number json_object_get_boolean()=1 +new_obj.big_number json_object_get_double()=2147483649.000000 +new_obj.a_null json_object_get_type()=null +new_obj.a_null json_object_get_int()=0 +new_obj.a_null json_object_get_int64()=0 +new_obj.a_null json_object_get_boolean()=0 +new_obj.a_null json_object_get_double()=0.000000 + +================================ +json_object_is_type: null,boolean,double,int,object,array,string +new_obj : 0,0,0,0,1,0,0 +new_obj.string_of_digits : 0,0,0,0,0,0,1 +new_obj.regular_number : 0,0,0,1,0,0,0 +new_obj.decimal_number : 0,0,1,0,0,0,0 +new_obj.boolean_true : 0,1,0,0,0,0,0 +new_obj.boolean_false : 0,1,0,0,0,0,0 +new_obj.big_number : 0,0,0,1,0,0,0 +new_obj.a_null : 1,0,0,0,0,0,0 diff --git a/json-c/src/tests/test_cast.test b/json-c/src/tests/test_cast.test new file mode 100644 index 0000000..df165f8 --- /dev/null +++ b/json-c/src/tests/test_cast.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_cast +exit $? diff --git a/json-c/src/tests/test_charcase.c b/json-c/src/tests/test_charcase.c new file mode 100644 index 0000000..9179467 --- /dev/null +++ b/json-c/src/tests/test_charcase.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +#include "json.h" +#include "json_tokener.h" + +static void test_case_parse(void); + +int main(int argc, char **argv) +{ + MC_SET_DEBUG(1); + + test_case_parse(); +} + +/* make sure only lowercase forms are parsed in strict mode */ +static void test_case_parse() +{ + struct json_tokener *tok; + json_object *new_obj; + + tok = json_tokener_new(); + json_tokener_set_flags(tok, JSON_TOKENER_STRICT); + + new_obj = json_tokener_parse_ex(tok, "True", 4); + assert (new_obj == NULL); + + new_obj = json_tokener_parse_ex(tok, "False", 5); + assert (new_obj == NULL); + + new_obj = json_tokener_parse_ex(tok, "Null", 4); + assert (new_obj == NULL); + + printf("OK\n"); + + json_tokener_free(tok); +} diff --git a/json-c/src/tests/test_charcase.expected b/json-c/src/tests/test_charcase.expected new file mode 100644 index 0000000..e178f82 --- /dev/null +++ b/json-c/src/tests/test_charcase.expected @@ -0,0 +1 @@ +OK diff --git a/json-c/src/tests/test_charcase.test b/json-c/src/tests/test_charcase.test new file mode 100644 index 0000000..40edbf4 --- /dev/null +++ b/json-c/src/tests/test_charcase.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_charcase +exit $? diff --git a/json-c/src/tests/test_locale.c b/json-c/src/tests/test_locale.c new file mode 100644 index 0000000..7924bca --- /dev/null +++ b/json-c/src/tests/test_locale.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +#include "config.h" +#include "json.h" +#include "json_tokener.h" + +#ifdef HAVE_LOCALE_H +#include +#endif /* HAVE_LOCALE_H */ + +int main(int argc, char **argv) +{ + json_object *new_obj; +#ifdef HAVE_SETLOCALE + setlocale(LC_NUMERIC, "de_DE"); +#else + printf("No locale\n"); +#endif + + MC_SET_DEBUG(1); + + new_obj = json_tokener_parse("[1.2,3.4,123456.78,5.0,2.3e10]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + printf("new_obj.to_string()=%s\n", json_object_to_json_string_ext(new_obj,JSON_C_TO_STRING_NOZERO)); + json_object_put(new_obj); +} + diff --git a/json-c/src/tests/test_locale.expected b/json-c/src/tests/test_locale.expected new file mode 100644 index 0000000..4415692 --- /dev/null +++ b/json-c/src/tests/test_locale.expected @@ -0,0 +1,2 @@ +new_obj.to_string()=[ 1.2, 3.4, 123456.78, 5.0, 2.3e10 ] +new_obj.to_string()=[1.2,3.4,123456.78,5.0,2.3e10] diff --git a/json-c/src/tests/test_locale.test b/json-c/src/tests/test_locale.test new file mode 100644 index 0000000..436587f --- /dev/null +++ b/json-c/src/tests/test_locale.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_locale +exit $? diff --git a/json-c/src/tests/test_null.c b/json-c/src/tests/test_null.c new file mode 100644 index 0000000..da86fb6 --- /dev/null +++ b/json-c/src/tests/test_null.c @@ -0,0 +1,57 @@ +/* +* Tests if binary strings are supported. +*/ + +#include +#include +#include "config.h" + +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" + +int main() +{ + // this test has a space after the null character. check that it's still included + const char *input = " \0 "; + const char *expected = "\" \\u0000 \""; + struct json_object *string = json_object_new_string_len(input, 3); + const char *json = json_object_to_json_string(string); + + int strings_match = !strcmp( expected, json); + int retval = 0; + if (strings_match) + { + printf("JSON write result is correct: %s\n", json); + printf("PASS\n"); + } else { + printf("JSON write result doesn't match expected string\n"); + printf("expected string: "); + printf("%s\n", expected); + printf("parsed string: "); + printf("%s\n", json); + printf("FAIL\n"); + retval=1; + } + json_object_put(string); + + struct json_object *parsed_str = json_tokener_parse(expected); + if (parsed_str) + { + int parsed_len = json_object_get_string_len(parsed_str); + const char *parsed_cstr = json_object_get_string(parsed_str); + int ii; + printf("Re-parsed object string len=%d, chars=[", parsed_len); + for (ii = 0; ii < parsed_len ; ii++) + { + printf("%s%d", (ii ? ", " : ""), (int)parsed_cstr[ii]); + } + printf("]\n"); + json_object_put(parsed_str); + } + else + { + printf("ERROR: failed to parse\n"); + } + return retval; +} diff --git a/json-c/src/tests/test_null.expected b/json-c/src/tests/test_null.expected new file mode 100644 index 0000000..be1c9d1 --- /dev/null +++ b/json-c/src/tests/test_null.expected @@ -0,0 +1,3 @@ +JSON write result is correct: " \u0000 " +PASS +Re-parsed object string len=3, chars=[32, 0, 32] diff --git a/json-c/src/tests/test_null.test b/json-c/src/tests/test_null.test new file mode 100644 index 0000000..7c4365c --- /dev/null +++ b/json-c/src/tests/test_null.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_null +exit $? diff --git a/json-c/src/tests/test_parse.c b/json-c/src/tests/test_parse.c new file mode 100644 index 0000000..2e5996e --- /dev/null +++ b/json-c/src/tests/test_parse.c @@ -0,0 +1,342 @@ +#include +#include +#include +#include +#include + +#include "json.h" +#include "json_tokener.h" + +static void test_basic_parse(void); +static void test_verbose_parse(void); +static void test_incremental_parse(void); + +int main(int argc, char **argv) +{ + MC_SET_DEBUG(1); + + test_basic_parse(); + printf("==================================\n"); + test_verbose_parse(); + printf("==================================\n"); + test_incremental_parse(); + printf("==================================\n"); +} + +static void test_basic_parse() +{ + json_object *new_obj; + + new_obj = json_tokener_parse("\"\003\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("/* hello */\"foo\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("// hello\n\"foo\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("\"\\u0041\\u0042\\u0043\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("null"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("NaN"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("-NaN"); /* non-sensical, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("Inf"); /* must use full string, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("inf"); /* must use full string, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("Infinity"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("infinity"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("-Infinity"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("-infinity"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("True"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("12"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("12.3"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("12.3.4"); /* non-sensical, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + /* was returning (int)2015 before patch, should return null */ + new_obj = json_tokener_parse("2015-01-15"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{\"FoO\" : -12.3E512}"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{\"FoO\" : -12.3E51.2}"); /* non-sensical, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"\\n\"]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"\\nabc\\n\"]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[null]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[false]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{}"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": \"bar\" }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); +} + +static void test_verbose_parse() +{ + json_object *new_obj; + enum json_tokener_error error = json_tokener_success; + + new_obj = json_tokener_parse_verbose("{ foo }", &error); + assert (error == json_tokener_error_parse_object_key_name); + assert (new_obj == NULL); + + new_obj = json_tokener_parse("{ foo }"); + assert (new_obj == NULL); + + new_obj = json_tokener_parse("foo"); + assert (new_obj == NULL); + new_obj = json_tokener_parse_verbose("foo", &error); + assert (new_obj == NULL); + + /* b/c the string starts with 'f' parsing return a boolean error */ + assert (error == json_tokener_error_parse_boolean); + + printf("json_tokener_parse_versbose() OK\n"); +} + +struct incremental_step { + const char *string_to_parse; + int length; + int char_offset; + enum json_tokener_error expected_error; + int reset_tokener; +} incremental_steps[] = { + + /* Check that full json messages can be parsed, both w/ and w/o a reset */ + { "{ \"foo\": 123 }", -1, -1, json_tokener_success, 0 }, + { "{ \"foo\": 456 }", -1, -1, json_tokener_success, 1 }, + { "{ \"foo\": 789 }", -1, -1, json_tokener_success, 1 }, + + /* Check a basic incremental parse */ + { "{ \"foo", -1, -1, json_tokener_continue, 0 }, + { "\": {\"bar", -1, -1, json_tokener_continue, 0 }, + { "\":13}}", -1, -1, json_tokener_success, 1 }, + + /* Check that json_tokener_reset actually resets */ + { "{ \"foo", -1, -1, json_tokener_continue, 1 }, + { ": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1 }, + + /* Check incremental parsing with trailing characters */ + { "{ \"foo", -1, -1, json_tokener_continue, 0 }, + { "\": {\"bar", -1, -1, json_tokener_continue, 0 }, + { "\":13}}XXXX", 10, 6, json_tokener_success, 0 }, + { "XXXX", 4, 0, json_tokener_error_parse_unexpected, 1 }, + + /* Check that trailing characters can change w/o a reset */ + { "{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0 }, + { "\"Y\"", -1, -1, json_tokener_success, 1 }, + + /* To stop parsing a number we need to reach a non-digit, e.g. a \0 */ + { "1", 1, 1, json_tokener_continue, 0 }, + { "2", 2, 1, json_tokener_success, 0 }, + + /* Some bad formatting. Check we get the correct error status */ + { "2015-01-15", 10, 4, json_tokener_error_parse_number, 1 }, + + /* Strings have a well defined end point, so we can stop at the quote */ + { "\"blue\"", -1, -1, json_tokener_success, 0 }, + + /* Check each of the escape sequences defined by the spec */ + { "\"\\\"\"", -1, -1, json_tokener_success, 0 }, + { "\"\\\\\"", -1, -1, json_tokener_success, 0 }, + { "\"\\b\"", -1, -1, json_tokener_success, 0 }, + { "\"\\f\"", -1, -1, json_tokener_success, 0 }, + { "\"\\n\"", -1, -1, json_tokener_success, 0 }, + { "\"\\r\"", -1, -1, json_tokener_success, 0 }, + { "\"\\t\"", -1, -1, json_tokener_success, 0 }, + + { "[1,2,3]", -1, -1, json_tokener_success, 0 }, + + /* This behaviour doesn't entirely follow the json spec, but until we have + a way to specify how strict to be we follow Postel's Law and be liberal + in what we accept (up to a point). */ + { "[1,2,3,]", -1, -1, json_tokener_success, 0 }, + { "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0 }, + + { "[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 3 }, + { "{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 3 }, + + { NULL, -1, -1, json_tokener_success, 0 }, +}; + +static void test_incremental_parse() +{ + json_object *new_obj; + enum json_tokener_error jerr; + json_tokener *tok; + const char *string_to_parse; + int ii; + int num_ok, num_error; + + num_ok = 0; + num_error = 0; + + printf("Starting incremental tests.\n"); + printf("Note: quotes and backslashes seen in the output here are literal values passed\n"); + printf(" to the parse functions. e.g. this is 4 characters: \"\\f\"\n"); + + string_to_parse = "{ \"foo"; /* } */ + printf("json_tokener_parse(%s) ... ", string_to_parse); + new_obj = json_tokener_parse(string_to_parse); + if (new_obj == NULL) printf("got error as expected\n"); + + /* test incremental parsing in various forms */ + tok = json_tokener_new(); + for (ii = 0; incremental_steps[ii].string_to_parse != NULL; ii++) + { + int this_step_ok = 0; + struct incremental_step *step = &incremental_steps[ii]; + int length = step->length; + int expected_char_offset = step->char_offset; + + if (step->reset_tokener & 2) + json_tokener_set_flags(tok, JSON_TOKENER_STRICT); + else + json_tokener_set_flags(tok, 0); + + if (length == -1) + length = strlen(step->string_to_parse); + if (expected_char_offset == -1) + expected_char_offset = length; + + printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ", + step->string_to_parse, length); + new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length); + + jerr = json_tokener_get_error(tok); + if (step->expected_error != json_tokener_success) + { + if (new_obj != NULL) + printf("ERROR: invalid object returned: %s\n", + json_object_to_json_string(new_obj)); + else if (jerr != step->expected_error) + printf("ERROR: got wrong error: %s\n", + json_tokener_error_desc(jerr)); + else if (tok->char_offset != expected_char_offset) + printf("ERROR: wrong char_offset %d != expected %d\n", + tok->char_offset, + expected_char_offset); + else + { + printf("OK: got correct error: %s\n", json_tokener_error_desc(jerr)); + this_step_ok = 1; + } + } + else + { + if (new_obj == NULL) + printf("ERROR: expected valid object, instead: %s\n", + json_tokener_error_desc(jerr)); + else if (tok->char_offset != expected_char_offset) + printf("ERROR: wrong char_offset %d != expected %d\n", + tok->char_offset, + expected_char_offset); + else + { + printf("OK: got object of type [%s]: %s\n", + json_type_to_name(json_object_get_type(new_obj)), + json_object_to_json_string(new_obj)); + this_step_ok = 1; + } + } + + if (new_obj) + json_object_put(new_obj); + + if (step->reset_tokener & 1) + json_tokener_reset(tok); + + if (this_step_ok) + num_ok++; + else + num_error++; + } + + json_tokener_free(tok); + + printf("End Incremental Tests OK=%d ERROR=%d\n", num_ok, num_error); + + return; +} diff --git a/json-c/src/tests/test_parse.expected b/json-c/src/tests/test_parse.expected new file mode 100644 index 0000000..bb76db2 --- /dev/null +++ b/json-c/src/tests/test_parse.expected @@ -0,0 +1,70 @@ +new_obj.to_string()="\u0003" +new_obj.to_string()="foo" +new_obj.to_string()="foo" +new_obj.to_string()="ABC" +new_obj.to_string()=null +new_obj.to_string()=NaN +new_obj.to_string()=null +new_obj.to_string()=null +new_obj.to_string()=null +new_obj.to_string()=Infinity +new_obj.to_string()=Infinity +new_obj.to_string()=-Infinity +new_obj.to_string()=-Infinity +new_obj.to_string()=true +new_obj.to_string()=12 +new_obj.to_string()=12.3 +new_obj.to_string()=null +new_obj.to_string()=null +new_obj.to_string()={ "FoO": -12.3E512 } +new_obj.to_string()=null +new_obj.to_string()=[ "\n" ] +new_obj.to_string()=[ "\nabc\n" ] +new_obj.to_string()=[ null ] +new_obj.to_string()=[ ] +new_obj.to_string()=[ false ] +new_obj.to_string()=[ "abc", null, "def", 12 ] +new_obj.to_string()={ } +new_obj.to_string()={ "foo": "bar" } +new_obj.to_string()={ "foo": "bar", "baz": null, "bool0": true } +new_obj.to_string()={ "foo": [ null, "foo" ] } +new_obj.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] } +================================== +json_tokener_parse_versbose() OK +================================== +Starting incremental tests. +Note: quotes and backslashes seen in the output here are literal values passed + to the parse functions. e.g. this is 4 characters: "\f" +json_tokener_parse({ "foo) ... got error as expected +json_tokener_parse_ex(tok, { "foo": 123 }, 14) ... OK: got object of type [object]: { "foo": 123 } +json_tokener_parse_ex(tok, { "foo": 456 }, 14) ... OK: got object of type [object]: { "foo": 456 } +json_tokener_parse_ex(tok, { "foo": 789 }, 14) ... OK: got object of type [object]: { "foo": 789 } +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ":13}} , 6) ... OK: got object of type [object]: { "foo": { "bar": 13 } } +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, : "bar"} , 8) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ":13}}XXXX , 10) ... OK: got object of type [object]: { "foo": { "bar": 13 } } +json_tokener_parse_ex(tok, XXXX , 4) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, {"x": 123 }"X", 14) ... OK: got object of type [object]: { "x": 123 } +json_tokener_parse_ex(tok, "Y" , 3) ... OK: got object of type [string]: "Y" +json_tokener_parse_ex(tok, 1 , 1) ... OK: got correct error: continue +json_tokener_parse_ex(tok, 2 , 2) ... OK: got object of type [int]: 12 +json_tokener_parse_ex(tok, 2015-01-15 , 10) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, "blue" , 6) ... OK: got object of type [string]: "blue" +json_tokener_parse_ex(tok, "\"" , 4) ... OK: got object of type [string]: "\"" +json_tokener_parse_ex(tok, "\\" , 4) ... OK: got object of type [string]: "\\" +json_tokener_parse_ex(tok, "\b" , 4) ... OK: got object of type [string]: "\b" +json_tokener_parse_ex(tok, "\f" , 4) ... OK: got object of type [string]: "\f" +json_tokener_parse_ex(tok, "\n" , 4) ... OK: got object of type [string]: "\n" +json_tokener_parse_ex(tok, "\r" , 4) ... OK: got object of type [string]: "\r" +json_tokener_parse_ex(tok, "\t" , 4) ... OK: got object of type [string]: "\t" +json_tokener_parse_ex(tok, [1,2,3] , 7) ... OK: got object of type [array]: [ 1, 2, 3 ] +json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got object of type [array]: [ 1, 2, 3 ] +json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, {"a":1,} , 8) ... OK: got correct error: unexpected character +End Incremental Tests OK=30 ERROR=0 +================================== diff --git a/json-c/src/tests/test_parse.test b/json-c/src/tests/test_parse.test new file mode 100644 index 0000000..719a3ad --- /dev/null +++ b/json-c/src/tests/test_parse.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_parse +exit $? diff --git a/json-c/src/tests/test_parse_int64.c b/json-c/src/tests/test_parse_int64.c new file mode 100644 index 0000000..dfcdae0 --- /dev/null +++ b/json-c/src/tests/test_parse_int64.c @@ -0,0 +1,115 @@ + +#include +#include + +#include "config.h" + +#include "json_inttypes.h" +#include "json_util.h" + +void checkit(const char *buf) +{ + int64_t cint64 = -666; + + int retval = json_parse_int64(buf, &cint64); + printf("buf=%s parseit=%d, value=%" PRId64 " \n", buf, retval, cint64); +} + +/** + * This test calls json_parse_int64 with a variety of different strings. + * It's purpose is to ensure that the results are consistent across all + * different environments that it might be executed in. + * + * This always exits with a 0 exit value. The output should be compared + * against previously saved expected output. + */ +int main() +{ + char buf[100]; + + checkit("x"); + + checkit("0"); + checkit("-0"); + + checkit("00000000"); + checkit("-00000000"); + + checkit("1"); + + strcpy(buf, "2147483647"); // aka INT32_MAX + checkit(buf); + + strcpy(buf, "-1"); + checkit(buf); + + strcpy(buf, " -1"); + checkit(buf); + + strcpy(buf, "00001234"); + checkit(buf); + + strcpy(buf, "0001234x"); + checkit(buf); + + strcpy(buf, "-00001234"); + checkit(buf); + + strcpy(buf, "-00001234x"); + checkit(buf); + + strcpy(buf, "4294967295"); // aka UINT32_MAX + + sprintf(buf, "4294967296"); // aka UINT32_MAX + 1 + + strcpy(buf, "21474836470"); // INT32_MAX * 10 + checkit(buf); + + strcpy(buf, "31474836470"); // INT32_MAX * 10 + a bunch + checkit(buf); + + strcpy(buf, "-2147483647"); // INT32_MIN + 1 + checkit(buf); + + strcpy(buf, "-2147483648"); // INT32_MIN + checkit(buf); + + strcpy(buf, "-2147483649"); // INT32_MIN - 1 + checkit(buf); + + strcpy(buf, "-21474836480"); // INT32_MIN * 10 + checkit(buf); + + strcpy(buf, "9223372036854775806"); // INT64_MAX - 1 + checkit(buf); + + strcpy(buf, "9223372036854775807"); // INT64_MAX + checkit(buf); + + strcpy(buf, "9223372036854775808"); // INT64_MAX + 1 + checkit(buf); + + strcpy(buf, "-9223372036854775808"); // INT64_MIN + checkit(buf); + + strcpy(buf, "-9223372036854775809"); // INT64_MIN - 1 + checkit(buf); + + strcpy(buf, "18446744073709551614"); // UINT64_MAX - 1 + checkit(buf); + + strcpy(buf, "18446744073709551615"); // UINT64_MAX + checkit(buf); + + strcpy(buf, "18446744073709551616"); // UINT64_MAX + 1 + checkit(buf); + + strcpy(buf, "-18446744073709551616"); // -UINT64_MAX + checkit(buf); + + // Ensure we can still parse valid numbers after parsing out of range ones. + strcpy(buf, "123"); + checkit(buf); + + return 0; +} diff --git a/json-c/src/tests/test_parse_int64.expected b/json-c/src/tests/test_parse_int64.expected new file mode 100644 index 0000000..1ed8f02 --- /dev/null +++ b/json-c/src/tests/test_parse_int64.expected @@ -0,0 +1,29 @@ +buf=x parseit=1, value=-666 +buf=0 parseit=0, value=0 +buf=-0 parseit=0, value=0 +buf=00000000 parseit=0, value=0 +buf=-00000000 parseit=0, value=0 +buf=1 parseit=0, value=1 +buf=2147483647 parseit=0, value=2147483647 +buf=-1 parseit=0, value=-1 +buf= -1 parseit=0, value=-1 +buf=00001234 parseit=0, value=1234 +buf=0001234x parseit=0, value=1234 +buf=-00001234 parseit=0, value=-1234 +buf=-00001234x parseit=0, value=-1234 +buf=21474836470 parseit=0, value=21474836470 +buf=31474836470 parseit=0, value=31474836470 +buf=-2147483647 parseit=0, value=-2147483647 +buf=-2147483648 parseit=0, value=-2147483648 +buf=-2147483649 parseit=0, value=-2147483649 +buf=-21474836480 parseit=0, value=-21474836480 +buf=9223372036854775806 parseit=0, value=9223372036854775806 +buf=9223372036854775807 parseit=0, value=9223372036854775807 +buf=9223372036854775808 parseit=0, value=9223372036854775807 +buf=-9223372036854775808 parseit=0, value=-9223372036854775808 +buf=-9223372036854775809 parseit=0, value=-9223372036854775808 +buf=18446744073709551614 parseit=0, value=9223372036854775807 +buf=18446744073709551615 parseit=0, value=9223372036854775807 +buf=18446744073709551616 parseit=0, value=9223372036854775807 +buf=-18446744073709551616 parseit=0, value=-9223372036854775808 +buf=123 parseit=0, value=123 diff --git a/json-c/src/tests/test_parse_int64.test b/json-c/src/tests/test_parse_int64.test new file mode 100644 index 0000000..556681f --- /dev/null +++ b/json-c/src/tests/test_parse_int64.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_parse_int64 +exit $? diff --git a/json-c/src/tests/test_printbuf.c b/json-c/src/tests/test_printbuf.c new file mode 100644 index 0000000..b363296 --- /dev/null +++ b/json-c/src/tests/test_printbuf.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "printbuf.h" + +static void test_basic_printbuf_memset(void); +static void test_printbuf_memset_length(void); + +static void test_basic_printbuf_memset() +{ + struct printbuf *pb; + + printf("%s: starting test\n", __func__); + pb = printbuf_new(); + sprintbuf(pb, "blue:%d", 1); + printbuf_memset(pb, -1, 'x', 52); + printf("Buffer contents:%.*s\n", printbuf_length(pb), pb->buf); + printbuf_free(pb); + printf("%s: end test\n", __func__); +} + +static void test_printbuf_memset_length() +{ + struct printbuf *pb; + + printf("%s: starting test\n", __func__); + pb = printbuf_new(); + printbuf_memset(pb, -1, ' ', 0); + printbuf_memset(pb, -1, ' ', 0); + printbuf_memset(pb, -1, ' ', 0); + printbuf_memset(pb, -1, ' ', 0); + printbuf_memset(pb, -1, ' ', 0); + printf("Buffer length: %d\n", printbuf_length(pb)); + printbuf_memset(pb, -1, ' ', 2); + printbuf_memset(pb, -1, ' ', 4); + printbuf_memset(pb, -1, ' ', 6); + printf("Buffer length: %d\n", printbuf_length(pb)); + printbuf_memset(pb, -1, ' ', 6); + printf("Buffer length: %d\n", printbuf_length(pb)); + printbuf_memset(pb, -1, ' ', 8); + printbuf_memset(pb, -1, ' ', 10); + printbuf_memset(pb, -1, ' ', 10); + printbuf_memset(pb, -1, ' ', 10); + printbuf_memset(pb, -1, ' ', 20); + printf("Buffer length: %d\n", printbuf_length(pb)); + + // No length change should occur + printbuf_memset(pb, 0, 'x', 30); + printf("Buffer length: %d\n", printbuf_length(pb)); + + // This should extend it by one. + printbuf_memset(pb, 0, 'x', printbuf_length(pb) + 1); + printf("Buffer length: %d\n", printbuf_length(pb)); + + printbuf_free(pb); + printf("%s: end test\n", __func__); +} + +static void test_printbuf_memappend(int *before_resize); +static void test_printbuf_memappend(int *before_resize) +{ + struct printbuf *pb; + int initial_size; + + printf("%s: starting test\n", __func__); + pb = printbuf_new(); + printf("Buffer length: %d\n", printbuf_length(pb)); + + initial_size = pb->size; + + while(pb->size == initial_size) + { + printbuf_memappend_fast(pb, "x", 1); + } + *before_resize = printbuf_length(pb) - 1; + printf("Appended %d bytes for resize: [%s]\n", *before_resize + 1, pb->buf); + + printbuf_reset(pb); + printbuf_memappend_fast(pb, "bluexyz123", 3); + printf("Partial append: %d, [%s]\n", printbuf_length(pb), pb->buf); + + char with_nulls[] = { 'a', 'b', '\0', 'c' }; + printbuf_reset(pb); + printbuf_memappend_fast(pb, with_nulls, (int)sizeof(with_nulls)); + printf("With embedded \\0 character: %d, [%s]\n", printbuf_length(pb), pb->buf); + + printbuf_free(pb); + pb = printbuf_new(); + char *data = malloc(*before_resize); + memset(data, 'X', *before_resize); + printbuf_memappend_fast(pb, data, *before_resize); + printf("Append to just before resize: %d, [%s]\n", printbuf_length(pb), pb->buf); + + free(data); + printbuf_free(pb); + + pb = printbuf_new(); + data = malloc(*before_resize + 1); + memset(data, 'X', *before_resize + 1); + printbuf_memappend_fast(pb, data, *before_resize + 1); + printf("Append to just after resize: %d, [%s]\n", printbuf_length(pb), pb->buf); + + free(data); + + printbuf_free(pb); + printf("%s: end test\n", __func__); +} + +static void test_sprintbuf(int before_resize); +static void test_sprintbuf(int before_resize) +{ + struct printbuf *pb; + + printf("%s: starting test\n", __func__); + pb = printbuf_new(); + printf("Buffer length: %d\n", printbuf_length(pb)); + + char *data = malloc(before_resize + 1 + 1); + memset(data, 'X', before_resize + 1 + 1); + data[before_resize + 1] = '\0'; + sprintbuf(pb, "%s", data); + free(data); + printf("sprintbuf to just after resize(%d+1): %d, [%s], strlen(buf)=%d\n", before_resize, printbuf_length(pb), pb->buf, (int)strlen(pb->buf)); + + printbuf_reset(pb); + sprintbuf(pb, "plain"); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + sprintbuf(pb, "%d", 1); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + sprintbuf(pb, "%d", INT_MAX); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + sprintbuf(pb, "%d", INT_MIN); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + sprintbuf(pb, "%s", "%s"); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + printbuf_free(pb); + printf("%s: end test\n", __func__); +} + +int main(int argc, char **argv) +{ + int before_resize = 0; + + mc_set_debug(1); + + test_basic_printbuf_memset(); + printf("========================================\n"); + test_printbuf_memset_length(); + printf("========================================\n"); + test_printbuf_memappend(&before_resize); + printf("========================================\n"); + test_sprintbuf(before_resize); + printf("========================================\n"); + + return 0; +} diff --git a/json-c/src/tests/test_printbuf.expected b/json-c/src/tests/test_printbuf.expected new file mode 100644 index 0000000..ec69095 --- /dev/null +++ b/json-c/src/tests/test_printbuf.expected @@ -0,0 +1,32 @@ +test_basic_printbuf_memset: starting test +Buffer contents:blue:1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +test_basic_printbuf_memset: end test +======================================== +test_printbuf_memset_length: starting test +Buffer length: 0 +Buffer length: 12 +Buffer length: 18 +Buffer length: 76 +Buffer length: 76 +Buffer length: 77 +test_printbuf_memset_length: end test +======================================== +test_printbuf_memappend: starting test +Buffer length: 0 +Appended 32 bytes for resize: [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] +Partial append: 3, [blu] +With embedded \0 character: 4, [ab] +Append to just before resize: 31, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX] +Append to just after resize: 32, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX] +test_printbuf_memappend: end test +======================================== +test_sprintbuf: starting test +Buffer length: 0 +sprintbuf to just after resize(31+1): 32, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX], strlen(buf)=32 +5, [plain] +6, [plain1] +16, [plain12147483647] +27, [plain12147483647-2147483648] +29, [plain12147483647-2147483648%s] +test_sprintbuf: end test +======================================== diff --git a/json-c/src/tests/test_printbuf.test b/json-c/src/tests/test_printbuf.test new file mode 100644 index 0000000..8da4fb5 --- /dev/null +++ b/json-c/src/tests/test_printbuf.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_printbuf +exit $? diff --git a/json-c/src/tests/test_set_serializer.c b/json-c/src/tests/test_set_serializer.c new file mode 100644 index 0000000..e79b00d --- /dev/null +++ b/json-c/src/tests/test_set_serializer.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include "json.h" +#include "printbuf.h" + +struct myinfo { + int value; +}; + +static int freeit_was_called = 0; +static void freeit(json_object *jso, void *userdata) +{ + struct myinfo *info = userdata; + printf("freeit, value=%d\n", info->value); + // Don't actually free anything here, the userdata is stack allocated. + freeit_was_called = 1; +} +static int custom_serializer(struct json_object *o, + struct printbuf *pb, + int level, + int flags) +{ + sprintbuf(pb, "Custom Output"); + return 0; +} + +int main(int argc, char **argv) +{ + json_object *my_object; + + MC_SET_DEBUG(1); + + printf("Test setting, then resetting a custom serializer:\n"); + my_object = json_object_new_object(); + json_object_object_add(my_object, "abc", json_object_new_int(12)); + json_object_object_add(my_object, "foo", json_object_new_string("bar")); + + printf("my_object.to_string(standard)=%s\n", json_object_to_json_string(my_object)); + + struct myinfo userdata = { .value = 123 }; + json_object_set_serializer(my_object, custom_serializer, &userdata, freeit); + + printf("my_object.to_string(custom serializer)=%s\n", json_object_to_json_string(my_object)); + + printf("Next line of output should be from the custom freeit function:\n"); + freeit_was_called = 0; + json_object_set_serializer(my_object, NULL, NULL, NULL); + assert(freeit_was_called); + + printf("my_object.to_string(standard)=%s\n", json_object_to_json_string(my_object)); + + json_object_put(my_object); + + // ============================================ + + my_object = json_object_new_object(); + printf("Check that the custom serializer isn't free'd until the last json_object_put:\n"); + json_object_set_serializer(my_object, custom_serializer, &userdata, freeit); + json_object_get(my_object); + json_object_put(my_object); + printf("my_object.to_string(custom serializer)=%s\n", json_object_to_json_string(my_object)); + printf("Next line of output should be from the custom freeit function:\n"); + + freeit_was_called = 0; + json_object_put(my_object); + assert(freeit_was_called); + + return 0; +} diff --git a/json-c/src/tests/test_set_serializer.expected b/json-c/src/tests/test_set_serializer.expected new file mode 100644 index 0000000..f5d3747 --- /dev/null +++ b/json-c/src/tests/test_set_serializer.expected @@ -0,0 +1,10 @@ +Test setting, then resetting a custom serializer: +my_object.to_string(standard)={ "abc": 12, "foo": "bar" } +my_object.to_string(custom serializer)=Custom Output +Next line of output should be from the custom freeit function: +freeit, value=123 +my_object.to_string(standard)={ "abc": 12, "foo": "bar" } +Check that the custom serializer isn't free'd until the last json_object_put: +my_object.to_string(custom serializer)=Custom Output +Next line of output should be from the custom freeit function: +freeit, value=123 diff --git a/json-c/src/tests/test_set_serializer.test b/json-c/src/tests/test_set_serializer.test new file mode 100644 index 0000000..0034183 --- /dev/null +++ b/json-c/src/tests/test_set_serializer.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_set_serializer +exit $? diff --git a/libcurl/libcurl.vcxproj b/libcurl/libcurl.vcxproj new file mode 100644 index 0000000..98d529d --- /dev/null +++ b/libcurl/libcurl.vcxproj @@ -0,0 +1,129 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + {B69D7658-2A3F-4BB5-9A7E-4546B8551EC0} + libcurl + Win32Proj + + + + StaticLibrary + NotSet + true + v140_xp + + + StaticLibrary + NotSet + v140_xp + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)build\temp\lib\ + $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ + $(SolutionDir)build\temp\lib\ + $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + $(ProjectName)-mt-debug + $(ProjectName)-mt + + + + Disabled + $(ProjectDir)src\include\;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;AO_BUILDING_LIBAO;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + false + + + EnableFastChecks + MultiThreadedDebug + + + $(IntDir)vc90.pdb + Level3 + OldStyle + + + + + @echo off +set curl_headers=curl.h,curlbuild.h,curlrules.h,curlver.h,easy.h,mprintf.h,multi.h,stdcheaders.h,typecheck-gcc.h + +for %%a in ("%curl_headers:,=" "%") do ( + xcopy "$(ProjectDir)src\include\curl\%%a" "$(SolutionDir)build\temp\include\curl\" /I /Y /D +) + + + + + + MaxSpeed + true + $(ProjectDir)src\include\;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;AO_BUILDING_LIBAO;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreaded + true + + + $(IntDir)vc90.pdb + Level3 + + + + + + + @echo off +set curl_headers=curl.h,curlbuild.h,curlrules.h,curlver.h,easy.h,mprintf.h,multi.h,stdcheaders.h,typecheck-gcc.h + +for %%a in ("%curl_headers:,=" "%") do ( + xcopy "$(ProjectDir)src\include\curl\%%a" "$(SolutionDir)build\temp\include\curl\" /I /Y /D +) + + + + + + + \ No newline at end of file diff --git a/libcurl/libcurl.vcxproj.filters b/libcurl/libcurl.vcxproj.filters new file mode 100644 index 0000000..1ad06e9 --- /dev/null +++ b/libcurl/libcurl.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {2a0877fb-7db4-436f-967f-0784ed77c701} + + + {16157074-e564-417f-9c0b-a94b51acc7a7} + + + + + Include\curl + + + Include\curl + + + Include\curl + + + Include\curl + + + Include\curl + + + Include\curl + + + Include\curl + + + Include\curl + + + Include\curl + + + + + Sources + + + \ No newline at end of file diff --git a/libcurl/src/include/curl/curl.h b/libcurl/src/include/curl/curl.h new file mode 100644 index 0000000..07ff831 --- /dev/null +++ b/libcurl/src/include/curl/curl.h @@ -0,0 +1,2364 @@ +#ifndef __CURL_CURL_H +#define __CURL_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * http://curl.haxx.se/libcurl/ + * + * curl-library mailing list subscription and unsubscription web interface: + * http://cool.haxx.se/mailman/listinfo/curl-library/ + */ + +#include "curlver.h" /* libcurl version defines */ +#include "curlbuild.h" /* libcurl build definitions */ +#include "curlrules.h" /* libcurl rules enforcement */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && \ + !defined(WIN32) && !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || defined(__LWIP_OPT_H__)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) +#include +#endif + +#if !defined(WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#ifdef __BEOS__ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void CURL; + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(WIN32) && !defined(__LWIP_OPT_H__) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist* contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ +#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */ +#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */ +#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer + do not free in formfree */ +#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer + do not free in formfree */ +#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */ +#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */ +#define HTTPPOST_CALLBACK (1<<6) /* upload file contents by using the + regular read callback to get the data + and pass the given pointer as custom + pointer */ + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ +}; + +/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered + deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in + 7.32.0, it avoids floating point and provides more detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + + + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Content of this structure depends on information which is known and is + achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man + page for callbacks returning this structure -- some fields are mandatory, + some others are optional. The FLAG field has special meaning. */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char * b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + 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_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* 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_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an + OpenSSL SSL_CTX */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#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_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS +}; + +struct curl_khkey { + const char *key; /* points to a zero-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 + +/* name is uppercase CURLOPT_, + type is one of the defined CURLOPTTYPE_ + number is unique identifier */ +#ifdef CINIT +#undef CINIT +#endif + +#ifdef CURL_ISOCPP +#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLOPT_/**/name = type + number +#endif + +/* + * This macro-mania below setups the CURLOPT_[what] enum, to be used with + * curl_easy_setopt(). The first argument in the CINIT() macro is the [what] + * word. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CINIT(WRITEDATA, OBJECTPOINT, 1), + + /* The full URL to get/put */ + CINIT(URL, OBJECTPOINT, 2), + + /* Port number to connect to, if other than default. */ + CINIT(PORT, LONG, 3), + + /* Name of proxy to use. */ + CINIT(PROXY, OBJECTPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CINIT(USERPWD, OBJECTPOINT, 5), + + /* "user:password" to use with proxy. */ + CINIT(PROXYUSERPWD, OBJECTPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CINIT(RANGE, OBJECTPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CINIT(READDATA, OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. If this is not used, error messages go to stderr instead: */ + CINIT(ERRORBUFFER, OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CINIT(READFUNCTION, FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CINIT(TIMEOUT, LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CINIT(INFILESIZE, LONG, 14), + + /* POST static input fields. */ + CINIT(POSTFIELDS, OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CINIT(REFERER, OBJECTPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CINIT(FTPPORT, OBJECTPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CINIT(USERAGENT, OBJECTPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CINIT(LOW_SPEED_LIMIT, LONG, 19), + + /* Set the "low speed time" */ + CINIT(LOW_SPEED_TIME, LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CINIT(RESUME_FROM, LONG, 21), + + /* Set cookie in request: */ + CINIT(COOKIE, OBJECTPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CINIT(HTTPHEADER, OBJECTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CINIT(HTTPPOST, OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CINIT(SSLCERT, OBJECTPOINT, 25), + + /* password for the SSL or SSH private key */ + CINIT(KEYPASSWD, OBJECTPOINT, 26), + + /* send TYPE parameter? */ + CINIT(CRLF, LONG, 27), + + /* send linked-list of QUOTE commands */ + CINIT(QUOTE, OBJECTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CINIT(HEADERDATA, OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CINIT(COOKIEFILE, OBJECTPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CINIT(SSLVERSION, LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CINIT(TIMECONDITION, LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CINIT(TIMEVALUE, LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CINIT(CUSTOMREQUEST, OBJECTPOINT, 36), + + /* HTTP request, for odd commands like DELETE, TRACE and others */ + CINIT(STDERR, OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CINIT(POSTQUOTE, OBJECTPOINT, 39), + + CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */ + + CINIT(VERBOSE, LONG, 41), /* talk a lot */ + CINIT(HEADER, LONG, 42), /* throw the header out too */ + CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ + CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ + CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */ + CINIT(UPLOAD, LONG, 46), /* this is an upload */ + CINIT(POST, LONG, 47), /* HTTP POST method */ + CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */ + + CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ + + CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ + CINIT(PUT, LONG, 54), /* HTTP PUT */ + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CINIT(PROGRESSDATA, OBJECTPOINT, 57), +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA + + /* We want the referrer field set automatically when following locations */ + CINIT(AUTOREFERER, LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CINIT(PROXYPORT, LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CINIT(POSTFIELDSIZE, LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CINIT(HTTPPROXYTUNNEL, LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CINIT(INTERFACE, OBJECTPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CINIT(KRBLEVEL, OBJECTPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CINIT(SSL_VERIFYPEER, LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAINFO, OBJECTPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CINIT(MAXREDIRS, LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CINIT(FILETIME, LONG, 69), + + /* This points to a linked list of telnet options */ + CINIT(TELNETOPTIONS, OBJECTPOINT, 70), + + /* Max amount of cached alive connections */ + CINIT(MAXCONNECTS, LONG, 71), + + CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */ + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CINIT(FRESH_CONNECT, LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CINIT(FORBID_REUSE, LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CINIT(RANDOM_FILE, OBJECTPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CINIT(EGDSOCKET, OBJECTPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CINIT(CONNECTTIMEOUT, LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CINIT(HTTPGET, LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CINIT(SSL_VERIFYHOST, LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CINIT(COOKIEJAR, OBJECTPOINT, 82), + + /* Specify which SSL ciphers to use */ + CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CINIT(HTTP_VERSION, LONG, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CINIT(FTP_USE_EPSV, LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CINIT(SSLCERTTYPE, OBJECTPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CINIT(SSLKEY, OBJECTPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CINIT(SSLKEYTYPE, OBJECTPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CINIT(SSLENGINE, OBJECTPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CINIT(SSLENGINE_DEFAULT, LONG, 90), + + /* Non-zero value means to use the global dns cache */ + CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */ + + /* DNS cache timeout */ + CINIT(DNS_CACHE_TIMEOUT, LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CINIT(PREQUOTE, OBJECTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, OBJECTPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102), + + /* Set pointer to private data */ + CINIT(PRIVATE, OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CINIT(HTTP200ALIASES, OBJECTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CINIT(UNRESTRICTED_AUTH, LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CINIT(FTP_USE_EPRT, LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(HTTPAUTH, LONG, 107), + + /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx + in second argument. The function must be matching the + curl_ssl_ctx_callback proto. */ + CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(PROXYAUTH, LONG, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to resolve names to those IP versions only. This only has + affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CINIT(IPRESOLVE, LONG, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CINIT(MAXFILESIZE, LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CINIT(INFILESIZE_LARGE, OFF_T, 115), + + /* Sets the continuation offset. There is also a LONG version of this; + * look above for RESUME_FROM. + */ + CINIT(RESUME_FROM_LARGE, OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CINIT(MAXFILESIZE_LARGE, OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CINIT(NETRC_FILE, OBJECTPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CINIT(USE_SSL, LONG, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CINIT(TCP_NODELAY, LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CINIT(FTPSSLAUTH, LONG, 129), + + CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), + CINIT(IOCTLDATA, OBJECTPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* zero terminated string for pass on to the FTP server when asked for + "account" info */ + CINIT(FTP_ACCOUNT, OBJECTPOINT, 134), + + /* feed cookies into cookie engine */ + CINIT(COOKIELIST, OBJECTPOINT, 135), + + /* ignore Content-Length */ + CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CINIT(FTP_SKIP_PASV_IP, LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CINIT(FTP_FILEMETHOD, LONG, 138), + + /* Local port number to bind the socket to */ + CINIT(LOCALPORT, LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CINIT(LOCALPORTRANGE, LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CINIT(CONNECT_ONLY, LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), + CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147), + + /* callback function for setting socket options */ + CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), + CINIT(SOCKOPTDATA, OBJECTPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CINIT(SSL_SESSIONID_CACHE, LONG, 150), + + /* allowed SSH authentication methods */ + CINIT(SSH_AUTH_TYPES, LONG, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152), + CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CINIT(FTP_SSL_CCC, LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CINIT(TIMEOUT_MS, LONG, 155), + CINIT(CONNECTTIMEOUT_MS, LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CINIT(HTTP_TRANSFER_DECODING, LONG, 157), + CINIT(HTTP_CONTENT_DECODING, LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CINIT(NEW_FILE_PERMS, LONG, 159), + CINIT(NEW_DIRECTORY_PERMS, LONG, 160), + + /* Set the behaviour of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CINIT(POSTREDIR, LONG, 161), + + /* used by scp/sftp to verify the host's public key */ + CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), + CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), + + /* POST volatile input fields. */ + CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CINIT(PROXY_TRANSFER_MODE, LONG, 166), + + /* Callback function for seeking in the input stream */ + CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), + CINIT(SEEKDATA, OBJECTPOINT, 168), + + /* CRL file */ + CINIT(CRLFILE, OBJECTPOINT, 169), + + /* Issuer certificate */ + CINIT(ISSUERCERT, OBJECTPOINT, 170), + + /* (IPv6) Address scope */ + CINIT(ADDRESS_SCOPE, LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CINIT(CERTINFO, LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CINIT(USERNAME, OBJECTPOINT, 173), + CINIT(PASSWORD, OBJECTPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CINIT(PROXYUSERNAME, OBJECTPOINT, 175), + CINIT(PROXYPASSWORD, OBJECTPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CINIT(NOPROXY, OBJECTPOINT, 177), + + /* block size for TFTP transfers */ + CINIT(TFTP_BLKSIZE, LONG, 178), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CINIT(PROTOCOLS, LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to all protocols except FILE and SCP. */ + CINIT(REDIR_PROTOCOLS, LONG, 182), + + /* set the SSH knownhost file name to use */ + CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CINIT(SSH_KEYDATA, OBJECTPOINT, 185), + + /* set the SMTP mail originator */ + CINIT(MAIL_FROM, OBJECTPOINT, 186), + + /* set the SMTP mail receiver(s) */ + CINIT(MAIL_RCPT, OBJECTPOINT, 187), + + /* FTP: send PRET before PASV */ + CINIT(FTP_USE_PRET, LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CINIT(RTSP_REQUEST, LONG, 189), + + /* The RTSP session identifier */ + CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190), + + /* The RTSP stream URI */ + CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CINIT(RTSP_CLIENT_CSEQ, LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CINIT(RTSP_SERVER_CSEQ, LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CINIT(INTERLEAVEDATA, OBJECTPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CINIT(WILDCARDMATCH, LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CINIT(CHUNK_DATA, OBJECTPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CINIT(FNMATCH_DATA, OBJECTPOINT, 202), + + /* send linked-list of name:port:address sets */ + CINIT(RESOLVE, OBJECTPOINT, 203), + + /* Set a username for authenticated TLS */ + CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204), + + /* Set a password for authenticated TLS */ + CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CINIT(TRANSFER_ENCODING, LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), + CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), + + /* allow GSSAPI credential delegation */ + CINIT(GSSAPI_DELEGATION, LONG, 210), + + /* Set the name servers to use for DNS resolution */ + CINIT(DNS_SERVERS, OBJECTPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of miliseconds. */ + CINIT(ACCEPTTIMEOUT_MS, LONG, 212), + + /* Set TCP keepalive */ + CINIT(TCP_KEEPALIVE, LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CINIT(TCP_KEEPIDLE, LONG, 214), + CINIT(TCP_KEEPINTVL, LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CINIT(SSL_OPTIONS, LONG, 216), + + /* Set the SMTP auth originator */ + CINIT(MAIL_AUTH, OBJECTPOINT, 217), + + /* Enable/disable SASL initial response */ + CINIT(SASL_IR, LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_INTERFACE, OBJECTPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223), + + /* Set authentication options directly */ + CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_NPN, LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_ALPN, LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CINIT(PROXYHEADER, OBJECTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CINIT(HEADEROPT, LONG, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CINIT(PINNEDPUBLICKEY, OBJECTPOINT, 230), + + /* Path to Unix domain socket */ + CINIT(UNIX_SOCKET_PATH, OBJECTPOINT, 231), + + /* Set if we should verify the certificate status. */ + CINIT(SSL_VERIFYSTATUS, LONG, 232), + + /* Set if we should enable TLS false start. */ + CINIT(SSL_FALSESTART, LONG, 233), + + /* Do not squash dot-dot sequences */ + CINIT(PATH_AS_IS, LONG, 234), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ +#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2.0 in the request */ + + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + libcurl, see lib/README.curlx for details */ +CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2); +CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n); + +/* name is uppercase CURLFORM_ */ +#ifdef CFINIT +#undef CFINIT +#endif + +#ifdef CURL_ISOCPP +#define CFINIT(name) CURLFORM_ ## name +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define CFINIT(name) CURLFORM_/**/name +#endif + +typedef enum { + CFINIT(NOTHING), /********* the first one is unused ************/ + + /* */ + CFINIT(COPYNAME), + CFINIT(PTRNAME), + CFINIT(NAMELENGTH), + CFINIT(COPYCONTENTS), + CFINIT(PTRCONTENTS), + CFINIT(CONTENTSLENGTH), + CFINIT(FILECONTENT), + CFINIT(ARRAY), + CFINIT(OBSOLETE), + CFINIT(FILE), + + CFINIT(BUFFER), + CFINIT(BUFFERPTR), + CFINIT(BUFFERLENGTH), + + CFINIT(CONTENTTYPE), + CFINIT(CONTENTHEADER), + CFINIT(FILENAME), + CFINIT(END), + CFINIT(OBSOLETE2), + + CFINIT(STREAM), + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +#undef CFINIT /* done */ + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines with be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL builds. Asked + for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_CYASSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_DARWINSSL = 9, + CURLSSLBACKEND_AXTLS = 10 +} curl_sslbackend; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_SLIST + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43, + /* Fill in new entries below here! */ + + CURLINFO_LASTONE = 43 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + +typedef void CURLSH; + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_FOURTH + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options 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_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is suported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#if !defined(BUILDING_LIBCURL) +//#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +//#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +//#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +//#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* __CURL_CURL_H */ diff --git a/libcurl/src/include/curl/curlbuild.h b/libcurl/src/include/curl/curlbuild.h new file mode 100644 index 0000000..9937bd0 --- /dev/null +++ b/libcurl/src/include/curl/curlbuild.h @@ -0,0 +1,599 @@ +#ifndef __CURL_CURLBUILD_H +#define __CURL_CURLBUILD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * See file include/curl/curlbuild.h.in, run configure, and forget + * that this file exists it is only used for non-configure systems. + * But you can keep reading if you want ;-) + * + */ + +/* ================================================================ */ +/* NOTES FOR NON-CONFIGURE SYSTEMS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * If you think that something actually needs to be changed, adjusted + * or fixed in this file, then, report it on the libcurl development + * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * Try to keep one section per platform, compiler and architecture, + * otherwise, if an existing section is reused for a different one and + * later on the original is adjusted, probably the piggybacking one can + * be adversely changed. + * + * In order to differentiate between platforms/compilers/architectures + * use only compiler built in predefined preprocessor symbols. + * + * This header file shall only export symbols which are 'curl' or 'CURL' + * prefixed, otherwise public name space would be polluted. + * + * NOTE 2: + * ------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a + * 64-bit wide signed integral data type. The width of this data type + * must remain constant and independent of any possible large file + * support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a + * 32-bit wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This + * rule shall only be violated if off_t is the only 64-bit data type + * available and the size of off_t is independent of large file support + * settings. Keep your build on the safe side avoiding an off_t gating. + * If you have a 64-bit off_t then take for sure that another 64-bit + * data type exists, dig deeper and you will find it. + * + * NOTE 3: + * ------- + * + * Right now you might be staring at file include/curl/curlbuild.h.dist or + * at file include/curl/curlbuild.h, this is due to the following reason: + * file include/curl/curlbuild.h.dist is renamed to include/curl/curlbuild.h + * when the libcurl source code distribution archive file is created. + * + * File include/curl/curlbuild.h.dist is not included in the distribution + * archive. File include/curl/curlbuild.h is not present in the git tree. + * + * The distributed include/curl/curlbuild.h file is only intended to be used + * on systems which can not run the also distributed configure script. + * + * On systems capable of running the configure script, the configure process + * will overwrite the distributed include/curl/curlbuild.h file with one that + * is suitable and specific to the library being configured and built, which + * is generated from the include/curl/curlbuild.h.in template file. + * + * If you check out from git on a non-configure platform, you must run the + * appropriate buildconf* script to set up curlbuild.h and other local files. + * + */ + +/* ================================================================ */ +/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ +/* ================================================================ */ + +#ifdef CURL_SIZEOF_LONG +# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T +# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_SOCKLEN_T +# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_OFF_T +# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_T +# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_TU +# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined +#endif + +#ifdef CURL_FORMAT_OFF_T +# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_OFF_T +# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_T +# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_TU +# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined +#endif + +/* ================================================================ */ +/* EXTERNAL INTERFACE SETTINGS FOR NON-CONFIGURE SYSTEMS ONLY */ +/* ================================================================ */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__SALFORDC__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_FORMAT_OFF_T "%I64d" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__TURBOC__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_FORMAT_OFF_T "%I64d" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_FORMAT_OFF_T "%I64d" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__LCC__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__MWERKS__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(_WIN32_WCE) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_FORMAT_OFF_T "%I64d" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__MINGW32__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_FORMAT_OFF_T "%I64d" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# define CURL_SIZEOF_LONG 4 +# elif defined(_LP64) +# define CURL_SIZEOF_LONG 8 +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# define CURL_SIZEOF_LONG 4 +# elif defined(_LP64) +# define CURL_SIZEOF_LONG 8 +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_SIZEOF_LONG 8 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_FORMAT_OFF_T "%I64d" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 4 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__EMSCRIPTEN__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) +# if defined(__ILP32__) || \ + defined(__i386__) || defined(__ppc__) || defined(__arm__) || defined(__sparc__) +# define CURL_SIZEOF_LONG 4 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_FORMAT_OFF_T "%lld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) +# define CURL_SIZEOF_LONG 8 +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_FORMAT_OFF_T "%ld" +# define CURL_SIZEOF_CURL_OFF_T 8 +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_SIZEOF_CURL_SOCKLEN_T 4 +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +# error "Unknown non-configure build target!" + Error Compilation_aborted_Unknown_non_configure_build_target +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ + +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +#endif /* __CURL_CURLBUILD_H */ diff --git a/libcurl/src/include/curl/curlbuild.h.cmake b/libcurl/src/include/curl/curlbuild.h.cmake new file mode 100644 index 0000000..60bc7a7 --- /dev/null +++ b/libcurl/src/include/curl/curlbuild.h.cmake @@ -0,0 +1,197 @@ +#ifndef __CURL_CURLBUILD_H +#define __CURL_CURLBUILD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * If you think that something actually needs to be changed, adjusted + * or fixed in this file, then, report it on the libcurl development + * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * This header file shall only export symbols which are 'curl' or 'CURL' + * prefixed, otherwise public name space would be polluted. + * + * NOTE 2: + * ------- + * + * Right now you might be staring at file include/curl/curlbuild.h.in or + * at file include/curl/curlbuild.h, this is due to the following reason: + * + * On systems capable of running the configure script, the configure process + * will overwrite the distributed include/curl/curlbuild.h file with one that + * is suitable and specific to the library being configured and built, which + * is generated from the include/curl/curlbuild.h.in template file. + * + */ + +/* ================================================================ */ +/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ +/* ================================================================ */ + +#ifdef CURL_SIZEOF_LONG +#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T +#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_SOCKLEN_T +#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_OFF_T +#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_T +#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_TU +#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined +#endif + +#ifdef CURL_FORMAT_OFF_T +#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_OFF_T +#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_T +#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_TU +#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined +#endif + +/* ================================================================ */ +/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ +/* ================================================================ */ + +/* Configure process defines this to 1 when it finds out that system */ +/* header file ws2tcpip.h must be included by the external interface. */ +#cmakedefine CURL_PULL_WS2TCPIP_H +#ifdef CURL_PULL_WS2TCPIP_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# include +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/types.h must be included by the external interface. */ +#cmakedefine CURL_PULL_SYS_TYPES_H +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file stdint.h must be included by the external interface. */ +#cmakedefine CURL_PULL_STDINT_H +#ifdef CURL_PULL_STDINT_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file inttypes.h must be included by the external interface. */ +#cmakedefine CURL_PULL_INTTYPES_H +#ifdef CURL_PULL_INTTYPES_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/socket.h must be included by the external interface. */ +#cmakedefine CURL_PULL_SYS_SOCKET_H +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/poll.h must be included by the external interface. */ +#cmakedefine CURL_PULL_SYS_POLL_H +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* The size of `long', as computed by sizeof. */ +#define CURL_SIZEOF_LONG ${CURL_SIZEOF_LONG} + +/* Integral data type used for curl_socklen_t. */ +#define CURL_TYPEOF_CURL_SOCKLEN_T ${CURL_TYPEOF_CURL_SOCKLEN_T} + +/* The size of `curl_socklen_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_SOCKLEN_T ${CURL_SIZEOF_CURL_SOCKLEN_T} + +/* Data type definition of curl_socklen_t. */ +typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; + +/* Signed integral data type used for curl_off_t. */ +#define CURL_TYPEOF_CURL_OFF_T ${CURL_TYPEOF_CURL_OFF_T} + +/* Data type definition of curl_off_t. */ +typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; + +/* curl_off_t formatting string directive without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_T "${CURL_FORMAT_CURL_OFF_T}" + +/* unsigned curl_off_t formatting string without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_TU "${CURL_FORMAT_CURL_OFF_TU}" + +/* curl_off_t formatting string directive with "%" conversion specifier. */ +#define CURL_FORMAT_OFF_T "${CURL_FORMAT_OFF_T}" + +/* The size of `curl_off_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_OFF_T ${CURL_SIZEOF_CURL_OFF_T} + +/* curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_T ${CURL_SUFFIX_CURL_OFF_T} + +/* unsigned curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_TU ${CURL_SUFFIX_CURL_OFF_TU} + +#endif /* __CURL_CURLBUILD_H */ diff --git a/libcurl/src/include/curl/curlbuild.h.in b/libcurl/src/include/curl/curlbuild.h.in new file mode 100644 index 0000000..e29f195 --- /dev/null +++ b/libcurl/src/include/curl/curlbuild.h.in @@ -0,0 +1,197 @@ +#ifndef __CURL_CURLBUILD_H +#define __CURL_CURLBUILD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * If you think that something actually needs to be changed, adjusted + * or fixed in this file, then, report it on the libcurl development + * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * This header file shall only export symbols which are 'curl' or 'CURL' + * prefixed, otherwise public name space would be polluted. + * + * NOTE 2: + * ------- + * + * Right now you might be staring at file include/curl/curlbuild.h.in or + * at file include/curl/curlbuild.h, this is due to the following reason: + * + * On systems capable of running the configure script, the configure process + * will overwrite the distributed include/curl/curlbuild.h file with one that + * is suitable and specific to the library being configured and built, which + * is generated from the include/curl/curlbuild.h.in template file. + * + */ + +/* ================================================================ */ +/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ +/* ================================================================ */ + +#ifdef CURL_SIZEOF_LONG +#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T +#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_SOCKLEN_T +#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_OFF_T +#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_T +#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_TU +#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined +#endif + +#ifdef CURL_FORMAT_OFF_T +#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_OFF_T +#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_T +#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_TU +#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined +#endif + +/* ================================================================ */ +/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ +/* ================================================================ */ + +/* Configure process defines this to 1 when it finds out that system */ +/* header file ws2tcpip.h must be included by the external interface. */ +#undef CURL_PULL_WS2TCPIP_H +#ifdef CURL_PULL_WS2TCPIP_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# include +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/types.h must be included by the external interface. */ +#undef CURL_PULL_SYS_TYPES_H +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file stdint.h must be included by the external interface. */ +#undef CURL_PULL_STDINT_H +#ifdef CURL_PULL_STDINT_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file inttypes.h must be included by the external interface. */ +#undef CURL_PULL_INTTYPES_H +#ifdef CURL_PULL_INTTYPES_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/socket.h must be included by the external interface. */ +#undef CURL_PULL_SYS_SOCKET_H +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/poll.h must be included by the external interface. */ +#undef CURL_PULL_SYS_POLL_H +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* The size of `long', as computed by sizeof. */ +#undef CURL_SIZEOF_LONG + +/* Integral data type used for curl_socklen_t. */ +#undef CURL_TYPEOF_CURL_SOCKLEN_T + +/* The size of `curl_socklen_t', as computed by sizeof. */ +#undef CURL_SIZEOF_CURL_SOCKLEN_T + +/* Data type definition of curl_socklen_t. */ +typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; + +/* Signed integral data type used for curl_off_t. */ +#undef CURL_TYPEOF_CURL_OFF_T + +/* Data type definition of curl_off_t. */ +typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; + +/* curl_off_t formatting string directive without "%" conversion specifier. */ +#undef CURL_FORMAT_CURL_OFF_T + +/* unsigned curl_off_t formatting string without "%" conversion specifier. */ +#undef CURL_FORMAT_CURL_OFF_TU + +/* curl_off_t formatting string directive with "%" conversion specifier. */ +#undef CURL_FORMAT_OFF_T + +/* The size of `curl_off_t', as computed by sizeof. */ +#undef CURL_SIZEOF_CURL_OFF_T + +/* curl_off_t constant suffix. */ +#undef CURL_SUFFIX_CURL_OFF_T + +/* unsigned curl_off_t constant suffix. */ +#undef CURL_SUFFIX_CURL_OFF_TU + +#endif /* __CURL_CURLBUILD_H */ diff --git a/libcurl/src/include/curl/curlrules.h b/libcurl/src/include/curl/curlrules.h new file mode 100644 index 0000000..7c2ede3 --- /dev/null +++ b/libcurl/src/include/curl/curlrules.h @@ -0,0 +1,262 @@ +#ifndef __CURL_CURLRULES_H +#define __CURL_CURLRULES_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* COMPILE TIME SANITY CHECKS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * All checks done in this file are intentionally placed in a public + * header file which is pulled by curl/curl.h when an application is + * being built using an already built libcurl library. Additionally + * this file is also included and used when building the library. + * + * If compilation fails on this file it is certainly sure that the + * problem is elsewhere. It could be a problem in the curlbuild.h + * header file, or simply that you are using different compilation + * settings than those used to build the library. + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * Do not deactivate any check, these are done to make sure that the + * library is properly built and used. + * + * You can find further help on the libcurl development mailing list: + * http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * NOTE 2 + * ------ + * + * Some of the following compile time checks are based on the fact + * that the dimension of a constant array can not be a negative one. + * In this way if the compile time verification fails, the compilation + * will fail issuing an error. The error description wording is compiler + * dependent but it will be quite similar to one of the following: + * + * "negative subscript or subscript is too large" + * "array must have at least one element" + * "-1 is an illegal array size" + * "size of array is negative" + * + * If you are building an application which tries to use an already + * built libcurl library and you are getting this kind of errors on + * this file, it is a clear indication that there is a mismatch between + * how the library was built and how you are trying to use it for your + * application. Your already compiled or binary library provider is the + * only one who can give you the details you need to properly use it. + */ + +/* + * Verify that some macros are actually defined. + */ + +#ifndef CURL_SIZEOF_LONG +# error "CURL_SIZEOF_LONG definition is missing!" + Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing +#endif + +#ifndef CURL_TYPEOF_CURL_SOCKLEN_T +# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing +#endif + +#ifndef CURL_SIZEOF_CURL_SOCKLEN_T +# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing +#endif + +#ifndef CURL_TYPEOF_CURL_OFF_T +# error "CURL_TYPEOF_CURL_OFF_T definition is missing!" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing +#endif + +#ifndef CURL_FORMAT_CURL_OFF_T +# error "CURL_FORMAT_CURL_OFF_T definition is missing!" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing +#endif + +#ifndef CURL_FORMAT_CURL_OFF_TU +# error "CURL_FORMAT_CURL_OFF_TU definition is missing!" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing +#endif + +#ifndef CURL_FORMAT_OFF_T +# error "CURL_FORMAT_OFF_T definition is missing!" + Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing +#endif + +#ifndef CURL_SIZEOF_CURL_OFF_T +# error "CURL_SIZEOF_CURL_OFF_T definition is missing!" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing +#endif + +#ifndef CURL_SUFFIX_CURL_OFF_T +# error "CURL_SUFFIX_CURL_OFF_T definition is missing!" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing +#endif + +#ifndef CURL_SUFFIX_CURL_OFF_TU +# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing +#endif + +/* + * Macros private to this header file. + */ + +#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1 + +#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1 + +/* + * Verify that the size previously defined and expected for long + * is the same as the one reported by sizeof() at compile time. + */ + +typedef char + __curl_rule_01__ + [CurlchkszEQ(long, CURL_SIZEOF_LONG)]; + +/* + * Verify that the size previously defined and expected for + * curl_off_t is actually the the same as the one reported + * by sizeof() at compile time. + */ + +typedef char + __curl_rule_02__ + [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)]; + +/* + * Verify at compile time that the size of curl_off_t as reported + * by sizeof() is greater or equal than the one reported for long + * for the current compilation. + */ + +typedef char + __curl_rule_03__ + [CurlchkszGE(curl_off_t, long)]; + +/* + * Verify that the size previously defined and expected for + * curl_socklen_t is actually the the same as the one reported + * by sizeof() at compile time. + */ + +typedef char + __curl_rule_04__ + [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)]; + +/* + * Verify at compile time that the size of curl_socklen_t as reported + * by sizeof() is greater or equal than the one reported for int for + * the current compilation. + */ + +typedef char + __curl_rule_05__ + [CurlchkszGE(curl_socklen_t, int)]; + +/* ================================================================ */ +/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */ +/* ================================================================ */ + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define __CURL_OFF_T_C_HLPR2(x) x +# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ + __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ + __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +/* + * Get rid of macros private to this header file. + */ + +#undef CurlchkszEQ +#undef CurlchkszGE + +/* + * Get rid of macros not intended to exist beyond this point. + */ + +#undef CURL_PULL_WS2TCPIP_H +#undef CURL_PULL_SYS_TYPES_H +#undef CURL_PULL_SYS_SOCKET_H +#undef CURL_PULL_SYS_POLL_H +#undef CURL_PULL_STDINT_H +#undef CURL_PULL_INTTYPES_H + +#undef CURL_TYPEOF_CURL_SOCKLEN_T +#undef CURL_TYPEOF_CURL_OFF_T + +#ifdef CURL_NO_OLDIES +#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */ +#endif + +#endif /* __CURL_CURLRULES_H */ diff --git a/libcurl/src/include/curl/curlver.h b/libcurl/src/include/curl/curlver.h new file mode 100644 index 0000000..7976c1f --- /dev/null +++ b/libcurl/src/include/curl/curlver.h @@ -0,0 +1,69 @@ +#ifndef __CURL_CURLVER_H +#define __CURL_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2015 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.42.1" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 42 +#define LIBCURL_VERSION_PATCH 1 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparions by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. +*/ +#define LIBCURL_VERSION_NUM 0x072a01 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date should follow this template: + * + * "Mon Feb 12 11:35:33 UTC 2007" + */ +#define LIBCURL_TIMESTAMP "Wed Apr 29 06:07:13 UTC 2015" + +#endif /* __CURL_CURLVER_H */ diff --git a/libcurl/src/include/curl/easy.h b/libcurl/src/include/curl/easy.h new file mode 100644 index 0000000..c1e3e76 --- /dev/null +++ b/libcurl/src/include/curl/easy.h @@ -0,0 +1,102 @@ +#ifndef __CURL_EASY_H +#define __CURL_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libcurl/src/include/curl/mprintf.h b/libcurl/src/include/curl/mprintf.h new file mode 100644 index 0000000..c6b0d76 --- /dev/null +++ b/libcurl/src/include/curl/mprintf.h @@ -0,0 +1,74 @@ +#ifndef __CURL_MPRINTF_H +#define __CURL_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef _MPRINTF_REPLACE +# undef printf +# undef fprintf +# undef sprintf +# undef vsprintf +# undef snprintf +# undef vprintf +# undef vfprintf +# undef vsnprintf +# undef aprintf +# undef vaprintf +# define printf curl_mprintf +# define fprintf curl_mfprintf +# define sprintf curl_msprintf +# define vsprintf curl_mvsprintf +# define snprintf curl_msnprintf +# define vprintf curl_mvprintf +# define vfprintf curl_mvfprintf +# define vsnprintf curl_mvsnprintf +# define aprintf curl_maprintf +# define vaprintf curl_mvaprintf +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __CURL_MPRINTF_H */ diff --git a/libcurl/src/include/curl/multi.h b/libcurl/src/include/curl/multi.h new file mode 100644 index 0000000..d5776b3 --- /dev/null +++ b/libcurl/src/include/curl/multi.h @@ -0,0 +1,400 @@ +#ifndef __CURL_MULTI_H +#define __CURL_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void CURLM; + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on invidual transfers even when this + * returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic informations. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a zero-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#if !defined(CURL_ALLOW_OLD_MULTI_SOCKET) && !defined(BUILDING_LIBCURL) +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#undef curl_multi_socket +#define curl_multi_socket(x,y,z) sk_expand(curl_multi_socket_action)(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +#undef CINIT /* re-using the same name as in curl.h */ + +#ifdef CURL_ISOCPP +#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLMOPT_/**/name = type + number +#endif + +typedef enum { + /* This is the socket callback function pointer */ + CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CINIT(SOCKETDATA, OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CINIT(PIPELINING, LONG, 3), + + /* This is the timer callback function pointer */ + CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CINIT(TIMERDATA, OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CINIT(MAXCONNECTS, LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CINIT(MAX_HOST_CONNECTIONS, LONG, 7), + + /* maximum number of requests in a pipeline */ + CINIT(MAX_PIPELINE_LENGTH, LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10), + + /* a list of site names(+port) that are blacklisted from + pipelining */ + CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11), + + /* a list of server types that are blacklisted from + pipelining */ + CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/libcurl/src/include/curl/stdcheaders.h b/libcurl/src/include/curl/stdcheaders.h new file mode 100644 index 0000000..ad82ef6 --- /dev/null +++ b/libcurl/src/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef __STDC_HEADERS_H +#define __STDC_HEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread (void *, size_t, size_t, FILE *); +size_t fwrite (const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* __STDC_HEADERS_H */ diff --git a/libcurl/src/include/curl/typecheck-gcc.h b/libcurl/src/include/curl/typecheck-gcc.h new file mode 100644 index 0000000..69d41a2 --- /dev/null +++ b/libcurl/src/include/curl/typecheck-gcc.h @@ -0,0 +1,610 @@ +#ifndef __CURL_TYPECHECK_GCC_H +#define __CURL_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(_curl_is_sometype_option(_curl_opt)) + * if(!_curl_is_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define _curl_is_sometype_option, _curl_is_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ +__extension__ ({ \ + __typeof__ (option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(_curl_is_long_option(_curl_opt)) \ + if(!_curl_is_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(_curl_is_off_t_option(_curl_opt)) \ + if(!_curl_is_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(_curl_is_string_option(_curl_opt)) \ + if(!_curl_is_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(_curl_is_write_cb_option(_curl_opt)) \ + if(!_curl_is_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!_curl_is_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!_curl_is_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!_curl_is_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!_curl_is_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!_curl_is_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!_curl_is_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!_curl_is_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(_curl_is_conv_cb_option(_curl_opt)) \ + if(!_curl_is_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!_curl_is_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(_curl_is_cb_data_option(_curl_opt)) \ + if(!_curl_is_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!_curl_is_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!_curl_is_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(_curl_is_postfields_option(_curl_opt)) \ + if(!_curl_is_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!_curl_is_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if(_curl_is_slist_option(_curl_opt)) \ + if(!_curl_is_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!_curl_is_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ +}) + +/* wraps curl_easy_getinfo() with typechecking */ +/* FIXME: don't allow const pointers */ +#define curl_easy_getinfo(handle, info, arg) \ +__extension__ ({ \ + __typeof__ (info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(_curl_is_string_info(_curl_info)) \ + if(!_curl_is_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(_curl_is_long_info(_curl_info)) \ + if(!_curl_is_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(_curl_is_double_info(_curl_info)) \ + if(!_curl_is_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(_curl_is_slist_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ +}) + +/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(), + * for now just make sure that the functions are called with three + * arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define _CURL_WARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +_CURL_WARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string (char* or char[]) argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a FILE* argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a void* or char* argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a struct curl_httppost* argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a struct curl_slist* argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +_CURL_WARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to char * for this info") +_CURL_WARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +_CURL_WARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to struct curl_slist * for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define _curl_is_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define _curl_is_off_t_option(option) \ + ((option) > CURLOPTTYPE_OFF_T) + +/* evaluates to true if option takes a char* argument */ +#define _curl_is_string_option(option) \ + ((option) == CURLOPT_URL || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define _curl_is_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define _curl_is_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define _curl_is_cb_data_option(option) \ + ((option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_PRIVATE || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define _curl_is_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define _curl_is_slist_option(option) \ + ((option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + (option) == CURLOPT_MAIL_RCPT || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define _curl_is_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) + +/* evaluates to true if info expects a pointer to long argument */ +#define _curl_is_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define _curl_is_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define _curl_is_slist_info(info) \ + (CURLINFO_SLIST < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true iff expr is a pointer */ +#define _curl_is_any_ptr(expr) \ + (sizeof(expr) == sizeof(void*)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define _curl_is_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define _curl_is_ptr(expr, type) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define _curl_is_arr(expr, type) \ + (_curl_is_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define _curl_is_string(expr) \ + (_curl_is_arr((expr), char) || \ + _curl_is_arr((expr), signed char) || \ + _curl_is_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define _curl_is_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define _curl_is_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define _curl_is_error_buffer(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define _curl_is_cb_data(expr) \ + (_curl_is_ptr((expr), void) || \ + _curl_is_ptr((expr), FILE)) +#else /* be less strict */ +#define _curl_is_cb_data(expr) \ + _curl_is_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define _curl_is_FILE(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *)) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define _curl_is_postfields(expr) \ + (_curl_is_ptr((expr), void) || \ + _curl_is_arr((expr), char)) + +/* FIXME: the whole callback checking is messy... + * The idea is to tolerate char vs. void and const vs. not const + * pointers in arguments at least + */ +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define _curl_callback_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func), type*)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define _curl_is_read_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \ + _curl_callback_compatible((expr), _curl_read_callback1) || \ + _curl_callback_compatible((expr), _curl_read_callback2) || \ + _curl_callback_compatible((expr), _curl_read_callback3) || \ + _curl_callback_compatible((expr), _curl_read_callback4) || \ + _curl_callback_compatible((expr), _curl_read_callback5) || \ + _curl_callback_compatible((expr), _curl_read_callback6)) +typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*); +typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*); +typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*); +typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*); +typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*); +typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define _curl_is_write_cb(expr) \ + (_curl_is_read_cb(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \ + _curl_callback_compatible((expr), _curl_write_callback1) || \ + _curl_callback_compatible((expr), _curl_write_callback2) || \ + _curl_callback_compatible((expr), _curl_write_callback3) || \ + _curl_callback_compatible((expr), _curl_write_callback4) || \ + _curl_callback_compatible((expr), _curl_write_callback5) || \ + _curl_callback_compatible((expr), _curl_write_callback6)) +typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*); +typedef size_t (_curl_write_callback2)(const char *, size_t, size_t, + const void*); +typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*); +typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*); +typedef size_t (_curl_write_callback5)(const void *, size_t, size_t, + const void*); +typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define _curl_is_ioctl_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback1) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback2) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback3) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*); +typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*); +typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*); +typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define _curl_is_sockopt_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \ + _curl_callback_compatible((expr), _curl_sockopt_callback1) || \ + _curl_callback_compatible((expr), _curl_sockopt_callback2)) +typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define _curl_is_opensocket_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\ + _curl_callback_compatible((expr), _curl_opensocket_callback1) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback2) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback3) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define _curl_is_progress_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \ + _curl_callback_compatible((expr), _curl_progress_callback1) || \ + _curl_callback_compatible((expr), _curl_progress_callback2)) +typedef int (_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define _curl_is_debug_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \ + _curl_callback_compatible((expr), _curl_debug_callback1) || \ + _curl_callback_compatible((expr), _curl_debug_callback2) || \ + _curl_callback_compatible((expr), _curl_debug_callback3) || \ + _curl_callback_compatible((expr), _curl_debug_callback4) || \ + _curl_callback_compatible((expr), _curl_debug_callback5) || \ + _curl_callback_compatible((expr), _curl_debug_callback6) || \ + _curl_callback_compatible((expr), _curl_debug_callback7) || \ + _curl_callback_compatible((expr), _curl_debug_callback8)) +typedef int (_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define _curl_is_ssl_ctx_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); +typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); +typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); +typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define _curl_is_conv_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \ + _curl_callback_compatible((expr), _curl_conv_callback1) || \ + _curl_callback_compatible((expr), _curl_conv_callback2) || \ + _curl_callback_compatible((expr), _curl_conv_callback3) || \ + _curl_callback_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define _curl_is_seek_cb(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \ + _curl_callback_compatible((expr), _curl_seek_callback1) || \ + _curl_callback_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* __CURL_TYPECHECK_GCC_H */ diff --git a/libcurl/src/lib/amigaos.c b/libcurl/src/lib/amigaos.c new file mode 100644 index 0000000..10783b2 --- /dev/null +++ b/libcurl/src/lib/amigaos.c @@ -0,0 +1,77 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(__AMIGA__) && !defined(__ixemul__) + +#include + +#include "amigaos.h" + +struct Library *SocketBase = NULL; +extern int errno, h_errno; + +#ifdef __libnix__ +#include +void __request(const char *msg); +#else +# define __request( msg ) Printf( msg "\n\a") +#endif + +CURL_STATIC void Curl_amiga_cleanup() +{ + if(SocketBase) { + CloseLibrary(SocketBase); + SocketBase = NULL; + } +} + +CURL_STATIC bool Curl_amiga_init() +{ + if(!SocketBase) + SocketBase = OpenLibrary("bsdsocket.library", 4); + + if(!SocketBase) { + __request("No TCP/IP Stack running!"); + return FALSE; + } + + if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno, + SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL", + TAG_DONE)) { + __request("SocketBaseTags ERROR"); + return FALSE; + } + +#ifndef __libnix__ + atexit(Curl_amiga_cleanup); +#endif + + return TRUE; +} + +#ifdef __libnix__ +ADD2EXIT(Curl_amiga_cleanup, -50); +#endif + +#endif /* __AMIGA__ && ! __ixemul__ */ diff --git a/libcurl/src/lib/amigaos.h b/libcurl/src/lib/amigaos.h new file mode 100644 index 0000000..7e61cab --- /dev/null +++ b/libcurl/src/lib/amigaos.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_AMIGAOS_H +#define HEADER_CURL_AMIGAOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(__AMIGA__) && !defined(__ixemul__) + +CURL_STATIC bool Curl_amiga_init(); +CURL_STATIC void Curl_amiga_cleanup(); + +#else + +#define Curl_amiga_init() 1 +#define Curl_amiga_cleanup() Curl_nop_stmt + +#endif + +#endif /* HEADER_CURL_AMIGAOS_H */ + diff --git a/libcurl/src/lib/arpa_telnet.h b/libcurl/src/lib/arpa_telnet.h new file mode 100644 index 0000000..098d9a9 --- /dev/null +++ b/libcurl/src/lib/arpa_telnet.h @@ -0,0 +1,104 @@ +#ifndef HEADER_CURL_ARPA_TELNET_H +#define HEADER_CURL_ARPA_TELNET_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET +/* + * Telnet option defines. Add more here if in need. + */ +#define CURL_TELOPT_BINARY 0 /* binary 8bit data */ +#define CURL_TELOPT_ECHO 1 /* just echo! */ +#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */ +#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */ +#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */ +#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */ +#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */ + +#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */ +#define CURL_NEW_ENV_VAR 0 +#define CURL_NEW_ENV_VALUE 1 + +/* + * The telnet options represented as strings + */ +static const char * const telnetoptions[]= +{ + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", + "NAME", "STATUS", "TIMING MARK", "RCTE", + "NAOL", "NAOP", "NAOCRD", "NAOHTS", + "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", + "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", + "TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", + "TTYLOC", "3270 REGIME", "X3 PAD", "NAWS", + "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC", + "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON" +}; + +#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON + +#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM) +#define CURL_TELOPT(x) telnetoptions[x] + +#define CURL_NTELOPTS 40 + +/* + * First some defines + */ +#define CURL_xEOF 236 /* End Of File */ +#define CURL_SE 240 /* Sub negotiation End */ +#define CURL_NOP 241 /* No OPeration */ +#define CURL_DM 242 /* Data Mark */ +#define CURL_GA 249 /* Go Ahead, reverse the line */ +#define CURL_SB 250 /* SuBnegotiation */ +#define CURL_WILL 251 /* Our side WILL use this option */ +#define CURL_WONT 252 /* Our side WON'T use this option */ +#define CURL_DO 253 /* DO use this option! */ +#define CURL_DONT 254 /* DON'T use this option! */ +#define CURL_IAC 255 /* Interpret As Command */ + +/* + * Then those numbers represented as strings: + */ +static const char * const telnetcmds[]= +{ + "EOF", "SUSP", "ABORT", "EOR", "SE", + "NOP", "DMARK", "BRK", "IP", "AO", + "AYT", "EC", "EL", "GA", "SB", + "WILL", "WONT", "DO", "DONT", "IAC" +}; + +#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */ +#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */ + +#define CURL_TELQUAL_IS 0 +#define CURL_TELQUAL_SEND 1 +#define CURL_TELQUAL_INFO 2 +#define CURL_TELQUAL_NAME 3 + +#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \ + ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) ) +#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM] + +#endif /* CURL_DISABLE_TELNET */ + +#endif /* HEADER_CURL_ARPA_TELNET_H */ diff --git a/libcurl/src/lib/asyn-ares.c b/libcurl/src/lib/asyn-ares.c new file mode 100644 index 0000000..4819a09 --- /dev/null +++ b/libcurl/src/lib/asyn-ares.c @@ -0,0 +1,691 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +/*********************************************************************** + * Only for ares-enabled builds + * And only for functions that fulfill the asynch resolver backend API + * as defined in asyn.h, nothing else belongs in this file! + **********************************************************************/ + +#ifdef CURLRES_ARES + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "multiif.h" +#include "inet_pton.h" +#include "connect.h" +#include "select.h" +#include "progress.h" +#include "curl_printf.h" + +# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) +# define CARES_STATICLIB +# endif +# include +# include /* really old c-ares didn't include this by + itself */ + +#if ARES_VERSION >= 0x010500 +/* c-ares 1.5.0 or later, the callback proto is modified */ +#define HAVE_CARES_CALLBACK_TIMEOUTS 1 +#endif + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +struct ResolverResults { + int num_pending; /* number of ares_gethostbyname() requests */ + Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ + int last_status; +}; + +/* + * Curl_resolver_global_init() - the generic low-level asynchronous name + * resolve API. Called from curl_global_init() to initialize global resolver + * environment. Initializes ares library. + */ +CURL_STATIC int Curl_resolver_global_init(void) +{ +#ifdef CARES_HAVE_ARES_LIBRARY_INIT + if(ares_library_init(ARES_LIB_INIT_ALL)) { + return CURLE_FAILED_INIT; + } +#endif + return CURLE_OK; +} + +/* + * Curl_resolver_global_cleanup() + * + * Called from curl_global_cleanup() to destroy global resolver environment. + * Deinitializes ares library. + */ +CURL_STATIC void Curl_resolver_global_cleanup(void) +{ +#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP + ares_library_cleanup(); +#endif +} + +/* + * Curl_resolver_init() + * + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Fills the passed pointer by the initialized ares_channel. + */ +CURL_STATIC CURLcode Curl_resolver_init(void **resolver) +{ + int status = ares_init((ares_channel*)resolver); + if(status != ARES_SUCCESS) { + if(status == ARES_ENOMEM) + return CURLE_OUT_OF_MEMORY; + else + return CURLE_FAILED_INIT; + } + return CURLE_OK; + /* make sure that all other returns from this function should destroy the + ares channel before returning error! */ +} + +/* + * Curl_resolver_cleanup() + * + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Destroys the ares channel. + */ +CURL_STATIC void Curl_resolver_cleanup(void *resolver) +{ + ares_destroy((ares_channel)resolver); +} + +/* + * Curl_resolver_duphandle() + * + * Called from curl_easy_duphandle() to duplicate resolver URL-state specific + * environment ('resolver' member of the UrlState structure). Duplicates the + * 'from' ares channel and passes the resulting channel to the 'to' pointer. + */ +CURL_STATIC int Curl_resolver_duphandle(void **to, void *from) +{ + /* Clone the ares channel for the new handle */ + if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from)) + return CURLE_FAILED_INIT; + return CURLE_OK; +} + +static void destroy_async_data (struct Curl_async *async); + +/* + * Cancel all possibly still on-going resolves for this connection. + */ +CURL_STATIC void Curl_resolver_cancel(struct connectdata *conn) +{ + if(conn->data && conn->data->state.resolver) + ares_cancel((ares_channel)conn->data->state.resolver); + destroy_async_data(&conn->async); +} + +/* + * destroy_async_data() cleans up async resolver data. + */ +static void destroy_async_data (struct Curl_async *async) +{ + free(async->hostname); + + if(async->os_specific) { + struct ResolverResults *res = (struct ResolverResults *)async->os_specific; + if(res) { + if(res->temp_ai) { + Curl_freeaddrinfo(res->temp_ai); + res->temp_ai = NULL; + } + free(res); + } + async->os_specific = NULL; + } + + async->hostname = NULL; +} + +/* + * Curl_resolver_getsock() is called when someone from the outside world + * (using curl_multi_fdset()) wants to get our fd_set setup and we're talking + * with ares. The caller must make sure that this function is only called when + * we have a working ares channel. + * + * Returns: sockets-in-use-bitmap + */ + +CURL_STATIC int Curl_resolver_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) + +{ + struct timeval maxtime; + struct timeval timebuf; + struct timeval *timeout; + long milli; + int max = ares_getsock((ares_channel)conn->data->state.resolver, + (ares_socket_t *)socks, numsocks); + + maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; + maxtime.tv_usec = 0; + + timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, + &timebuf); + milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000); + if(milli == 0) + milli += 10; + Curl_expire_latest(conn->data, milli); + + return max; +} + +/* + * waitperform() + * + * 1) Ask ares what sockets it currently plays with, then + * 2) wait for the timeout period to check for action on ares' sockets. + * 3) tell ares to act on all the sockets marked as "with action" + * + * return number of sockets it worked on + */ + +static int waitperform(struct connectdata *conn, int timeout_ms) +{ + struct SessionHandle *data = conn->data; + int nfds; + int bitmask; + ares_socket_t socks[ARES_GETSOCK_MAXNUM]; + struct pollfd pfd[ARES_GETSOCK_MAXNUM]; + int i; + int num = 0; + + bitmask = ares_getsock((ares_channel)data->state.resolver, socks, + ARES_GETSOCK_MAXNUM); + + for(i=0; i < ARES_GETSOCK_MAXNUM; i++) { + pfd[i].events = 0; + pfd[i].revents = 0; + if(ARES_GETSOCK_READABLE(bitmask, i)) { + pfd[i].fd = socks[i]; + pfd[i].events |= POLLRDNORM|POLLIN; + } + if(ARES_GETSOCK_WRITABLE(bitmask, i)) { + pfd[i].fd = socks[i]; + pfd[i].events |= POLLWRNORM|POLLOUT; + } + if(pfd[i].events != 0) + num++; + else + break; + } + + if(num) + nfds = Curl_poll(pfd, num, timeout_ms); + else + nfds = 0; + + if(!nfds) + /* Call ares_process() unconditonally here, even if we simply timed out + above, as otherwise the ares name resolve won't timeout! */ + ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD, + ARES_SOCKET_BAD); + else { + /* move through the descriptors and ask for processing on them */ + for(i=0; i < num; i++) + ares_process_fd((ares_channel)data->state.resolver, + pfd[i].revents & (POLLRDNORM|POLLIN)? + pfd[i].fd:ARES_SOCKET_BAD, + pfd[i].revents & (POLLWRNORM|POLLOUT)? + pfd[i].fd:ARES_SOCKET_BAD); + } + return nfds; +} + +/* + * Curl_resolver_is_resolved() is called repeatedly to check if a previous + * name resolve request has completed. It should also make sure to time-out if + * the operation seems to take too long. + * + * Returns normal CURLcode errors. + */ +CURL_STATIC CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns) +{ + struct SessionHandle *data = conn->data; + struct ResolverResults *res = (struct ResolverResults *) + conn->async.os_specific; + CURLcode result = CURLE_OK; + + *dns = NULL; + + waitperform(conn, 0); + + if(res && !res->num_pending) { + (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai); + /* temp_ai ownership is moved to the connection, so we need not free-up + them */ + res->temp_ai = NULL; + if(!conn->async.dns) { + failf(data, "Could not resolve: %s (%s)", + conn->async.hostname, ares_strerror(conn->async.status)); + result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: + CURLE_COULDNT_RESOLVE_HOST; + } + else + *dns = conn->async.dns; + + destroy_async_data(&conn->async); + } + + return result; +} + +/* + * Curl_resolver_wait_resolv() + * + * waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and + * CURLE_OPERATION_TIMEDOUT if a time-out occurred. + */ +CURL_STATIC CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + long timeout; + struct timeval now = Curl_tvnow(); + struct Curl_dns_entry *temp_entry; + + timeout = Curl_timeleft(data, &now, TRUE); + if(!timeout) + timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */ + + /* Wait for the name resolve query to complete. */ + for(;;) { + struct timeval *tvp, tv, store; + long timediff; + int itimeout; + int timeout_ms; + + itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; + + store.tv_sec = itimeout/1000; + store.tv_usec = (itimeout%1000)*1000; + + tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv); + + /* use the timeout period ares returned to us above if less than one + second is left, otherwise just use 1000ms to make sure the progress + callback gets called frequent enough */ + if(!tvp->tv_sec) + timeout_ms = (int)(tvp->tv_usec/1000); + else + timeout_ms = 1000; + + waitperform(conn, timeout_ms); + Curl_resolver_is_resolved(conn, &temp_entry); + + if(conn->async.done) + break; + + if(Curl_pgrsUpdate(conn)) { + result = CURLE_ABORTED_BY_CALLBACK; + timeout = -1; /* trigger the cancel below */ + } + else { + struct timeval now2 = Curl_tvnow(); + timediff = Curl_tvdiff(now2, now); /* spent time */ + timeout -= timediff?timediff:1; /* always deduct at least 1 */ + now = now2; /* for next loop */ + } + + if(timeout < 0) { + /* our timeout, so we cancel the ares operation */ + ares_cancel((ares_channel)data->state.resolver); + break; + } + } + + /* Operation complete, if the lookup was successful we now have the entry + in the cache. */ + if(entry) + *entry = conn->async.dns; + + if(result) + /* close the connection, since we can't return failure here without + cleaning up this connection properly. + TODO: remove this action from here, it is not a name resolver decision. + */ + connclose(conn, "c-ares resolve failed"); + + return result; +} + +/* Connects results to the list */ +static void compound_results(struct ResolverResults *res, + Curl_addrinfo *ai) +{ + Curl_addrinfo *ai_tail; + if(!ai) + return; + ai_tail = ai; + + while(ai_tail->ai_next) + ai_tail = ai_tail->ai_next; + + /* Add the new results to the list of old results. */ + ai_tail->ai_next = res->temp_ai; + res->temp_ai = ai; +} + +/* + * ares_query_completed_cb() is the callback that ares will call when + * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(), + * when using ares, is completed either successfully or with failure. + */ +static void query_completed_cb(void *arg, /* (struct connectdata *) */ + int status, +#ifdef HAVE_CARES_CALLBACK_TIMEOUTS + int timeouts, +#endif + struct hostent *hostent) +{ + struct connectdata *conn = (struct connectdata *)arg; + struct ResolverResults *res; + +#ifdef HAVE_CARES_CALLBACK_TIMEOUTS + (void)timeouts; /* ignored */ +#endif + + if(ARES_EDESTRUCTION == status) + /* when this ares handle is getting destroyed, the 'arg' pointer may not + be valid so only defer it when we know the 'status' says its fine! */ + return; + + res = (struct ResolverResults *)conn->async.os_specific; + res->num_pending--; + + if(CURL_ASYNC_SUCCESS == status) { + Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port); + if(ai) { + compound_results(res, ai); + } + } + /* A successful result overwrites any previous error */ + if(res->last_status != ARES_SUCCESS) + res->last_status = status; +} + +/* + * Curl_resolver_getaddrinfo() - when using ares + * + * Returns name information about the given hostname and port number. If + * successful, the 'hostent' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + */ +CURL_STATIC Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + char *bufp; + struct SessionHandle *data = conn->data; + struct in_addr in; + int family = PF_INET; +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + struct in6_addr in6; +#endif /* CURLRES_IPV6 */ + + *waitp = 0; /* default to synchronous response */ + + /* First check if this is an IPv4 address string */ + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + } + +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + /* Otherwise, check if this is an IPv6 address string */ + if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) + /* This must be an IPv6 address literal. */ + return Curl_ip2addr(AF_INET6, &in6, hostname, port); + + switch(conn->ip_version) { + default: +#if ARES_VERSION >= 0x010601 + family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older + c-ares versions this just falls through and defaults + to PF_INET */ + break; +#endif + case CURL_IPRESOLVE_V4: + family = PF_INET; + break; + case CURL_IPRESOLVE_V6: + family = PF_INET6; + break; + } +#endif /* CURLRES_IPV6 */ + + bufp = strdup(hostname); + if(bufp) { + struct ResolverResults *res = NULL; + free(conn->async.hostname); + conn->async.hostname = bufp; + conn->async.port = port; + conn->async.done = FALSE; /* not done */ + conn->async.status = 0; /* clear */ + conn->async.dns = NULL; /* clear */ + res = calloc(sizeof(struct ResolverResults), 1); + if(!res) { + free(conn->async.hostname); + conn->async.hostname = NULL; + return NULL; + } + conn->async.os_specific = res; + + /* initial status - failed */ + res->last_status = ARES_ENOTFOUND; +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + if(family == PF_UNSPEC) { + if(Curl_ipv6works()) { + res->num_pending = 2; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET, query_completed_cb, conn); + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET6, query_completed_cb, conn); + } + else { + res->num_pending = 1; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET, query_completed_cb, conn); + } + } + else +#endif /* CURLRES_IPV6 */ + { + res->num_pending = 1; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, family, + query_completed_cb, conn); + } + + *waitp = 1; /* expect asynchronous response */ + } + return NULL; /* no struct yet */ +} + +CURL_STATIC CURLcode Curl_set_dns_servers(struct SessionHandle *data, + char *servers) +{ + CURLcode result = CURLE_NOT_BUILT_IN; + int ares_result; + + /* If server is NULL or empty, this would purge all DNS servers + * from ares library, which will cause any and all queries to fail. + * So, just return OK if none are configured and don't actually make + * any changes to c-ares. This lets c-ares use it's defaults, which + * it gets from the OS (for instance from /etc/resolv.conf on Linux). + */ + if(!(servers && servers[0])) + return CURLE_OK; + +#if (ARES_VERSION >= 0x010704) + ares_result = ares_set_servers_csv(data->state.resolver, servers); + switch(ares_result) { + case ARES_SUCCESS: + result = CURLE_OK; + break; + case ARES_ENOMEM: + result = CURLE_OUT_OF_MEMORY; + break; + case ARES_ENOTINITIALIZED: + case ARES_ENODATA: + case ARES_EBADSTR: + default: + result = CURLE_BAD_FUNCTION_ARGUMENT; + break; + } +#else /* too old c-ares version! */ + (void)data; + (void)(ares_result); +#endif + return result; +} + +CURL_STATIC CURLcode Curl_set_dns_interface(struct SessionHandle *data, + const char *interf) +{ +#if (ARES_VERSION >= 0x010704) + if(!interf) + interf = ""; + + ares_set_local_dev((ares_channel)data->state.resolver, interf); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURL_STATIC CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data, + const char *local_ip4) +{ +#if (ARES_VERSION >= 0x010704) + struct in_addr a4; + + if((!local_ip4) || (local_ip4[0] == 0)) { + a4.s_addr = 0; /* disabled: do not bind to a specific address */ + } + else { + if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) { + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + + ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr)); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURL_STATIC CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data, + const char *local_ip6) +{ +#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6) + unsigned char a6[INET6_ADDRSTRLEN]; + + if((!local_ip6) || (local_ip6[0] == 0)) { + /* disabled: do not bind to a specific address */ + memset(a6, 0, sizeof(a6)); + } + else { + if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) { + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + + ares_set_local_ip6((ares_channel)data->state.resolver, a6); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +#endif +} +#endif /* CURLRES_ARES */ diff --git a/libcurl/src/lib/asyn-thread.c b/libcurl/src/lib/asyn-thread.c new file mode 100644 index 0000000..3737bff --- /dev/null +++ b/libcurl/src/lib/asyn-thread.c @@ -0,0 +1,698 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if defined(USE_THREADS_POSIX) +# ifdef HAVE_PTHREAD_H +# include +# endif +#elif defined(USE_THREADS_WIN32) +# ifdef HAVE_PROCESS_H +# include +# endif +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#ifdef HAVE_GETADDRINFO +# define RESOLVER_ENOMEM EAI_MEMORY +#else +# define RESOLVER_ENOMEM ENOMEM +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "multiif.h" +#include "inet_pton.h" +#include "inet_ntop.h" +#include "curl_threads.h" +#include "connect.h" +#include "curl_printf.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/*********************************************************************** + * Only for threaded name resolves builds + **********************************************************************/ +#ifdef CURLRES_THREADED + +/* + * Curl_resolver_global_init() + * Called from curl_global_init() to initialize global resolver environment. + * Does nothing here. + */ +CURL_STATIC int Curl_resolver_global_init(void) +{ + return CURLE_OK; +} + +/* + * Curl_resolver_global_cleanup() + * Called from curl_global_cleanup() to destroy global resolver environment. + * Does nothing here. + */ +CURL_STATIC void Curl_resolver_global_cleanup(void) +{ +} + +/* + * Curl_resolver_init() + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Does nothing here. + */ +CURL_STATIC CURLcode Curl_resolver_init(void **resolver) +{ + (void)resolver; + return CURLE_OK; +} + +/* + * Curl_resolver_cleanup() + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Does nothing here. + */ +CURL_STATIC void Curl_resolver_cleanup(void *resolver) +{ + (void)resolver; +} + +/* + * Curl_resolver_duphandle() + * Called from curl_easy_duphandle() to duplicate resolver URL state-specific + * environment ('resolver' member of the UrlState structure). Does nothing + * here. + */ +CURL_STATIC int Curl_resolver_duphandle(void **to, void *from) +{ + (void)to; + (void)from; + return CURLE_OK; +} + +static void destroy_async_data(struct Curl_async *); + +/* + * Cancel all possibly still on-going resolves for this connection. + */ +CURL_STATIC void Curl_resolver_cancel(struct connectdata *conn) +{ + destroy_async_data(&conn->async); +} + +/* This function is used to init a threaded resolve */ +static bool init_resolve_thread(struct connectdata *conn, + const char *hostname, int port, + const struct addrinfo *hints); + + +/* Data for synchronization between resolver thread and its parent */ +struct thread_sync_data { + curl_mutex_t * mtx; + int done; + + char * hostname; /* hostname to resolve, Curl_async.hostname + duplicate */ + int port; + int sock_error; + Curl_addrinfo *res; +#ifdef HAVE_GETADDRINFO + struct addrinfo hints; +#endif + struct thread_data *td; /* for thread-self cleanup */ +}; + +struct thread_data { + curl_thread_t thread_hnd; + unsigned int poll_interval; + long interval_end; + struct thread_sync_data tsd; +}; + +static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn) +{ + return &(((struct thread_data *)conn->async.os_specific)->tsd); +} + +#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd); + +/* Destroy resolver thread synchronization data */ +static +void destroy_thread_sync_data(struct thread_sync_data * tsd) +{ + if(tsd->mtx) { + Curl_mutex_destroy(tsd->mtx); + free(tsd->mtx); + } + + free(tsd->hostname); + + if(tsd->res) + Curl_freeaddrinfo(tsd->res); + + memset(tsd, 0, sizeof(*tsd)); +} + +/* Initialize resolver thread synchronization data */ +static +int init_thread_sync_data(struct thread_data * td, + const char * hostname, + int port, + const struct addrinfo *hints) +{ + struct thread_sync_data *tsd = &td->tsd; + + memset(tsd, 0, sizeof(*tsd)); + + tsd->td = td; + tsd->port = port; +#ifdef HAVE_GETADDRINFO + DEBUGASSERT(hints); + tsd->hints = *hints; +#else + (void) hints; +#endif + + tsd->mtx = malloc(sizeof(curl_mutex_t)); + if(tsd->mtx == NULL) + goto err_exit; + + Curl_mutex_init(tsd->mtx); + + tsd->sock_error = CURL_ASYNC_SUCCESS; + + /* Copying hostname string because original can be destroyed by parent + * thread during gethostbyname execution. + */ + tsd->hostname = strdup(hostname); + if(!tsd->hostname) + goto err_exit; + + return 1; + + err_exit: + /* Memory allocation failed */ + destroy_thread_sync_data(tsd); + return 0; +} + +static int getaddrinfo_complete(struct connectdata *conn) +{ + struct thread_sync_data *tsd = conn_thread_sync_data(conn); + int rc; + + rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res); + /* The tsd->res structure has been copied to async.dns and perhaps the DNS + cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it. + */ + tsd->res = NULL; + + return rc; +} + + +#ifdef HAVE_GETADDRINFO + +/* + * getaddrinfo_thread() resolves a name and then exits. + * + * For builds without ARES, but with ENABLE_IPV6, create a resolver thread + * and wait on it. + */ +static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) +{ + struct thread_sync_data *tsd = (struct thread_sync_data*)arg; + struct thread_data *td = tsd->td; + char service[12]; + int rc; + + snprintf(service, sizeof(service), "%d", tsd->port); + + rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res); + + if(rc != 0) { + tsd->sock_error = SOCKERRNO?SOCKERRNO:rc; + if(tsd->sock_error == 0) + tsd->sock_error = RESOLVER_ENOMEM; + } + + Curl_mutex_acquire(tsd->mtx); + if(tsd->done) { + /* 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; +} + +#else /* HAVE_GETADDRINFO */ + +/* + * gethostbyname_thread() resolves a name and then exits. + */ +static unsigned int CURL_STDCALL gethostbyname_thread (void *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); + + if(!tsd->res) { + tsd->sock_error = SOCKERRNO; + if(tsd->sock_error == 0) + tsd->sock_error = RESOLVER_ENOMEM; + } + + Curl_mutex_acquire(tsd->mtx); + if(tsd->done) { + /* 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; +} + +#endif /* HAVE_GETADDRINFO */ + +/* + * destroy_async_data() cleans up async resolver data and thread handle. + */ +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; + + free(async->hostname); + async->hostname = NULL; +} + +/* + * init_resolve_thread() starts a new thread that performs the actual + * resolve. This function returns before the resolve is done. + * + * Returns FALSE in case of failure, otherwise TRUE. + */ +static bool init_resolve_thread (struct connectdata *conn, + const char *hostname, int port, + const struct addrinfo *hints) +{ + struct thread_data *td = calloc(1, sizeof(struct thread_data)); + int err = RESOLVER_ENOMEM; + + conn->async.os_specific = (void*) td; + if(!td) + goto err_exit; + + conn->async.port = port; + conn->async.done = FALSE; + conn->async.status = 0; + conn->async.dns = NULL; + td->thread_hnd = curl_thread_t_null; + + if(!init_thread_sync_data(td, hostname, port, hints)) + goto err_exit; + + free(conn->async.hostname); + conn->async.hostname = strdup(hostname); + if(!conn->async.hostname) + goto err_exit; + +#ifdef HAVE_GETADDRINFO + td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd); +#else + td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd); +#endif + + if(!td->thread_hnd) { +#ifndef _WIN32_WCE + err = errno; +#endif + goto err_exit; + } + + return TRUE; + + err_exit: + destroy_async_data(&conn->async); + + SET_ERRNO(err); + + return FALSE; +} + +/* + * resolver_error() calls failf() with the appropriate message after a resolve + * error + */ + +static CURLcode resolver_error(struct connectdata *conn) +{ + const char *host_or_proxy; + CURLcode result; + + if(conn->bits.httpproxy) { + host_or_proxy = "proxy"; + result = CURLE_COULDNT_RESOLVE_PROXY; + } + else { + host_or_proxy = "host"; + result = CURLE_COULDNT_RESOLVE_HOST; + } + + failf(conn->data, "Could not resolve %s: %s", host_or_proxy, + conn->async.hostname); + + return result; +} + +/* + * Curl_resolver_wait_resolv() + * + * waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * This is the version for resolves-in-a-thread. + */ +CURL_STATIC CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + CURLcode result = CURLE_OK; + + DEBUGASSERT(conn && td); + + /* wait for the thread to resolve the name */ + if(Curl_thread_join(&td->thread_hnd)) + result = getaddrinfo_complete(conn); + else + DEBUGASSERT(0); + + conn->async.done = TRUE; + + if(entry) + *entry = conn->async.dns; + + if(!conn->async.dns) + /* a name was not resolved, report error */ + result = resolver_error(conn); + + destroy_async_data(&conn->async); + + if(!conn->async.dns) + connclose(conn, "asynch resolve failed"); + + return result; +} + +/* + * Curl_resolver_is_resolved() is called repeatedly to check if a previous + * name resolve request has completed. It should also make sure to time-out if + * the operation seems to take too long. + */ +CURL_STATIC CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + struct SessionHandle *data = conn->data; + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + int done = 0; + + *entry = NULL; + + if(!td) { + DEBUGASSERT(td); + return CURLE_COULDNT_RESOLVE_HOST; + } + + Curl_mutex_acquire(td->tsd.mtx); + done = td->tsd.done; + Curl_mutex_release(td->tsd.mtx); + + if(done) { + getaddrinfo_complete(conn); + + if(!conn->async.dns) { + CURLcode result = resolver_error(conn); + destroy_async_data(&conn->async); + return result; + } + destroy_async_data(&conn->async); + *entry = conn->async.dns; + } + else { + /* poll for name lookup done with exponential backoff up to 250ms */ + long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); + if(elapsed < 0) + elapsed = 0; + + if(td->poll_interval == 0) + /* Start at 1ms poll interval */ + td->poll_interval = 1; + else if(elapsed >= td->interval_end) + /* Back-off exponentially if last interval expired */ + td->poll_interval *= 2; + + if(td->poll_interval > 250) + td->poll_interval = 250; + + td->interval_end = elapsed + td->poll_interval; + Curl_expire(conn->data, td->poll_interval); + } + + return CURLE_OK; +} + +CURL_STATIC int Curl_resolver_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return 0; +} + +#ifndef HAVE_GETADDRINFO +/* + * Curl_getaddrinfo() - for platforms without getaddrinfo + */ +CURL_STATIC Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct in_addr in; + + *waitp = 0; /* default to synchronous response */ + + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + + /* fire up a new resolver thread! */ + if(init_resolve_thread(conn, hostname, port, NULL)) { + *waitp = 1; /* expect asynchronous response */ + return NULL; + } + + /* fall-back to blocking version */ + return Curl_ipv4_resolve_r(hostname, port); +} + +#else /* !HAVE_GETADDRINFO */ + +/* + * Curl_resolver_getaddrinfo() - for getaddrinfo + */ +CURL_STATIC Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct addrinfo hints; + struct in_addr in; + Curl_addrinfo *res; + int error; + char sbuf[12]; + int pf = PF_INET; +#ifdef CURLRES_IPV6 + struct in6_addr in6; +#endif /* CURLRES_IPV6 */ + + *waitp = 0; /* default to synchronous response */ + + /* First check if this is an IPv4 address string */ + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + +#ifdef CURLRES_IPV6 + /* check if this is an IPv6 address string */ + if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) + /* This is an IPv6 address literal */ + return Curl_ip2addr(AF_INET6, &in6, hostname, port); + + /* + * Check if a limited name resolve has been requested. + */ + switch(conn->ip_version) { + case CURL_IPRESOLVE_V4: + pf = PF_INET; + break; + case CURL_IPRESOLVE_V6: + pf = PF_INET6; + break; + default: + pf = PF_UNSPEC; + break; + } + + if((pf != PF_INET) && !Curl_ipv6works()) + /* The stack seems to be a non-IPv6 one */ + pf = PF_INET; + +#endif /* CURLRES_IPV6 */ + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = pf; + hints.ai_socktype = conn->socktype; + + snprintf(sbuf, sizeof(sbuf), "%d", port); + + /* fire up a new resolver thread! */ + if(init_resolve_thread(conn, hostname, port, &hints)) { + *waitp = 1; /* expect asynchronous response */ + return NULL; + } + + /* fall-back to blocking version */ + infof(conn->data, "init_resolve_thread() failed for %s; %s\n", + hostname, Curl_strerror(conn, ERRNO)); + + error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res); + if(error) { + infof(conn->data, "getaddrinfo() failed for %s:%d; %s\n", + hostname, port, Curl_strerror(conn, SOCKERRNO)); + return NULL; + } + return res; +} + +#endif /* !HAVE_GETADDRINFO */ + +CURL_STATIC CURLcode Curl_set_dns_servers(struct SessionHandle *data, + char *servers) +{ + (void)data; + (void)servers; + return CURLE_NOT_BUILT_IN; + +} + +CURL_STATIC CURLcode Curl_set_dns_interface(struct SessionHandle *data, + const char *interf) +{ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +} + +CURL_STATIC CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data, + const char *local_ip4) +{ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +} + +CURL_STATIC CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data, + const char *local_ip6) +{ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +} + +#endif /* CURLRES_THREADED */ diff --git a/libcurl/src/lib/asyn.h b/libcurl/src/lib/asyn.h new file mode 100644 index 0000000..36e7c53 --- /dev/null +++ b/libcurl/src/lib/asyn.h @@ -0,0 +1,168 @@ +#ifndef HEADER_CURL_ASYN_H +#define HEADER_CURL_ASYN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "curl_addrinfo.h" + +struct addrinfo; +struct hostent; +struct SessionHandle; +struct connectdata; +struct Curl_dns_entry; + +/* + * This header defines all functions in the internal asynch resolver interface. + * All asynch resolvers need to provide these functions. + * asyn-ares.c and asyn-thread.c are the current implementations of asynch + * resolver backends. + */ + +/* + * Curl_resolver_global_init() + * + * Called from curl_global_init() to initialize global resolver environment. + * Returning anything else than CURLE_OK fails curl_global_init(). + */ +CURL_STATIC int Curl_resolver_global_init(void); + +/* + * Curl_resolver_global_cleanup() + * Called from curl_global_cleanup() to destroy global resolver environment. + */ +CURL_STATIC void Curl_resolver_global_cleanup(void); + +/* + * Curl_resolver_init() + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Should fill the passed pointer by the initialized handler. + * Returning anything else than CURLE_OK fails curl_easy_init() with the + * correspondent code. + */ +CURL_STATIC CURLcode Curl_resolver_init(void **resolver); + +/* + * Curl_resolver_cleanup() + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Should destroy the handler and free all resources connected to + * it. + */ +CURL_STATIC void Curl_resolver_cleanup(void *resolver); + +/* + * Curl_resolver_duphandle() + * Called from curl_easy_duphandle() to duplicate resolver URL-state specific + * environment ('resolver' member of the UrlState structure). Should + * duplicate the 'from' handle and pass the resulting handle to the 'to' + * pointer. Returning anything else than CURLE_OK causes failed + * curl_easy_duphandle() call. + */ +CURL_STATIC int Curl_resolver_duphandle(void **to, void *from); + +/* + * Curl_resolver_cancel(). + * + * It is called from inside other functions to cancel currently performing + * resolver request. Should also free any temporary resources allocated to + * perform a request. + */ +CURL_STATIC void Curl_resolver_cancel(struct connectdata *conn); + +/* Curl_resolver_getsock() + * + * This function is called from the multi_getsock() function. 'sock' is a + * pointer to an array to hold the file descriptors, with 'numsock' being the + * size of that array (in number of entries). This function is supposed to + * return bitmask indicating what file descriptors (referring to array indexes + * in the 'sock' array) to wait for, read/write. + */ +CURL_STATIC int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock, + int numsocks); + +/* + * Curl_resolver_is_resolved() + * + * Called repeatedly to check if a previous name resolve request has + * completed. It should also make sure to time-out if the operation seems to + * take too long. + * + * Returns normal CURLcode errors. + */ +CURL_STATIC CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns); + +/* + * Curl_resolver_wait_resolv() + * + * waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and + * CURLE_OPERATION_TIMEDOUT if a time-out occurred. + + */ +CURL_STATIC CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **dnsentry); + +/* + * Curl_resolver_getaddrinfo() - when using this resolver + * + * Returns name information about the given hostname and port number. If + * successful, the 'hostent' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + * + * Each resolver backend must of course make sure to return data in the + * correct format to comply with this. + */ +CURL_STATIC Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + +#ifndef CURLRES_ASYNCH +/* convert these functions if an asynch resolver isn't used */ +#define Curl_resolver_cancel(x) Curl_nop_stmt +#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_resolver_getsock(x,y,z) 0 +#define Curl_resolver_duphandle(x,y) CURLE_OK +#define Curl_resolver_init(x) CURLE_OK +#define Curl_resolver_global_init() CURLE_OK +#define Curl_resolver_global_cleanup() Curl_nop_stmt +#define Curl_resolver_cleanup(x) Curl_nop_stmt +#endif + +#ifdef CURLRES_ASYNCH +#define Curl_resolver_asynch() 1 +#else +#define Curl_resolver_asynch() 0 +#endif + + +/********** end of generic resolver interface functions *****************/ +#endif /* HEADER_CURL_ASYN_H */ diff --git a/libcurl/src/lib/base64.c b/libcurl/src/lib/base64.c new file mode 100644 index 0000000..ff51c2d --- /dev/null +++ b/libcurl/src/lib/base64.c @@ -0,0 +1,309 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Base64 encoding/decoding */ + +#include "curl_setup.h" +#include "curl_printf.h" +#include "urldata.h" /* for the SessionHandle definition */ +#include "warnless.h" +#include "curl_base64.h" +#include "non-ascii.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* ---- Base64 Encoding/Decoding Table --- */ +static const char base64[]= + "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) +{ + size_t padding = 0; + const char *s, *p; + unsigned long i, x = 0; + + for(i = 0, s = src; i < 4; i++, s++) { + unsigned long v = 0; + + if(*s == '=') { + x = (x << 6); + padding++; + } + else { + p = base64; + + while(*p && (*p != *s)) { + v++; + p++; + } + + if(*p == *s) + x = (x << 6) + v; + else + return 0; + } + } + + if(padding < 1) + dest[2] = curlx_ultouc(x & 0xFFUL); + + x >>= 8; + if(padding < 2) + dest[1] = curlx_ultouc(x & 0xFFUL); + + x >>= 8; + dest[0] = curlx_ultouc(x & 0xFFUL); + + return 3 - padding; +} + +/* + * Curl_base64_decode() + * + * Given a base64 NUL-terminated string at src, decode it and return a + * pointer in *outptr to a newly allocated memory area holding decoded + * data. Size of decoded data is returned in variable pointed by outlen. + * + * Returns CURLE_OK on success, otherwise specific error code. Function + * output shall not be considered valid unless CURLE_OK is returned. + * + * When decoded data length is 0, returns NULL in *outptr. + * + * @unittest: 1302 + */ +CURL_STATIC CURLcode Curl_base64_decode(const char *src, + unsigned char **outptr, size_t *outlen) +{ + size_t srclen = 0; + size_t length = 0; + size_t padding = 0; + size_t i; + size_t numQuantums; + size_t rawlen = 0; + unsigned char *pos; + unsigned char *newstr; + + *outptr = NULL; + *outlen = 0; + srclen = strlen(src); + + /* Check the length of the input string is valid */ + if(!srclen || srclen % 4) + return CURLE_BAD_CONTENT_ENCODING; + + /* Find the position of any = padding characters */ + while((src[length] != '=') && src[length]) + length++; + + /* A maximum of two = padding characters is allowed */ + if(src[length] == '=') { + padding++; + if(src[length + 1] == '=') + padding++; + } + + /* Check the = padding characters weren't part way through the input */ + if(length + padding != srclen) + return CURLE_BAD_CONTENT_ENCODING; + + /* Calculate the number of quantums */ + numQuantums = srclen / 4; + + /* Calculate the size of the decoded string */ + rawlen = (numQuantums * 3) - padding; + + /* Allocate our buffer including room for a zero terminator */ + newstr = malloc(rawlen + 1); + if(!newstr) + return CURLE_OUT_OF_MEMORY; + + pos = newstr; + + /* Decode the quantums */ + for(i = 0; i < numQuantums; i++) { + size_t result = decodeQuantum(pos, src); + if(!result) { + free(newstr); + + return CURLE_BAD_CONTENT_ENCODING; + } + + pos += result; + src += 4; + } + + /* Zero terminate */ + *pos = '\0'; + + /* Return the decoded data */ + *outptr = newstr; + *outlen = rawlen; + + return CURLE_OK; +} + +static CURLcode base64_encode(const char *table64, + struct SessionHandle *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen) +{ + CURLcode error; + unsigned char ibuf[3]; + unsigned char obuf[4]; + int i; + int inputparts; + char *output; + char *base64data; + char *convbuf = NULL; + + const char *indata = inputbuff; + + *outptr = NULL; + *outlen = 0; + + if(0 == insize) + insize = strlen(indata); + + base64data = output = malloc(insize*4/3+4); + if(NULL == output) + return CURLE_OUT_OF_MEMORY; + + /* + * The base64 data needs to be created using the network encoding + * not the host encoding. And we can't change the actual input + * so we copy it to a buffer, translate it, and use that instead. + */ + error = Curl_convert_clone(data, indata, insize, &convbuf); + if(error) { + free(output); + return error; + } + + if(convbuf) + indata = (char *)convbuf; + + while(insize > 0) { + for(i = inputparts = 0; i < 3; i++) { + if(insize > 0) { + inputparts++; + ibuf[i] = (unsigned char) *indata; + indata++; + insize--; + } + else + ibuf[i] = 0; + } + + obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); + obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ + ((ibuf[1] & 0xF0) >> 4)); + obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ + ((ibuf[2] & 0xC0) >> 6)); + obuf[3] = (unsigned char) (ibuf[2] & 0x3F); + + switch(inputparts) { + case 1: /* only one byte read */ + snprintf(output, 5, "%c%c==", + table64[obuf[0]], + table64[obuf[1]]); + break; + case 2: /* two bytes read */ + snprintf(output, 5, "%c%c%c=", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]]); + break; + default: + snprintf(output, 5, "%c%c%c%c", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]], + table64[obuf[3]] ); + break; + } + output += 4; + } + *output = '\0'; + *outptr = base64data; /* return pointer to new data, allocated memory */ + + free(convbuf); + + *outlen = strlen(base64data); /* return the length of the new data */ + + 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 + */ +CURL_STATIC 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 + */ +CURL_STATIC 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 ---- */ diff --git a/libcurl/src/lib/bundles.c b/libcurl/src/lib/bundles.c new file mode 100644 index 0000000..784e362 --- /dev/null +++ b/libcurl/src/lib/bundles.c @@ -0,0 +1,110 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Linus Nielsen Feltzing, + * Copyright (C) 2012-2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "multiif.h" +#include "bundles.h" +#include "sendf.h" +#include "rawstr.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +static void conn_llist_dtor(void *user, void *element) +{ + struct connectdata *data = element; + (void)user; + + data->bundle = NULL; +} + +CURL_STATIC CURLcode Curl_bundle_create(struct SessionHandle *data, + struct connectbundle **cb_ptr) +{ + (void)data; + DEBUGASSERT(*cb_ptr == NULL); + *cb_ptr = malloc(sizeof(struct connectbundle)); + if(!*cb_ptr) + return CURLE_OUT_OF_MEMORY; + + (*cb_ptr)->num_connections = 0; + (*cb_ptr)->server_supports_pipelining = FALSE; + + (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor); + if(!(*cb_ptr)->conn_list) { + Curl_safefree(*cb_ptr); + return CURLE_OUT_OF_MEMORY; + } + return CURLE_OK; +} + +CURL_STATIC void Curl_bundle_destroy(struct connectbundle *cb_ptr) +{ + if(!cb_ptr) + return; + + if(cb_ptr->conn_list) { + Curl_llist_destroy(cb_ptr->conn_list, NULL); + cb_ptr->conn_list = NULL; + } + free(cb_ptr); +} + +/* Add a connection to a bundle */ +CURL_STATIC CURLcode Curl_bundle_add_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn)) + return CURLE_OUT_OF_MEMORY; + + conn->bundle = cb_ptr; + + cb_ptr->num_connections++; + return CURLE_OK; +} + +/* Remove a connection from a bundle */ +CURL_STATIC int Curl_bundle_remove_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + struct curl_llist_element *curr; + + curr = cb_ptr->conn_list->head; + while(curr) { + if(curr->ptr == conn) { + Curl_llist_remove(cb_ptr->conn_list, curr, NULL); + cb_ptr->num_connections--; + conn->bundle = NULL; + return 1; /* we removed a handle */ + } + curr = curr->next; + } + return 0; +} diff --git a/libcurl/src/lib/bundles.h b/libcurl/src/lib/bundles.h new file mode 100644 index 0000000..af4382c --- /dev/null +++ b/libcurl/src/lib/bundles.h @@ -0,0 +1,45 @@ +#ifndef HEADER_CURL_BUNDLES_H +#define HEADER_CURL_BUNDLES_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Linus Nielsen Feltzing, + * + * 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. + * + ***************************************************************************/ + +struct connectbundle { + bool server_supports_pipelining; /* TRUE if server supports pipelining, + set after first response */ + size_t num_connections; /* Number of connections in the bundle */ + struct curl_llist *conn_list; /* The connectdata members of the bundle */ +}; + +CURL_STATIC CURLcode Curl_bundle_create(struct SessionHandle *data, + struct connectbundle **cb_ptr); + +CURL_STATIC void Curl_bundle_destroy(struct connectbundle *cb_ptr); + +CURL_STATIC CURLcode Curl_bundle_add_conn(struct connectbundle *cb_ptr, + struct connectdata *conn); + +CURL_STATIC int Curl_bundle_remove_conn(struct connectbundle *cb_ptr, + struct connectdata *conn); + + +#endif /* HEADER_CURL_BUNDLES_H */ + diff --git a/libcurl/src/lib/config-amigaos.h b/libcurl/src/lib/config-amigaos.h new file mode 100644 index 0000000..04b18b7 --- /dev/null +++ b/libcurl/src/lib/config-amigaos.h @@ -0,0 +1,166 @@ +#ifndef HEADER_CURL_CONFIG_AMIGAOS_H +#define HEADER_CURL_CONFIG_AMIGAOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for AmigaOS */ +/* ================================================================ */ + +#ifdef __AMIGA__ /* Any AmigaOS flavour */ + +#define HAVE_ARPA_INET_H 1 +#define HAVE_CLOSESOCKET_CAMEL 1 +#define HAVE_ERRNO_H 1 +#define HAVE_GETHOSTBYADDR 1 +#define HAVE_INET_ADDR 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_IOCTLSOCKET_CAMEL 1 +#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1 +#define HAVE_LIBCRYPTO 1 +#define HAVE_LIBSSL 1 +#define HAVE_LIBZ 1 +#define HAVE_LONGLONG 1 +#define HAVE_MALLOC_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_OPENSSL_CRYPTO_H 1 +#define HAVE_OPENSSL_ERR_H 1 +#define HAVE_OPENSSL_PEM_H 1 +#define HAVE_OPENSSL_RSA_H 1 +#define HAVE_OPENSSL_SSL_H 1 +#define HAVE_OPENSSL_X509_H 1 +#define HAVE_PERROR 1 +#define HAVE_PWD_H 1 +#define HAVE_RAND_EGD 1 +#define HAVE_RAND_STATUS 1 +#define HAVE_SELECT 1 +#define HAVE_SETJMP_H 1 +#define HAVE_SGTTY_H 1 +#define HAVE_SIGNAL 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SIG_ATOMIC_T 1 +#define HAVE_SOCKET 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRDUP 1 +#define HAVE_STRFTIME 1 +#define HAVE_STRICMP 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRSTR 1 +#define HAVE_STRUCT_TIMEVAL 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_SOCKIO_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UNAME 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UTIME 1 +#define HAVE_UTIME_H 1 +#define HAVE_WRITABLE_ARGV 1 +#define HAVE_ZLIB_H 1 +#define HAVE_SYS_IOCTL_H 1 + +#define NEED_MALLOC_H 1 + +#define SIZEOF_INT 4 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 + +#define USE_MANUAL 1 +#define USE_OPENSSL 1 +#define CURL_DISABLE_LDAP 1 + +#define OS "AmigaOS" + +#define PACKAGE "curl" +#define PACKAGE_BUGREPORT "curl-bug@haxx.se" +#define PACKAGE_NAME "curl" +#define PACKAGE_STRING "curl -" +#define PACKAGE_TARNAME "curl" +#define PACKAGE_VERSION "-" +#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt" + +#define RETSIGTYPE void +#define SELECT_TYPE_ARG1 int +#define SELECT_TYPE_ARG234 (fd_set *) +#define SELECT_TYPE_ARG5 (struct timeval *) + +#define STDC_HEADERS 1 +#define TIME_WITH_SYS_TIME 1 + +#define in_addr_t int + +#ifndef F_OK +# define F_OK 0 +#endif + +#ifndef O_RDONLY +# define O_RDONLY 0x0000 +#endif + +#ifndef LONG_MAX +# define LONG_MAX 0x7fffffffL +#endif + +#ifndef LONG_MIN +# define LONG_MIN (-0x7fffffffL-1) +#endif + +#define HAVE_GETNAMEINFO 1 +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 int +#define GETNAMEINFO_TYPE_ARG46 size_t +#define GETNAMEINFO_TYPE_ARG7 int + +#define HAVE_RECV 1 +#define RECV_TYPE_ARG1 long +#define RECV_TYPE_ARG2 char * +#define RECV_TYPE_ARG3 long +#define RECV_TYPE_ARG4 long +#define RECV_TYPE_RETV long + +#define HAVE_RECVFROM 1 +#define RECVFROM_TYPE_ARG1 long +#define RECVFROM_TYPE_ARG2 char +#define RECVFROM_TYPE_ARG3 long +#define RECVFROM_TYPE_ARG4 long +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 long +#define RECVFROM_TYPE_RETV long + +#define HAVE_SEND 1 +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 char * +#define SEND_TYPE_ARG3 int +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV int + +#endif /* __AMIGA__ */ +#endif /* HEADER_CURL_CONFIG_AMIGAOS_H */ diff --git a/libcurl/src/lib/config-android-arm.h b/libcurl/src/lib/config-android-arm.h new file mode 100644 index 0000000..8d64dbe --- /dev/null +++ b/libcurl/src/lib/config-android-arm.h @@ -0,0 +1,1019 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +//#define CURL_DISABLE_DICT 1 + +/* to disable FILE */ +//#define CURL_DISABLE_FILE 1 + +/* to disable FTP */ +//#define CURL_DISABLE_FTP 1 + +/* to disable Gopher */ +//#define CURL_DISABLE_GOPHER 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +//#define CURL_DISABLE_IMAP 1 + +/* to disable LDAP */ +//#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +//#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +/* #undef CURL_DISABLE_LIBCURL_OPTION */ + +/* to disable POP3 */ +//#define CURL_DISABLE_POP3 1 + +/* to disable proxies */ +/* #undef CURL_DISABLE_PROXY */ + +/* to disable RTSP */ +//#define CURL_DISABLE_RTSP 1 + +/* to disable SMB/CIFS */ +/* #undef CURL_DISABLE_SMB */ + +/* to disable SMTP */ +//#define CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +//#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +//#define CURL_DISABLE_TFTP 1 + +/* to disable TLS-SRP authentication */ +/* #undef CURL_DISABLE_TLS_SRP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define to the type of arg 2 for gethostname. */ +#define GETHOSTNAME_TYPE_ARG2 unsigned int + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Specifies the number of arguments to getservbyport_r */ +/* #undef GETSERVBYPORT_R_ARGS */ + +/* Specifies the size of the buffer to pass to getservbyport_r */ +/* #undef GETSERVBYPORT_R_BUFSIZE */ + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#define HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CYASSL_ERROR_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +/* #undef HAVE_FREEIFADDRS */ + +/* Define to 1 if you have the fsetxattr function. */ +/* #undef HAVE_FSETXATTR */ + +/* fsetxattr() takes 5 args */ +/* #undef HAVE_FSETXATTR_5 */ + +/* fsetxattr() takes 6 args */ +/* #undef HAVE_FSETXATTR_6 */ + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +/* #undef HAVE_GETHOSTBYADDR_R */ + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +/* #undef HAVE_GETHOSTBYADDR_R_8 */ + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +#define HAVE_GETHOSTBYNAME_R_6 1 + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +/* #undef HAVE_GETIFADDRS */ + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +/* #undef HAVE_GETPWUID_R */ + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have GSS-API libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have GNU GSS */ +/* #undef HAVE_GSSGNU */ + +/* if you have Heimdal */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have MIT Kerberos */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IFADDRS_H */ + +/* Define to 1 if you have the `if_nametoindex' function. */ +#define HAVE_IF_NAMETOINDEX 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +#define HAVE_LDAP_SSL 1 + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +#define HAVE_MEMRCHR 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#define HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NGHTTP2_NGHTTP2_H */ + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#define HAVE_POLL 1 + +/* If you have a fine poll */ +#define HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#define HAVE_POSIX_STRERROR_R 1 + +/* if you have */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +/* #undef HAVE_SETMODE */ + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +/* #undef HAVE_SIGNAL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SOCKET_H */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_XATTR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +/* #undef HAVE_WRITABLE_ARGV */ + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "arm-unknown-linux-androideabi" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 unsigned int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 unsigned int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `long long', as computed by sizeof. */ +/* #undef SIZEOF_LONG_LONG */ + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 4 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#define STRERROR_R_TYPE_ARG3 size_t + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* to enable iOS/Mac OS X native SSL/TLS support */ +/* #undef USE_DARWINSSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* Define to enable metalink support */ +/* #undef USE_METALINK */ + +/* if nghttp2 is in use */ +/* #undef USE_NGHTTP2 */ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* to enable Windows native SSL/TLS support */ +/* #undef USE_SCHANNEL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +#define USE_THREADS_POSIX 1 + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Use Unix domain sockets */ +#define USE_UNIX_SOCKETS 1 + +/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ +/* #undef USE_WIN32_IDN */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to 1 to provide own prototypes. */ +/* #undef WANT_IDN_PROTOTYPES */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ diff --git a/libcurl/src/lib/config-android-x86.h b/libcurl/src/lib/config-android-x86.h new file mode 100644 index 0000000..84cfed8 --- /dev/null +++ b/libcurl/src/lib/config-android-x86.h @@ -0,0 +1,1019 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +//#define CURL_DISABLE_DICT 1 + +/* to disable FILE */ +//#define CURL_DISABLE_FILE 1 + +/* to disable FTP */ +//#define CURL_DISABLE_FTP 1 + +/* to disable Gopher */ +//#define CURL_DISABLE_GOPHER 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +//#define CURL_DISABLE_IMAP 1 + +/* to disable LDAP */ +//#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +//#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +/* #undef CURL_DISABLE_LIBCURL_OPTION */ + +/* to disable POP3 */ +//#define CURL_DISABLE_POP3 1 + +/* to disable proxies */ +/* #undef CURL_DISABLE_PROXY */ + +/* to disable RTSP */ +//#define CURL_DISABLE_RTSP 1 + +/* to disable SMB/CIFS */ +/* #undef CURL_DISABLE_SMB */ + +/* to disable SMTP */ +//#define CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +//#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +//#define CURL_DISABLE_TFTP 1 + +/* to disable TLS-SRP authentication */ +/* #undef CURL_DISABLE_TLS_SRP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define to the type of arg 2 for gethostname. */ +#define GETHOSTNAME_TYPE_ARG2 unsigned int + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Specifies the number of arguments to getservbyport_r */ +/* #undef GETSERVBYPORT_R_ARGS */ + +/* Specifies the size of the buffer to pass to getservbyport_r */ +/* #undef GETSERVBYPORT_R_BUFSIZE */ + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#define HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CYASSL_ERROR_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +/* #undef HAVE_FREEIFADDRS */ + +/* Define to 1 if you have the fsetxattr function. */ +/* #undef HAVE_FSETXATTR */ + +/* fsetxattr() takes 5 args */ +/* #undef HAVE_FSETXATTR_5 */ + +/* fsetxattr() takes 6 args */ +/* #undef HAVE_FSETXATTR_6 */ + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +/* #undef HAVE_GETHOSTBYADDR_R */ + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +/* #undef HAVE_GETHOSTBYADDR_R_8 */ + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +#define HAVE_GETHOSTBYNAME_R_6 1 + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +/* #undef HAVE_GETIFADDRS */ + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +/* #undef HAVE_GETPWUID_R */ + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have GSS-API libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have GNU GSS */ +/* #undef HAVE_GSSGNU */ + +/* if you have Heimdal */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have MIT Kerberos */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IFADDRS_H */ + +/* Define to 1 if you have the `if_nametoindex' function. */ +#define HAVE_IF_NAMETOINDEX 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +#define HAVE_LDAP_SSL 1 + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +#define HAVE_MEMRCHR 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#define HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NGHTTP2_NGHTTP2_H */ + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#define HAVE_POLL 1 + +/* If you have a fine poll */ +#define HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#define HAVE_POSIX_STRERROR_R 1 + +/* if you have */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +/* #undef HAVE_SETMODE */ + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +/* #undef HAVE_SIGNAL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SOCKET_H */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_XATTR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +/* #undef HAVE_WRITABLE_ARGV */ + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "i686-pc-linux-android" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 unsigned int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 unsigned int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `long long', as computed by sizeof. */ +/* #undef SIZEOF_LONG_LONG */ + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 4 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#define STRERROR_R_TYPE_ARG3 size_t + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* to enable iOS/Mac OS X native SSL/TLS support */ +/* #undef USE_DARWINSSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* Define to enable metalink support */ +/* #undef USE_METALINK */ + +/* if nghttp2 is in use */ +/* #undef USE_NGHTTP2 */ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* to enable Windows native SSL/TLS support */ +/* #undef USE_SCHANNEL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +#define USE_THREADS_POSIX 1 + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Use Unix domain sockets */ +#define USE_UNIX_SOCKETS 1 + +/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ +/* #undef USE_WIN32_IDN */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to 1 to provide own prototypes. */ +/* #undef WANT_IDN_PROTOTYPES */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ diff --git a/libcurl/src/lib/config-dos.h b/libcurl/src/lib/config-dos.h new file mode 100644 index 0000000..288bd1d --- /dev/null +++ b/libcurl/src/lib/config-dos.h @@ -0,0 +1,181 @@ +#ifndef HEADER_CURL_CONFIG_DOS_H +#define HEADER_CURL_CONFIG_DOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* ================================================================ */ +/* lib/config-dos.h - Hand crafted config file for DOS */ +/* ================================================================ */ + +#if defined(DJGPP) + #define OS "MSDOS/djgpp" +#elif defined(__HIGHC__) + #define OS "MSDOS/HighC" +#elif defined(__WATCOMC__) + #define OS "MSDOS/Watcom" +#else + #define OS "MSDOS/?" +#endif + +#define PACKAGE "curl" + +#define HAVE_ARPA_INET_H 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_GETADDRINFO 1 +#define HAVE_GETNAMEINFO 1 +#define HAVE_GETPROTOBYNAME 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_IO_H 1 +#define HAVE_IOCTL 1 +#define HAVE_IOCTL_FIONBIO 1 +#define HAVE_IOCTLSOCKET 1 +#define HAVE_IOCTLSOCKET_FIONBIO 1 +#define HAVE_LIMITS_H 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LONGLONG 1 +#define HAVE_MEMORY_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_NETINET_TCP_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_PROCESS_H 1 +#define HAVE_RECV 1 +#define HAVE_RECVFROM 1 +#define HAVE_SELECT 1 +#define HAVE_SEND 1 +#define HAVE_SETJMP_H 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SETMODE 1 +#define HAVE_SIGNAL 1 +#define HAVE_SOCKET 1 +#define HAVE_STRDUP 1 +#define HAVE_STRICMP 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRUCT_TIMEVAL 1 +#define HAVE_STRUCT_IN6_ADDR 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UNISTD_H 1 + +#define NEED_MALLOC_H 1 + +#define RETSIGTYPE void +#define SIZEOF_INT 4 +#define SIZEOF_LONG_DOUBLE 16 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 +#define STDC_HEADERS 1 +#define TIME_WITH_SYS_TIME 1 + +/* Qualifiers for send(), recv(), recvfrom() and getnameinfo(). */ + +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void * +#define SEND_TYPE_ARG3 int +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV int + +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void * +#define RECV_TYPE_ARG3 int +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV int + +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 int +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 int +#define RECVFROM_TYPE_RETV int +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 int +#define GETNAMEINFO_TYPE_ARG46 int +#define GETNAMEINFO_TYPE_ARG7 int + +#define BSD + +/* CURLDEBUG definition enables memory tracking */ +/* #define CURLDEBUG */ + +/* USE_ZLIB on cmd-line */ +#ifdef USE_ZLIB + #define HAVE_ZLIB_H 1 + #define HAVE_LIBZ 1 +#endif + +/* USE_OPENSSL on cmd-line */ +#ifdef USE_OPENSSL + #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + #define HAVE_OPENSSL_ENGINE_H 1 + #define OPENSSL_NO_KRB5 1 +#endif + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +#define in_addr_t u_long + +#if defined(__HIGHC__) || \ + (defined(__GNUC__) && (__GNUC__ < 4)) + #define ssize_t int +#endif + +#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE") + +/* Target HAVE_x section */ + +#if defined(DJGPP) + #define HAVE_BASENAME 1 + #define HAVE_STRCASECMP 1 + #define HAVE_SIGACTION 1 + #define HAVE_SIGSETJMP 1 + #define HAVE_SYS_TIME_H 1 + #define HAVE_TERMIOS_H 1 + #define HAVE_VARIADIC_MACROS_GCC 1 + +#elif defined(__WATCOMC__) + #define HAVE_STRCASECMP 1 + +#elif defined(__HIGHC__) + #define HAVE_SYS_TIME_H 1 + #define strerror(e) strerror_s_((e)) +#endif + +#ifdef MSDOS /* Watt-32 */ + #define HAVE_CLOSE_S 1 +#endif + +#undef word +#undef byte + +#endif /* HEADER_CURL_CONFIG_DOS_H */ + diff --git a/libcurl/src/lib/config-emscripten.h b/libcurl/src/lib/config-emscripten.h new file mode 100644 index 0000000..2122818 --- /dev/null +++ b/libcurl/src/lib/config-emscripten.h @@ -0,0 +1,1032 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +/* #undef CURL_DISABLE_FTP */ + +/* to disable Gopher */ +/* #undef CURL_DISABLE_GOPHER */ + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +/* #undef CURL_DISABLE_IMAP */ + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +/* #undef CURL_DISABLE_LIBCURL_OPTION */ + +/* to disable POP3 */ +/* #undef CURL_DISABLE_POP3 */ + +/* to disable proxies */ +/* #undef CURL_DISABLE_PROXY */ + +/* to disable RTSP */ +/* #undef CURL_DISABLE_RTSP */ + +/* to disable SMB/CIFS */ +/* #undef CURL_DISABLE_SMB */ + +/* to disable SMTP */ +/* #undef CURL_DISABLE_SMTP */ + +/* to disable TELNET */ +/* #undef CURL_DISABLE_TELNET */ + +/* to disable TFTP */ +/* #undef CURL_DISABLE_TFTP */ + +/* to disable TLS-SRP authentication */ +/* #undef CURL_DISABLE_TLS_SRP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define to the type of arg 2 for gethostname. */ +#define GETHOSTNAME_TYPE_ARG2 size_t + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 socklen_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Specifies the number of arguments to getservbyport_r */ +#define GETSERVBYPORT_R_ARGS 6 + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#define GETSERVBYPORT_R_BUFSIZE 4096 + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if using BoringSSL. */ +/* #undef HAVE_BORINGSSL */ + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#define HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CYASSL_ERROR_SSL_H */ + +/* Define to 1 if you have the `DES_set_odd_parity' function. */ +/* #undef HAVE_DES_SET_ODD_PARITY */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the fsetxattr function. */ +#define HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +#define HAVE_FSETXATTR_5 1 + +/* fsetxattr() takes 6 args */ +/* #undef HAVE_FSETXATTR_6 */ + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#define HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +#define HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +#define HAVE_GETHOSTBYNAME_R_6 1 + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#define HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#define HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +#define HAVE_GETSERVBYPORT_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have GSS-API libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have GNU GSS */ +/* #undef HAVE_GSSGNU */ + +/* if you have Heimdal */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have MIT Kerberos */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `if_nametoindex' function. */ +#define HAVE_IF_NAMETOINDEX 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +#define HAVE_LDAP_SSL 1 + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if using libressl. */ +/* #undef HAVE_LIBRESSL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +/* #undef HAVE_MEMRCHR */ + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#define HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NGHTTP2_NGHTTP2_H */ + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#define HAVE_POLL 1 + +/* If you have a fine poll */ +#define HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#define HAVE_POSIX_STRERROR_R 1 + +/* if you have */ +/* #undef HAVE_PTHREAD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +/* #undef HAVE_SETMODE */ + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SOCKET_H */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STROPTS_H 1 + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "x86_64-unknown-linux-gnu" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV ssize_t + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV ssize_t + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long long', as computed by sizeof. */ +/* #undef SIZEOF_LONG_LONG */ + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#define STRERROR_R_TYPE_ARG3 size_t + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* to enable iOS/Mac OS X native SSL/TLS support */ +/* #undef USE_DARWINSSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* Define to enable metalink support */ +/* #undef USE_METALINK */ + +/* if nghttp2 is in use */ +/* #undef USE_NGHTTP2 */ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* to enable Windows native SSL/TLS support */ +/* #undef USE_SCHANNEL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +/* #undef USE_THREADS_POSIX */ + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Use Unix domain sockets */ +#define USE_UNIX_SOCKETS 1 + +/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ +/* #undef USE_WIN32_IDN */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* Use Windows LDAP implementation */ +/* #undef USE_WIN32_LDAP */ + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to 1 to provide own prototypes. */ +/* #undef WANT_IDN_PROTOTYPES */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + diff --git a/libcurl/src/lib/config-ios-sim.h b/libcurl/src/lib/config-ios-sim.h new file mode 100644 index 0000000..c94f53e --- /dev/null +++ b/libcurl/src/lib/config-ios-sim.h @@ -0,0 +1,1019 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +#define CURL_DISABLE_COOKIES 1 + +/* to disable cryptographic authentication */ +#define CURL_DISABLE_CRYPTO_AUTH 1 + +/* to disable DICT */ +#define CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#define CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable Gopher */ +#define CURL_DISABLE_GOPHER 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +#define CURL_DISABLE_IMAP 1 + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +#define CURL_DISABLE_LIBCURL_OPTION 1 + +/* to disable POP3 */ +#define CURL_DISABLE_POP3 1 + +/* to disable proxies */ +#define CURL_DISABLE_PROXY 1 + +/* to disable RTSP */ +#define CURL_DISABLE_RTSP 1 + +/* to disable SMB/CIFS */ +#define CURL_DISABLE_SMB 1 + +/* to disable SMTP */ +#define CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable TLS-SRP authentication */ +#define CURL_DISABLE_TLS_SRP 1 + +/* to disable verbose strings */ +#define CURL_DISABLE_VERBOSE_STRINGS 1 + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define to the type of arg 2 for gethostname. */ +#define GETHOSTNAME_TYPE_ARG2 size_t + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 socklen_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Specifies the number of arguments to getservbyport_r */ +/* #undef GETSERVBYPORT_R_ARGS */ + +/* Specifies the size of the buffer to pass to getservbyport_r */ +/* #undef GETSERVBYPORT_R_BUFSIZE */ + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */ + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CYASSL_ERROR_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the fsetxattr function. */ +#define HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +/* #undef HAVE_FSETXATTR_5 */ + +/* fsetxattr() takes 6 args */ +#define HAVE_FSETXATTR_6 1 + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +/* #undef HAVE_GETHOSTBYADDR_R */ + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +/* #undef HAVE_GETHOSTBYADDR_R_8 */ + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#define HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#define HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have GSS-API libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have GNU GSS */ +/* #undef HAVE_GSSGNU */ + +/* if you have Heimdal */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have MIT Kerberos */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `if_nametoindex' function. */ +#define HAVE_IF_NAMETOINDEX 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +/* #undef HAVE_MALLOC_H */ + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +/* #undef HAVE_MEMRCHR */ + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/* #undef HAVE_MSG_NOSIGNAL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NGHTTP2_NGHTTP2_H */ + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#define HAVE_POLL 1 + +/* If you have a fine poll */ +#define HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#define HAVE_POSIX_STRERROR_R 1 + +/* if you have */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SOCKET_H */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "x86_64-apple-darwin13.4.0" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV ssize_t + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV ssize_t + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long long', as computed by sizeof. */ +/* #undef SIZEOF_LONG_LONG */ + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#define STRERROR_R_TYPE_ARG3 size_t + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* to enable iOS/Mac OS X native SSL/TLS support */ +/* #undef USE_DARWINSSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +/* #undef USE_MANUAL */ + +/* Define to enable metalink support */ +/* #undef USE_METALINK */ + +/* if nghttp2 is in use */ +/* #undef USE_NGHTTP2 */ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* to enable Windows native SSL/TLS support */ +/* #undef USE_SCHANNEL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +#define USE_THREADS_POSIX 1 + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Use Unix domain sockets */ +/* #undef USE_UNIX_SOCKETS */ + +/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ +/* #undef USE_WIN32_IDN */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to 1 to provide own prototypes. */ +/* #undef WANT_IDN_PROTOTYPES */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ diff --git a/libcurl/src/lib/config-ios.h b/libcurl/src/lib/config-ios.h new file mode 100644 index 0000000..c94f53e --- /dev/null +++ b/libcurl/src/lib/config-ios.h @@ -0,0 +1,1019 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +#define CURL_DISABLE_COOKIES 1 + +/* to disable cryptographic authentication */ +#define CURL_DISABLE_CRYPTO_AUTH 1 + +/* to disable DICT */ +#define CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#define CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable Gopher */ +#define CURL_DISABLE_GOPHER 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +#define CURL_DISABLE_IMAP 1 + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +#define CURL_DISABLE_LIBCURL_OPTION 1 + +/* to disable POP3 */ +#define CURL_DISABLE_POP3 1 + +/* to disable proxies */ +#define CURL_DISABLE_PROXY 1 + +/* to disable RTSP */ +#define CURL_DISABLE_RTSP 1 + +/* to disable SMB/CIFS */ +#define CURL_DISABLE_SMB 1 + +/* to disable SMTP */ +#define CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable TLS-SRP authentication */ +#define CURL_DISABLE_TLS_SRP 1 + +/* to disable verbose strings */ +#define CURL_DISABLE_VERBOSE_STRINGS 1 + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define to the type of arg 2 for gethostname. */ +#define GETHOSTNAME_TYPE_ARG2 size_t + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 socklen_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Specifies the number of arguments to getservbyport_r */ +/* #undef GETSERVBYPORT_R_ARGS */ + +/* Specifies the size of the buffer to pass to getservbyport_r */ +/* #undef GETSERVBYPORT_R_BUFSIZE */ + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */ + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CYASSL_ERROR_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the fsetxattr function. */ +#define HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +/* #undef HAVE_FSETXATTR_5 */ + +/* fsetxattr() takes 6 args */ +#define HAVE_FSETXATTR_6 1 + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +/* #undef HAVE_GETHOSTBYADDR_R */ + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +/* #undef HAVE_GETHOSTBYADDR_R_8 */ + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#define HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#define HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have GSS-API libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have GNU GSS */ +/* #undef HAVE_GSSGNU */ + +/* if you have Heimdal */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have MIT Kerberos */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `if_nametoindex' function. */ +#define HAVE_IF_NAMETOINDEX 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +/* #undef HAVE_MALLOC_H */ + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +/* #undef HAVE_MEMRCHR */ + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/* #undef HAVE_MSG_NOSIGNAL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NGHTTP2_NGHTTP2_H */ + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#define HAVE_POLL 1 + +/* If you have a fine poll */ +#define HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#define HAVE_POSIX_STRERROR_R 1 + +/* if you have */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SOCKET_H */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "x86_64-apple-darwin13.4.0" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV ssize_t + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV ssize_t + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long long', as computed by sizeof. */ +/* #undef SIZEOF_LONG_LONG */ + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#define STRERROR_R_TYPE_ARG3 size_t + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* to enable iOS/Mac OS X native SSL/TLS support */ +/* #undef USE_DARWINSSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +/* #undef USE_MANUAL */ + +/* Define to enable metalink support */ +/* #undef USE_METALINK */ + +/* if nghttp2 is in use */ +/* #undef USE_NGHTTP2 */ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* to enable Windows native SSL/TLS support */ +/* #undef USE_SCHANNEL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +#define USE_THREADS_POSIX 1 + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Use Unix domain sockets */ +/* #undef USE_UNIX_SOCKETS */ + +/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ +/* #undef USE_WIN32_IDN */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to 1 to provide own prototypes. */ +/* #undef WANT_IDN_PROTOTYPES */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ diff --git a/libcurl/src/lib/config-mac.h b/libcurl/src/lib/config-mac.h new file mode 100644 index 0000000..ee7a659 --- /dev/null +++ b/libcurl/src/lib/config-mac.h @@ -0,0 +1,125 @@ +#ifndef HEADER_CURL_CONFIG_MAC_H +#define HEADER_CURL_CONFIG_MAC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* =================================================================== */ +/* Hand crafted config file for Mac OS 9 */ +/* =================================================================== */ +/* On Mac OS X you must run configure to generate curl_config.h file */ +/* =================================================================== */ + +#define OS "mac" + +/* Define if you want the built-in manual */ +#define USE_MANUAL 1 + +#define HAVE_ERRNO_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_ARPA_INET_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_FCNTL_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_ALLOCA_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UTIME_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_UTIME_H 1 + +#define TIME_WITH_SYS_TIME 1 + +#define HAVE_ALARM 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_UTIME 1 +#define HAVE_SETVBUF 1 +#define HAVE_STRFTIME 1 +#define HAVE_INET_ADDR 1 +#define HAVE_MEMCPY 1 +#define HAVE_SELECT 1 +#define HAVE_SOCKET 1 +#define HAVE_STRUCT_TIMEVAL 1 + +#define HAVE_SIGACTION 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SIG_ATOMIC_T 1 + +#ifdef MACOS_SSL_SUPPORT +# define USE_OPENSSL 1 +#endif + +#define CURL_DISABLE_LDAP 1 + +#define HAVE_RAND_STATUS 1 +#define HAVE_RAND_EGD 1 + +#define HAVE_IOCTL 1 +#define HAVE_IOCTL_FIONBIO 1 + +#define RETSIGTYPE void + +#define SIZEOF_INT 4 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 + +#define HAVE_GETNAMEINFO 1 +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 socklen_t +#define GETNAMEINFO_TYPE_ARG46 size_t +#define GETNAMEINFO_TYPE_ARG7 int + +#define HAVE_RECV 1 +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void * +#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV ssize_t + +#define HAVE_RECVFROM 1 +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 size_t +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 int +#define RECVFROM_TYPE_RETV ssize_t +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define HAVE_SEND 1 +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void * +#define SEND_TYPE_ARG3 size_T +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV ssize_t + +#define HAVE_EXTRA_STRICMP_H 1 +#define HAVE_EXTRA_STRDUP_H 1 + +#endif /* HEADER_CURL_CONFIG_MAC_H */ diff --git a/libcurl/src/lib/config-os400.h b/libcurl/src/lib/config-os400.h new file mode 100644 index 0000000..1e62228 --- /dev/null +++ b/libcurl/src/lib/config-os400.h @@ -0,0 +1,563 @@ +#ifndef HEADER_CURL_CONFIG_OS400_H +#define HEADER_CURL_CONFIG_OS400_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for OS/400 */ +/* ================================================================ */ + +#pragma enum(int) + +#undef PACKAGE + +/* Version number of this archive. */ +#undef VERSION + +/* Define if you have the getpass function. */ +#undef HAVE_GETPASS + +/* Define cpu-machine-OS */ +#define OS "OS/400" + +/* Define if you have the gethostbyaddr_r() function with 5 arguments */ +#define HAVE_GETHOSTBYADDR_R_5 + +/* Define if you have the gethostbyaddr_r() function with 7 arguments */ +#undef HAVE_GETHOSTBYADDR_R_7 + +/* Define if you have the gethostbyaddr_r() function with 8 arguments */ +#undef HAVE_GETHOSTBYADDR_R_8 + +/* OS400 supports a 3-argument ASCII version of gethostbyaddr_r(), but its + * prototype is incompatible with the "standard" one (1st argument is not + * const). However, getaddrinfo() is supported (ASCII version defined as + * a local wrapper in setup-os400.h) in a threadsafe way: we can then + * configure getaddrinfo() as such and get rid of gethostbyname_r() without + * loss of threadsafeness. */ +#undef HAVE_GETHOSTBYNAME_R +#undef HAVE_GETHOSTBYNAME_R_3 +#undef HAVE_GETHOSTBYNAME_R_5 +#undef HAVE_GETHOSTBYNAME_R_6 +#define HAVE_GETADDRINFO +#define HAVE_GETADDRINFO_THREADSAFE + +/* Define if you need the _REENTRANT define for some functions */ +#undef NEED_REENTRANT + +/* Define if you have the Kerberos4 libraries (including -ldes) */ +#undef HAVE_KRB4 + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define this to 'int' if ssize_t is not an available typedefed type */ +#undef ssize_t + +/* Define this as a suitable file to read random data from */ +#undef RANDOM_FILE + +/* Define this to your Entropy Gathering Daemon socket pathname */ +#undef EGD_SOCKET + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Define if you have the header file. */ +#define HAVE_ARPA_INET_H + +/* Define if you have the `closesocket' function. */ +#undef HAVE_CLOSESOCKET + +/* Define if you have the header file. */ +#undef HAVE_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_DES_H + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_ERR_H + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the `geteuid' function. */ +#define HAVE_GETEUID + +/* Define if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR + +/* Define if you have the `gethostbyaddr_r' function. */ +#define HAVE_GETHOSTBYADDR_R + +/* Define if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME + +/* Define if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define if you have the `getpass_r' function. */ +#undef HAVE_GETPASS_R + +/* Define if you have the `getpwuid' function. */ +#define HAVE_GETPWUID + +/* Define if you have the `getservbyname' function. */ +#define HAVE_GETSERVBYNAME + +/* Define if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY + +/* Define if you have the `timeval' struct. */ +#define HAVE_STRUCT_TIMEVAL + +/* Define if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR + +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H + +/* Define if you have the header file. */ +#undef HAVE_IO_H + +/* Define if you have the `krb_get_our_ip_for_realm' function. */ +#undef HAVE_KRB_GET_OUR_IP_FOR_REALM + +/* Define if you have the header file. */ +#undef HAVE_KRB_H + +/* Define if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define if you have the `resolve' library (-lresolve). */ +#undef HAVE_LIBRESOLVE + +/* Define if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* Define if you have GSS API. */ +#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). */ +#undef HAVE_LIBUCB + +/* Define if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R + +/* Define if you have the header file. */ +#define HAVE_MALLOC_H + +/* Define if you need the malloc.h header file even with stdlib.h */ +/* #define NEED_MALLOC_H 1 */ + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#define HAVE_NETDB_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_X509_H + +/* Define if you have the header file. */ +#undef HAVE_PEM_H + +/* Define if you have the `perror' function. */ +#define HAVE_PERROR + +/* Define if you have the header file. */ +#define HAVE_PWD_H + +/* Define if you have the `RAND_egd' function. */ +#undef HAVE_RAND_EGD + +/* Define if you have the `RAND_screen' function. */ +#undef HAVE_RAND_SCREEN + +/* Define if you have the `RAND_status' function. */ +#undef HAVE_RAND_STATUS + +/* Define if you have the header file. */ +#undef HAVE_RSA_H + +/* Define if you have the `select' function. */ +#define HAVE_SELECT + +/* Define if you have the `setvbuf' function. */ +#define HAVE_SETVBUF + +/* Define if you have the header file. */ +#undef HAVE_SGTTY_H + +/* Define if you have the `sigaction' function. */ +#define HAVE_SIGACTION + +/* Define if you have the `signal' function. */ +#undef HAVE_SIGNAL + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T + +/* Define if sig_atomic_t is already defined as volatile. */ +#undef HAVE_SIG_ATOMIC_T_VOLATILE + +/* Define if you have the `socket' function. */ +#define HAVE_SOCKET + +/* Define if you have the header file. */ +#undef HAVE_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H + + +/* The following define is needed on OS400 to enable strcmpi(), stricmp() and + strdup(). */ +#define __cplusplus__strings__ + +/* Define if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the `strcmpi' function. */ +#define HAVE_STRCMPI + +/* Define if you have the `stricmp' function. */ +#define HAVE_STRICMP + +/* Define if you have the `strdup' function. */ +#define HAVE_STRDUP + + +/* Define if you have the `strftime' function. */ +#define HAVE_STRFTIME + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H + +/* Define if you have the header file. */ +#define HAVE_STRING_H + +/* Define if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define if you have the header file. */ +#undef HAVE_STROPTS_H + +/* Define if you have the `strstr' function. */ +#define HAVE_STRSTR + +/* Define if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R + +/* Define if you have the `strtoll' function. */ +#undef HAVE_STRTOLL /* Allows ASCII compile on V5R1. */ + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H + +/* Define if you have the `tcgetattr' function. */ +#undef HAVE_TCGETATTR + +/* Define if you have the `tcsetattr' function. */ +#undef HAVE_TCSETATTR + +/* Define if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define if you have the header file. */ +#define HAVE_TIME_H + +/* Define if you have the `uname' function. */ +#undef HAVE_UNAME + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_WINSOCK_H + +/* Define if you have the header file. */ +#undef HAVE_X509_H + +/* Name of package */ +#undef PACKAGE + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 8 + +/* Define if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG + +/* The size of a `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* Whether long long constants must be suffixed by LL. */ + +#define HAVE_LL + +/* Define this if you have struct sockaddr_storage */ +#define HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#define _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* type to use in place of in_addr_t if not defined */ +#define in_addr_t unsigned long + +/* Define to `unsigned' if does not define. */ +#undef size_t + +/* Define if you have the ioctl function. */ +#define HAVE_IOCTL + +/* Define if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO + +/* Define if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR + +/* To disable LDAP */ +#undef CURL_DISABLE_LDAP + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL + +/* Define if you have the ldap_url_parse procedure. */ +/* #define HAVE_LDAP_URL_PARSE */ /* Disabled because of an IBM bug. */ + +/* Define if you have the getnameinfo function. */ +/* OS400 has no ASCII version of this procedure: wrapped in setup-os400.h. */ +#define HAVE_GETNAMEINFO + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 socklen_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* Define to use the GSKit package. */ +#define USE_GSKIT + +/* Define to use the OS/400 crypto library. */ +#define USE_OS400CRYPTO + +/* Define to use Unix sockets. */ +#define USE_UNIX_SOCKETS + +/* Use the system keyring as the default CA bundle. */ +#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB" + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* The following must be defined BEFORE system header files inclusion. */ + +#define __ptr128 /* No teraspace. */ +#define qadrt_use_fputc_inline /* Generate fputc() wrapper inline. */ +#define qadrt_use_fread_inline /* Generate fread() wrapper inline. */ +#define qadrt_use_fwrite_inline /* Generate fwrite() wrapper inline. */ + +#endif /* HEADER_CURL_CONFIG_OS400_H */ diff --git a/libcurl/src/lib/config-osx.h b/libcurl/src/lib/config-osx.h new file mode 100644 index 0000000..c94f53e --- /dev/null +++ b/libcurl/src/lib/config-osx.h @@ -0,0 +1,1019 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +#define CURL_DISABLE_COOKIES 1 + +/* to disable cryptographic authentication */ +#define CURL_DISABLE_CRYPTO_AUTH 1 + +/* to disable DICT */ +#define CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#define CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable Gopher */ +#define CURL_DISABLE_GOPHER 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +#define CURL_DISABLE_IMAP 1 + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +#define CURL_DISABLE_LIBCURL_OPTION 1 + +/* to disable POP3 */ +#define CURL_DISABLE_POP3 1 + +/* to disable proxies */ +#define CURL_DISABLE_PROXY 1 + +/* to disable RTSP */ +#define CURL_DISABLE_RTSP 1 + +/* to disable SMB/CIFS */ +#define CURL_DISABLE_SMB 1 + +/* to disable SMTP */ +#define CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable TLS-SRP authentication */ +#define CURL_DISABLE_TLS_SRP 1 + +/* to disable verbose strings */ +#define CURL_DISABLE_VERBOSE_STRINGS 1 + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define to the type of arg 2 for gethostname. */ +#define GETHOSTNAME_TYPE_ARG2 size_t + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 socklen_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Specifies the number of arguments to getservbyport_r */ +/* #undef GETSERVBYPORT_R_ARGS */ + +/* Specifies the size of the buffer to pass to getservbyport_r */ +/* #undef GETSERVBYPORT_R_BUFSIZE */ + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */ + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CYASSL_ERROR_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the fsetxattr function. */ +#define HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +/* #undef HAVE_FSETXATTR_5 */ + +/* fsetxattr() takes 6 args */ +#define HAVE_FSETXATTR_6 1 + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +/* #undef HAVE_GETHOSTBYADDR_R */ + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +/* #undef HAVE_GETHOSTBYADDR_R_8 */ + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#define HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#define HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have GSS-API libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have GNU GSS */ +/* #undef HAVE_GSSGNU */ + +/* if you have Heimdal */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have MIT Kerberos */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `if_nametoindex' function. */ +#define HAVE_IF_NAMETOINDEX 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +/* #undef HAVE_MALLOC_H */ + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +/* #undef HAVE_MEMRCHR */ + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/* #undef HAVE_MSG_NOSIGNAL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NGHTTP2_NGHTTP2_H */ + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#define HAVE_POLL 1 + +/* If you have a fine poll */ +#define HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#define HAVE_POSIX_STRERROR_R 1 + +/* if you have */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SOCKET_H */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "x86_64-apple-darwin13.4.0" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV ssize_t + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV ssize_t + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long long', as computed by sizeof. */ +/* #undef SIZEOF_LONG_LONG */ + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#define STRERROR_R_TYPE_ARG3 size_t + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* to enable iOS/Mac OS X native SSL/TLS support */ +/* #undef USE_DARWINSSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +/* #undef USE_MANUAL */ + +/* Define to enable metalink support */ +/* #undef USE_METALINK */ + +/* if nghttp2 is in use */ +/* #undef USE_NGHTTP2 */ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* to enable Windows native SSL/TLS support */ +/* #undef USE_SCHANNEL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +#define USE_THREADS_POSIX 1 + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Use Unix domain sockets */ +/* #undef USE_UNIX_SOCKETS */ + +/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ +/* #undef USE_WIN32_IDN */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to 1 to provide own prototypes. */ +/* #undef WANT_IDN_PROTOTYPES */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ diff --git a/libcurl/src/lib/config-riscos.h b/libcurl/src/lib/config-riscos.h new file mode 100644 index 0000000..e400577 --- /dev/null +++ b/libcurl/src/lib/config-riscos.h @@ -0,0 +1,513 @@ +#ifndef HEADER_CURL_CONFIG_RISCOS_H +#define HEADER_CURL_CONFIG_RISCOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for RISC OS */ +/* ================================================================ */ + +/* Name of this package! */ +#undef PACKAGE + +/* Version number of this archive. */ +#undef VERSION + +/* Define if you have the getpass function. */ +#undef HAVE_GETPASS + +/* Define cpu-machine-OS */ +#define OS "ARM-RISC OS" + +/* Define if you want the built-in manual */ +#define USE_MANUAL + +/* Define if you have the gethostbyaddr_r() function with 5 arguments */ +#undef HAVE_GETHOSTBYADDR_R_5 + +/* Define if you have the gethostbyaddr_r() function with 7 arguments */ +#undef HAVE_GETHOSTBYADDR_R_7 + +/* Define if you have the gethostbyaddr_r() function with 8 arguments */ +#undef HAVE_GETHOSTBYADDR_R_8 + +/* Define if you have the gethostbyname_r() function with 3 arguments */ +#undef HAVE_GETHOSTBYNAME_R_3 + +/* Define if you have the gethostbyname_r() function with 5 arguments */ +#undef HAVE_GETHOSTBYNAME_R_5 + +/* Define if you have the gethostbyname_r() function with 6 arguments */ +#undef HAVE_GETHOSTBYNAME_R_6 + +/* Define if you need the _REENTRANT define for some functions */ +#undef NEED_REENTRANT + +/* Define if you have the Kerberos4 libraries (including -ldes) */ +#undef HAVE_KRB4 + +/* Define if you want to enable IPv6 support */ +#undef ENABLE_IPV6 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define this to 'int' if ssize_t is not an available typedefed type */ +#undef ssize_t + +/* Define this as a suitable file to read random data from */ +#undef RANDOM_FILE + +/* Define this to your Entropy Gathering Daemon socket pathname */ +#undef EGD_SOCKET + +/* Define if you want to enable IPv6 support */ +#undef ENABLE_IPV6 + +/* Define if you have the alarm function. */ +#define HAVE_ALARM + +/* Define if you have the header file. */ +#define HAVE_ALLOCA_H + +/* Define if you have the header file. */ +#define HAVE_ARPA_INET_H + +/* Define if you have the `closesocket' function. */ +#undef HAVE_CLOSESOCKET + +/* Define if you have the header file. */ +#undef HAVE_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_DES_H + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_ERR_H + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE + +/* Define if getaddrinfo exists and works */ +#define HAVE_GETADDRINFO + +/* Define if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR + +/* Define if you have the `gethostbyaddr_r' function. */ +#undef HAVE_GETHOSTBYADDR_R + +/* Define if you have the `gethostbyname_r' function. */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME + +/* Define if you have the header file. */ +#define HAVE_GETOPT_H + +/* Define if you have the `getpass_r' function. */ +#undef HAVE_GETPASS_R + +/* Define if you have the `getpwuid' function. */ +#undef HAVE_GETPWUID + +/* Define if you have the `getservbyname' function. */ +#undef HAVE_GETSERVBYNAME + +/* Define if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY + +/* Define if you have the `timeval' struct. */ +#define HAVE_STRUCT_TIMEVAL + +/* Define if you have the `inet_addr' function. */ +#undef HAVE_INET_ADDR + +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H + +/* Define if you have the header file. */ +#undef HAVE_IO_H + +/* Define if you have the `krb_get_our_ip_for_realm' function. */ +#undef HAVE_KRB_GET_OUR_IP_FOR_REALM + +/* Define if you have the header file. */ +#undef HAVE_KRB_H + +/* Define if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define if you have the `resolve' library (-lresolve). */ +#undef HAVE_LIBRESOLVE + +/* Define if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* Define if you have the `ucb' library (-lucb). */ +#undef HAVE_LIBUCB + +/* Define if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define if you have the header file. */ +#define HAVE_MALLOC_H + +/* Define if you need the malloc.h header file even with stdlib.h */ +/* #define NEED_MALLOC_H 1 */ + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#define HAVE_NETDB_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_X509_H + +/* Define if you have the header file. */ +#undef HAVE_PEM_H + +/* Define if you have the `perror' function. */ +#undef HAVE_PERROR + +/* Define if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if you have the `RAND_egd' function. */ +#undef HAVE_RAND_EGD + +/* Define if you have the `RAND_screen' function. */ +#undef HAVE_RAND_SCREEN + +/* Define if you have the `RAND_status' function. */ +#undef HAVE_RAND_STATUS + +/* Define if you have the header file. */ +#undef HAVE_RSA_H + +/* Define if you have the `select' function. */ +#define HAVE_SELECT + +/* Define if you have the `setvbuf' function. */ +#undef HAVE_SETVBUF + +/* Define if you have the header file. */ +#define HAVE_SGTTY_H + +/* Define if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define if you have the `signal' function. */ +#define HAVE_SIGNAL + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T + +/* Define if sig_atomic_t is already defined as volatile. */ +#undef HAVE_SIG_ATOMIC_T_VOLATILE + +/* Define if you have the `socket' function. */ +#define HAVE_SOCKET + +/* Define if you have the header file. */ +#undef HAVE_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the `strcmpi' function. */ +#undef HAVE_STRCMPI + +/* Define if you have the `strdup' function. */ +#define HAVE_STRDUP + +/* Define if you have the `strftime' function. */ +#define HAVE_STRFTIME + +/* Define if you have the `stricmp' function. */ +#define HAVE_STRICMP + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#define HAVE_STRING_H + +/* Define if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define if you have the `strstr' function. */ +#define HAVE_STRSTR + +/* Define if you have the `strtok_r' function. */ +#undef HAVE_STRTOK_R + +/* Define if you have the `strtoll' function. */ +#undef HAVE_STRTOLL + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H + +/* Define if you have the `tcgetattr' function. */ +#define HAVE_TCGETATTR + +/* Define if you have the `tcsetattr' function. */ +#define HAVE_TCSETATTR + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the `uname' function. */ +#define HAVE_UNAME + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_WINSOCK_H + +/* Define if you have the header file. */ +#undef HAVE_X509_H + +/* Name of package */ +#undef PACKAGE + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long double', as computed by sizeof. */ +#undef SIZEOF_LONG_DOUBLE + +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define if you have the ioctl function. */ +#define HAVE_IOCTL + +/* Define if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP + +/* Define if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV ssize_t + +/* Define 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV ssize_t + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV ssize_t + +#endif /* HEADER_CURL_CONFIG_RISCOS_H */ diff --git a/libcurl/src/lib/config-symbian.h b/libcurl/src/lib/config-symbian.h new file mode 100644 index 0000000..a40e3d8 --- /dev/null +++ b/libcurl/src/lib/config-symbian.h @@ -0,0 +1,811 @@ +#ifndef HEADER_CURL_CONFIG_SYMBIAN_H +#define HEADER_CURL_CONFIG_SYMBIAN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for Symbian */ +/* ================================================================ */ + +/* Location of default ca bundle */ +/* #define CURL_CA_BUNDLE "/etc/pki/tls/certs/ca-bundle.crt"*/ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +/* #undef CURL_DISABLE_FTP */ + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable TELNET */ +/* #undef CURL_DISABLE_TELNET */ + +/* to disable TFTP */ +/* #undef CURL_DISABLE_TFTP */ + +/* to disable verbose strings */ +/* #define CURL_DISABLE_VERBOSE_STRINGS 1*/ + +/* Definition to make a library symbol externally visible. */ +/* #undef CURL_EXTERN_SYMBOL */ + +/* Use Windows LDAP implementation */ +/* #undef USE_WIN32_LDAP */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define to 1 if you have the header file. */ +/*#define HAVE_ALLOCA_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_ARPA_TFTP_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +/*#define HAVE_BASENAME 1*/ + +/* Define to 1 if bool is an available type. */ +/*#define HAVE_BOOL_T 1*/ + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/*#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1*/ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/*#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +/*#define HAVE_FORK 1*/ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define if getaddrinfo exists and works */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* If you have gethostbyname */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +/*#define HAVE_GETRLIMIT 1*/ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* we have a glibc-style strerror_r() */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/*#define HAVE_IDNA_STRERROR 1*/ + +/* Define to 1 if you have the `idn_free' function. */ +/*#define HAVE_IDN_FREE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_IDN_FREE_H 1*/ + +/* Define to 1 if you have the `inet_addr' function. */ +/*#define HAVE_INET_ADDR 1*/ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/*#define HAVE_INET_NTOP 1*/ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/*#define HAVE_INET_PTON 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO + function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/*#define HAVE_LBER_H 1*/ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/*#define HAVE_LDAP_H 1*/ + +/* Use LDAPS implementation */ +/*#define HAVE_LDAP_SSL 1*/ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/*#define HAVE_LDAP_URL_PARSE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_LIBGEN_H 1*/ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/*#define HAVE_LIBIDN 1*/ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/*#define HAVE_LIBSSH2 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_LIBSSH2_H 1*/ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/*#define HAVE_LIBSSL 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +/*#define HAVE_MALLOC_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/*#define HAVE_MSG_NOSIGNAL 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_NETINET_TCP_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/*#define HAVE_NI_WITHSCOPEID 1*/ + +/* we have no strerror_r() proto */ +/* #undef HAVE_NO_STRERROR_R_DECL */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_CRYPTO_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_ENGINE_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_ERR_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_PEM_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_PKCS12_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_RSA_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_SSL_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_X509_H 1*/ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `poll' function. */ +/*#define HAVE_POLL 1*/ + +/* If you have a fine poll */ +/*#define HAVE_POLL_FINE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_POLL_H 1*/ + +/* we have a POSIX-style strerror_r() */ +#define HAVE_POSIX_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/*#define HAVE_RAND_STATUS 1*/ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +/* #undef HAVE_SETMODE */ + +/* Define to 1 if you have the `setrlimit' function. */ +/*#define HAVE_SETRLIMIT 1*/ + +/* Define to 1 if you have the setsockopt function. */ +/* #undef HAVE_SETSOCKOPT */ + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_SGTTY_H 1*/ + +/* Define to 1 if you have the `sigaction' function. */ +/*#define HAVE_SIGACTION 1*/ + +/* Define to 1 if you have the `siginterrupt' function. */ +/*#define HAVE_SIGINTERRUPT 1*/ + +/* Define to 1 if you have the `signal' function. */ +/*#define HAVE_SIGNAL 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* If you have sigsetjmp */ +/*#define HAVE_SIGSETJMP 1*/ + +/* Define to 1 if sig_atomic_t is an available typedef. */ +/*#define HAVE_SIG_ATOMIC_T 1*/ + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/*#define HAVE_SSL_GET_SHUTDOWN 1*/ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#define HAVE_STRLCPY 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_SYS_POLL_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TERMIOS_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TERMIO_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TLD_H 1*/ + +/* Define to 1 if you have the `tld_strerror' function. */ +/*#define HAVE_TLD_STRERROR 1*/ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +/*#define HAVE_VARIADIC_MACROS_GCC 1*/ + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +/*#define HAVE_WRITABLE_ARGV 1*/ + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* cpu-machine-OS */ +#ifdef __WINS__ +#define OS "i386-pc-epoc32" +#elif __MARM__ +#define OS "arm-unknown-epoc32" +#else +/* This won't happen on any current Symbian version */ +#define OS "unknown-unknown-epoc32" +#endif + +/* Name of package */ +/*#define PACKAGE "curl"*/ + +/* Define to the address where bug reports for this package should be sent. */ +/*#define PACKAGE_BUGREPORT \ + "a suitable curl mailing list => http://curl.haxx.se/mail/"*/ + +/* Define to the full name of this package. */ +/*#define PACKAGE_NAME "curl"*/ + +/* Define to the full name and version of this package. */ +/*#define PACKAGE_STRING "curl -"*/ + +/* Define to the one symbol short name of this package. */ +/*#define PACKAGE_TARNAME "curl"*/ + +/* Define to the version of this package. */ +/*#define PACKAGE_VERSION "-"*/ + +/* a suitable file to read random data from */ +/*#define RANDOM_FILE "/dev/urandom"*/ + +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void* +#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV ssize_t + +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 size_t +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 size_t +#define RECVFROM_TYPE_RETV ssize_t +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void* +#define SEND_TYPE_ARG3 size_t +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV ssize_t + + +/* Define as the return type of signal handlers (`int' or `void'). */ +/*#define RETSIGTYPE void*/ + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable c-ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if libSSH2 is in use */ +/*#define USE_LIBSSH2 1*/ + +/* If you want to build curl with the built-in manual */ +/*#define USE_MANUAL 1*/ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +/*#define VERSION "7.18.2-CVS"*/ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* type to use in place of in_addr_t if not defined */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +/* Enabling curl debug mode when building in Symbian debug mode would work */ +/* except that debug mode introduces new exports that must be frozen. */ +#ifdef _DEBUG +/* #define CURLDEBUG */ +#endif + +/* sys/cdefs.h fails to define this for WINSCW prior to Symbian OS ver. 9.4 */ +#ifndef __LONG_LONG_SUPPORTED +#define __LONG_LONG_SUPPORTED +#endif + +/* Enable appropriate header only when zlib support is enabled */ +#ifdef HAVE_LIBZ +#define HAVE_ZLIB_H 1 +#endif + +#endif /* HEADER_CURL_CONFIG_SYMBIAN_H */ diff --git a/libcurl/src/lib/config-tpf.h b/libcurl/src/lib/config-tpf.h new file mode 100644 index 0000000..d6b8cc2 --- /dev/null +++ b/libcurl/src/lib/config-tpf.h @@ -0,0 +1,772 @@ +#ifndef HEADER_CURL_CONFIG_TPF_H +#define HEADER_CURL_CONFIG_TPF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for TPF */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* FEATURES, FUNCTIONS, and DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* NOTE: Refer also to the .mak file for some of the flags below */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +/* #undef CURL_DISABLE_FTP */ + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +/* #undef CURL_DISABLE_LDAP */ + +/* to disable TELNET */ +/* #undef CURL_DISABLE_TELNET */ + +/* to disable TFTP */ +/* #undef CURL_DISABLE_TFTP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* lber dynamic library file */ +/* #undef DL_LBER_FILE */ + +/* ldap dynamic library file */ +/* #undef DL_LDAP_FILE */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ + +/* Define to the type of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG1 */ + +/* Define to the type of arg 2 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG2 */ + +/* Define to the type of args 4 and 6 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG46 */ + +/* Define to the type of arg 7 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG7 */ + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ +#define HAVE_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ +#define HAVE_DES_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ +#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ +#define HAVE_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +/* #undef HAVE_FORK */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define if getaddrinfo exists and works */ +/* #undef HAVE_GETADDRINFO */ + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* If you have gethostbyname */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 1 */ + +/* Define to 1 if you have the getnameinfo function. */ +/* #undef HAVE_GETNAMEINFO */ + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getprotobyname' function. */ +/* #undef HAVE_GETPROTOBYNAME */ + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +/* #undef HAVE_GETRLIMIT */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* we have a glibc-style strerror_r() */ +/* #undef HAVE_GLIBC_STRERROR_R */ +#define HAVE_GLIBC_STRERROR_R 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `iconv' functions. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/* #undef HAVE_INET_NTOP */ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/* #undef HAVE_INET_PTON */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO + function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBGEN_H 1 */ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ +#define HAVE_LIBSSL 1 + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if NI_WITHSCOPEID exists and works */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* we have no strerror_r() proto */ +/* #undef HAVE_NO_STRERROR_R_DECL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ +#define HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ +#define HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ +#define HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ +#define HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ +#define HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ +#define HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ +#define HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ +#define HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ +#define HAVE_PEM_H 1 + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `poll' function. */ +/* #undef HAVE_POLL */ + +/* If you have a fine poll */ +/* #undef HAVE_POLL_FINE */ + +/* we have a POSIX-style strerror_r() */ +/* #undef HAVE_POSIX_STRERROR_R */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ +#define HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ +#define HAVE_RSA_H 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +/* #undef HAVE_SETSOCKOPT */ + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SGTTY_H 1 */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `siginterrupt' function. */ +/* #undef HAVE_SIGINTERRUPT */ + +/* Define to 1 if you have the `signal' function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* If you have sigsetjmp */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ +#define HAVE_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ +#define HAVE_STRICMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE */ + +/* Define this if you have struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +/* #undef HAVE_WRITABLE_ARGV */ + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* cpu-machine-OS */ +#define OS "s390x-ibm-tpf" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT \ + "a suitable curl mailing list => http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* If you want to build curl with the built-in manual */ +/* #undef USE_MANUAL */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if SSL is enabled */ +/* #undef USE_OPENSSL */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Version number of package */ +#define VERSION "not-used" + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* type to use in place of in_addr_t if not defined */ +/* #undef in_addr_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +/* Define to 1 if you have the getnameinfo function. */ +/* #undef HAVE_GETNAMEINFO 1 */ + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_QUAL_ARG1 const */ + +/* Define to the type of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG1 struct sockaddr * */ + +/* Define to the type of arg 2 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG2 socklen_t */ + +/* Define to the type of args 4 and 6 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG46 size_t */ + +/* Define to the type of arg 7 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG7 int */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +#define CURL_DOES_CONVERSIONS +#ifndef CURL_ICONV_CODESET_OF_HOST +#define CURL_ICONV_CODESET_OF_HOST "IBM-1047" +#endif + + +#endif /* HEADER_CURL_CONFIG_TPF_H */ diff --git a/libcurl/src/lib/config-vxworks.h b/libcurl/src/lib/config-vxworks.h new file mode 100644 index 0000000..d889efc --- /dev/null +++ b/libcurl/src/lib/config-vxworks.h @@ -0,0 +1,928 @@ +#ifndef HEADER_CURL_CONFIG_VXWORKS_H +#define HEADER_CURL_CONFIG_VXWORKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* =============================================================== */ +/* Hand crafted config file for VxWorks */ +/* =============================================================== */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable NTLM authentication */ +#define CURL_DISABLE_NTLM 1 + +/* to disable proxies */ +/* #undef CURL_DISABLE_PROXY */ + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +/* #undef CURL_EXTERN_SYMBOL */ + +/* Use Windows LDAP implementation */ +/* #undef USE_WIN32_LDAP */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 unsigned int + +/* Specifies the number of arguments to getservbyport_r */ +#define GETSERVBYPORT_R_ARGS 6 + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#define GETSERVBYPORT_R_BUFSIZE 4096 + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +/* #undef HAVE_BASENAME */ + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */ + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +/* #undef HAVE_GETEUID */ + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#define HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +#define HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +/* #undef HAVE_GETIFADDRS */ + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +/* #undef HAVE_GETPWUID */ + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IFADDRS_H */ + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/* #undef HAVE_INET_NTOP */ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/* #undef HAVE_INET_PTON */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBGEN_H */ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `libssh2_version' function. */ +/* #undef HAVE_LIBSSH2_VERSION */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#define HAVE_LIBSSL 1 + +/* if zlib is available */ +#define HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/* #undef HAVE_MSG_NOSIGNAL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +/* #undef HAVE_POLL */ + +/* If you have a fine poll */ +/* #undef HAVE_POLL_FINE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_POLL_H */ + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +/* #undef HAVE_POSIX_STRERROR_R */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 if you have the `RAND_egd' function. */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +#define HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SGTTY_H */ + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +#define HAVE_SSL_GET_SHUTDOWN 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +/* #undef HAVE_STRTOLL */ + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_PARAM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_TIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have a working vxworks-style strerror_r function. */ +#define HAVE_VXWORKS_STRERROR_R 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +#define HAVE_ZLIB_H 1 + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to 1 if the open function requires three arguments. */ +#define OPEN_NEEDS_ARG3 1 + +/* cpu-machine-OS */ +#define OS "unknown-unknown-vxworks" + +/* Name of package */ +#define PACKAGE "curl" + +/* a suitable file to read random data from */ +#define RANDOM_FILE "/dev/urandom" + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG5_IS_VOID */ + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 socklen_t + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG6_IS_VOID */ + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +/* #undef STRERROR_R_TYPE_ARG3 */ + +/* Define to 1 if you can safely include both and . */ +/* #undef TIME_WITH_SYS_TIME */ + +/* Define if you want to enable c-ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets. */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* if OpenSSL is in use */ +#define USE_OPENSSL 1 + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +#endif /* HEADER_CURL_CONFIG_VXWORKS_H */ diff --git a/libcurl/src/lib/config-win32.h b/libcurl/src/lib/config-win32.h new file mode 100644 index 0000000..e9a3712 --- /dev/null +++ b/libcurl/src/lib/config-win32.h @@ -0,0 +1,734 @@ +#ifndef HEADER_CURL_CONFIG_WIN32_H +#define HEADER_CURL_CONFIG_WIN32_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for Windows */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* HEADER FILES */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the header file. */ +/* #define HAVE_ARPA_INET_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_CRYPTO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_ERR_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__POCC__) +#define HAVE_GETOPT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_INTTYPES_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you need header even with header file. */ +#if !defined(__SALFORDC__) && !defined(__POCC__) +#define NEED_MALLOC_H 1 +#endif + +/* Define if you have the header file. */ +/* #define HAVE_NETDB_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_NETINET_IN_H 1 */ + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_PROCESS_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SGTTY_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SSL_H 1 */ + +/* Define to 1 if you have the header file. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_STDBOOL_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKIO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#ifndef __BORLANDC__ +#define HAVE_SYS_UTIME_H 1 +#endif + +/* Define if you have the header file. */ +/* #define HAVE_TERMIO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_TERMIOS_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) || \ + defined(__POCC__) +#define HAVE_UNISTD_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define if you have the header file. */ +#define HAVE_WINSOCK_H 1 + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_WINSOCK2_H 1 +#endif + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_WS2TCPIP_H 1 +#endif + +/* ---------------------------------------------------------------- */ +/* OTHER HEADER INFO */ +/* ---------------------------------------------------------------- */ + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +/* #define TIME_WITH_SYS_TIME 1 */ + +/* Define to 1 if bool is an available type. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_BOOL_T 1 +#endif + +/* ---------------------------------------------------------------- */ +/* FUNCTIONS */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the closesocket function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #define HAVE_DOPRNT 1 */ + +/* Define if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the getpass function. */ +/* #define HAVE_GETPASS 1 */ + +/* Define if you have the getservbyname function. */ +#define HAVE_GETSERVBYNAME 1 + +/* Define if you have the getprotobyname function. */ +#define HAVE_GETPROTOBYNAME + +/* Define if you have the gettimeofday function. */ +/* #define HAVE_GETTIMEOFDAY 1 */ + +/* Define if you have the inet_addr function. */ +#define HAVE_INET_ADDR 1 + +/* Define if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define if you have the perror function. */ +#define HAVE_PERROR 1 + +/* Define if you have the RAND_screen function when using SSL. */ +#define HAVE_RAND_SCREEN 1 + +/* Define if you have the `RAND_status' function when using SSL. */ +#define HAVE_RAND_STATUS 1 + +/* Define if you have the `CRYPTO_cleanup_all_ex_data' function. + This is present in OpenSSL versions after 0.9.6b */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the setlocale function. */ +#define HAVE_SETLOCALE 1 + +/* Define if you have the setmode function. */ +#define HAVE_SETMODE 1 + +/* Define if you have the setvbuf function. */ +#define HAVE_SETVBUF 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strcasecmp function. */ +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have the stricmp function. */ +#define HAVE_STRICMP 1 + +/* Define if you have the strncasecmp function. */ +/* #define HAVE_STRNCASECMP 1 */ + +/* Define if you have the strnicmp function. */ +#define HAVE_STRNICMP 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtoll function. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__POCC__) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1800)) +#define HAVE_STRTOLL 1 +#endif + +/* Define if you have the tcgetattr function. */ +/* #define HAVE_TCGETATTR 1 */ + +/* Define if you have the tcsetattr function. */ +/* #define HAVE_TCSETATTR 1 */ + +/* Define if you have the utime function. */ +#ifndef __BORLANDC__ +#define HAVE_UTIME 1 +#endif + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 DWORD + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* ---------------------------------------------------------------- */ +/* TYPEDEF REPLACEMENTS */ +/* ---------------------------------------------------------------- */ + +/* Define if in_addr_t is not an available 'typedefed' type. */ +#define in_addr_t unsigned long + +/* Define to the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define if ssize_t is not an available 'typedefed' type. */ +#ifndef _SSIZE_T_DEFINED +# if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || \ + defined(__POCC__) || \ + defined(__MINGW32__) +# elif defined(_WIN64) +# define _SSIZE_T_DEFINED +# define ssize_t __int64 +# else +# define _SSIZE_T_DEFINED +# define ssize_t int +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* TYPE SIZES */ +/* ---------------------------------------------------------------- */ + +/* Define to the size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* Define to the size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* Define to the size of `long long', as computed by sizeof. */ +/* #define SIZEOF_LONG_LONG 8 */ + +/* Define to the size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Define to the size of `size_t', as computed by sizeof. */ +#if defined(_WIN64) +# define SIZEOF_SIZE_T 8 +#else +# define SIZEOF_SIZE_T 4 +#endif + +/* ---------------------------------------------------------------- */ +/* BSD-style lwIP TCP/IP stack SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Define to use BSD-style lwIP TCP/IP stack. */ +/* #define USE_LWIPSOCK 1 */ + +#ifdef USE_LWIPSOCK +# undef USE_WINSOCK +# undef HAVE_WINSOCK_H +# undef HAVE_WINSOCK2_H +# undef HAVE_WS2TCPIP_H +# undef HAVE_ERRNO_H +# undef HAVE_GETHOSTNAME +# undef HAVE_GETNAMEINFO +# undef LWIP_POSIX_SOCKETS_IO_NAMES +# undef RECV_TYPE_ARG1 +# undef RECV_TYPE_ARG3 +# undef SEND_TYPE_ARG1 +# undef SEND_TYPE_ARG3 +# define HAVE_FREEADDRINFO +# define HAVE_GETADDRINFO +# define HAVE_GETHOSTBYNAME +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GETHOSTBYNAME_R_6 +# define LWIP_POSIX_SOCKETS_IO_NAMES 0 +# define RECV_TYPE_ARG1 int +# define RECV_TYPE_ARG3 size_t +# define SEND_TYPE_ARG1 int +# define SEND_TYPE_ARG3 size_t +#endif + +/* ---------------------------------------------------------------- */ +/* Watt-32 tcp/ip SPECIFIC */ +/* ---------------------------------------------------------------- */ + +#ifdef USE_WATT32 + #include + #undef byte + #undef word + #undef USE_WINSOCK + #undef HAVE_WINSOCK_H + #undef HAVE_WINSOCK2_H + #undef HAVE_WS2TCPIP_H + #define HAVE_GETADDRINFO + #define HAVE_GETNAMEINFO + #define HAVE_SYS_IOCTL_H + #define HAVE_SYS_SOCKET_H + #define HAVE_NETINET_IN_H + #define HAVE_NETDB_H + #define HAVE_ARPA_INET_H + #define HAVE_FREEADDRINFO + #define SOCKET int +#endif + + +/* ---------------------------------------------------------------- */ +/* COMPILER SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Define to nothing if compiler does not support 'const' qualifier. */ +/* #define const */ + +/* Define to nothing if compiler does not support 'volatile' qualifier. */ +/* #define volatile */ + +/* Windows should not have HAVE_GMTIME_R defined */ +/* #undef HAVE_GMTIME_R */ + +/* Define if the compiler supports C99 variadic macro style. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define HAVE_VARIADIC_MACROS_C99 1 +#endif + +/* Define if the compiler supports the 'long long' data type. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1310)) +#define HAVE_LONGLONG 1 +#endif + +/* Define to avoid VS2005 complaining about portable C functions. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +/* VS2005 and later dafault size for time_t is 64-bit, unless + _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# ifndef _USE_32BIT_TIME_T +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +#endif + +/* Define some minimum and default build targets for Visual Studio */ +#if defined(_MSC_VER) + /* Officially, Microsoft's Windows SDK versions 6.X does not support Windows + 2000 as a supported build target. VS2008 default installations provides + an embedded Windows SDK v6.0A along with the claim that Windows 2000 is a + valid build target for VS2008. Popular belief is that binaries built with + VS2008 using Windows SDK versions v6.X and Windows 2000 as a build target + are functional. */ +# define VS2008_MIN_TARGET 0x0500 + + /* The minimum build target for VS2012 is Vista unless Update 1 is installed + and the v110_xp toolset is choosen. */ +# if defined(_USING_V110_SDK71_) +# define VS2012_MIN_TARGET 0x0501 +# else +# define VS2012_MIN_TARGET 0x0600 +# endif + + /* VS2008 default build target is Windows Vista. We override default target + to be Windows XP. */ +# define VS2008_DEF_TARGET 0x0501 + + /* VS2012 default build target is Windows Vista unless Update 1 is installed + and the v110_xp toolset is choosen. */ +# if defined(_USING_V110_SDK71_) +# define VS2012_DEF_TARGET 0x0501 +# else +# define VS2012_DEF_TARGET 0x0600 +# endif +#endif + +/* VS2008 default target settings and minimum build target check. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER <= 1600) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT VS2008_DEF_TARGET +# endif +# ifndef WINVER +# define WINVER VS2008_DEF_TARGET +# endif +# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET) +# error VS2008 does not support Windows build targets prior to Windows 2000 +# endif +#endif + +/* VS2012 default target settings and minimum build target check. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT VS2012_DEF_TARGET +# endif +# ifndef WINVER +# define WINVER VS2012_DEF_TARGET +# endif +# if (_WIN32_WINNT < VS2012_MIN_TARGET) || (WINVER < VS2012_MIN_TARGET) +# if defined(_USING_V110_SDK71_) +# error VS2012 does not support Windows build targets prior to Windows XP +# else +# error VS2012 does not support Windows build targets prior to Windows \ +Vista +# endif +# endif +#endif + +/* When no build target is specified Pelles C 5.00 and later default build + target is Windows Vista. We override default target to be Windows 2000. */ +#if defined(__POCC__) && (__POCC__ >= 500) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# ifndef WINVER +# define WINVER 0x0500 +# endif +#endif + +/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is + quite convoluted, compiler dependent and even build target dependent. */ +#if defined(HAVE_WS2TCPIP_H) +# if defined(__POCC__) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# elif defined(_MSC_VER) && (_MSC_VER >= 1200) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# endif +#endif + +#if defined(__POCC__) +# ifndef _MSC_VER +# error Microsoft extensions /Ze compiler option is required +# endif +# ifndef __POCC__OLDNAMES +# error Compatibility names /Go compiler option is required +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* STRUCT RELATED */ +/* ---------------------------------------------------------------- */ + +/* Define if you have struct sockaddr_storage. */ +#if !defined(__SALFORDC__) && !defined(__BORLANDC__) +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 +#endif + +/* Define if you have struct timeval. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member. */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +#if HAVE_WINSOCK2_H && defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) +#define HAVE_STRUCT_POLLFD 1 +#endif + +/* ---------------------------------------------------------------- */ +/* LARGE FILE SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +#if defined(__MINGW32__) && !defined(USE_WIN32_LARGE_FILES) +# define USE_WIN32_LARGE_FILES +#endif + +#if defined(__WATCOMC__) && !defined(USE_WIN32_LARGE_FILES) +# define USE_WIN32_LARGE_FILES +#endif + +#if defined(__POCC__) +# undef USE_WIN32_LARGE_FILES +#endif + +#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) +# define USE_WIN32_SMALL_FILES +#endif + +/* ---------------------------------------------------------------- */ +/* DNS RESOLVER SPECIALTY */ +/* ---------------------------------------------------------------- */ + +/* + * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS. + */ + +/* Define to enable c-ares asynchronous DNS lookups. */ +/* #define USE_ARES 1 */ + +/* Default define to enable threaded asynchronous DNS lookups. */ +#if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \ + !defined(USE_THREADS_WIN32) +# define USE_THREADS_WIN32 1 +#endif + +#if defined(USE_ARES) && defined(USE_THREADS_WIN32) +# error "Only one DNS lookup specialty may be defined at most" +#endif + +/* ---------------------------------------------------------------- */ +/* LDAP SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(CURL_HAS_NOVELL_LDAPSDK) || defined(CURL_HAS_MOZILLA_LDAPSDK) +#undef USE_WIN32_LDAP +#define HAVE_LDAP_SSL_H 1 +#define HAVE_LDAP_URL_PARSE 1 +#elif defined(CURL_HAS_OPENLDAP_LDAPSDK) +#undef USE_WIN32_LDAP +#define HAVE_LDAP_URL_PARSE 1 +#else +#undef HAVE_LDAP_URL_PARSE +#define USE_WIN32_LDAP 1 +#endif + +#if defined(__WATCOMC__) && defined(USE_WIN32_LDAP) +#if __WATCOMC__ < 1280 +#define WINBERAPI __declspec(cdecl) +#define WINLDAPAPI __declspec(cdecl) +#endif +#endif + +#if defined(__POCC__) && defined(USE_WIN32_LDAP) +# define CURL_DISABLE_LDAP 1 +#endif + +/* Define to use the Windows crypto library. */ +#if !defined(USE_OPENSSL) && !defined(USE_NSS) +#define USE_WIN32_CRYPTO +#endif + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* Define cpu-machine-OS */ +#undef OS +#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */ +#define OS "i386-pc-win32" +#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */ +#define OS "x86_64-pc-win32" +#elif defined(_M_IA64) /* Itanium */ +#define OS "ia64-pc-win32" +#else +#define OS "unknown-pc-win32" +#endif + +/* Name of package */ +#define PACKAGE "curl" + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +#if defined(__POCC__) || (USE_IPV6) +# define ENABLE_IPV6 1 +#endif + +#endif /* HEADER_CURL_CONFIG_WIN32_H */ diff --git a/libcurl/src/lib/config-win32ce.h b/libcurl/src/lib/config-win32ce.h new file mode 100644 index 0000000..a723fd1 --- /dev/null +++ b/libcurl/src/lib/config-win32ce.h @@ -0,0 +1,448 @@ +#ifndef HEADER_CURL_CONFIG_WIN32CE_H +#define HEADER_CURL_CONFIG_WIN32CE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* lib/config-win32ce.h - Hand crafted config file for windows ce */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* HEADER FILES */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the header file. */ +/* #define HAVE_ARPA_INET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ASSERT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_CRYPTO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ERRNO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ERR_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_GETOPT_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you need the malloc.h header header file even with stdlib.h */ +#define NEED_MALLOC_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_NETDB_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_NETINET_IN_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SGTTY_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SSL_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_PROCESS_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKIO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TYPES_H 1 */ + +/* Define if you have the header file */ +#define HAVE_SYS_UTIME_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_TERMIO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_TERMIOS_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) +#define HAVE_UNISTD_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define if you have the header file. */ +#define HAVE_WINSOCK_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_WINSOCK2_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_WS2TCPIP_H 1 */ + +/* ---------------------------------------------------------------- */ +/* OTHER HEADER INFO */ +/* ---------------------------------------------------------------- */ + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +/* #define TIME_WITH_SYS_TIME 1 */ + +/* ---------------------------------------------------------------- */ +/* FUNCTIONS */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the closesocket function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #define HAVE_DOPRNT 1 */ + +/* Define if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the getpass function. */ +/* #define HAVE_GETPASS 1 */ + +/* Define if you have the getservbyname function. */ +#define HAVE_GETSERVBYNAME 1 + +/* Define if you have the gettimeofday function. */ +/* #define HAVE_GETTIMEOFDAY 1 */ + +/* Define if you have the inet_addr function. */ +#define HAVE_INET_ADDR 1 + +/* Define if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define if you have the perror function. */ +#define HAVE_PERROR 1 + +/* Define if you have the RAND_screen function when using SSL */ +#define HAVE_RAND_SCREEN 1 + +/* Define if you have the `RAND_status' function when using SSL. */ +#define HAVE_RAND_STATUS 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the setvbuf function. */ +#define HAVE_SETVBUF 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strcasecmp function. */ +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strdup function. */ +/* #define HAVE_STRDUP 1 */ + +/* Define if you have the strftime function. */ +/* #define HAVE_STRFTIME 1 */ + +/* Define if you have the stricmp function. */ +/* #define HAVE_STRICMP 1 */ + +/* Define if you have the strncasecmp function. */ +/* #define HAVE_STRNCASECMP 1 */ + +/* Define if you have the strnicmp function. */ +/* #define HAVE_STRNICMP 1 */ + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtoll function. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) +#define HAVE_STRTOLL 1 +#endif + +/* Define if you have the tcgetattr function. */ +/* #define HAVE_TCGETATTR 1 */ + +/* Define if you have the tcsetattr function. */ +/* #define HAVE_TCSETATTR 1 */ + +/* Define if you have the utime function */ +#define HAVE_UTIME 1 + +/* Define if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 DWORD + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* ---------------------------------------------------------------- */ +/* TYPEDEF REPLACEMENTS */ +/* ---------------------------------------------------------------- */ + +/* Define this if in_addr_t is not an available 'typedefed' type */ +#define in_addr_t unsigned long + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define ssize_t if it is not an available 'typedefed' type */ +#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__) +#elif defined(_WIN64) +#define ssize_t __int64 +#else +#define ssize_t int +#endif + +/* ---------------------------------------------------------------- */ +/* TYPE SIZES */ +/* ---------------------------------------------------------------- */ + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* The size of `long long', as computed by sizeof. */ +/* #define SIZEOF_LONG_LONG 8 */ + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#if defined(_WIN64) +# define SIZEOF_SIZE_T 8 +#else +# define SIZEOF_SIZE_T 4 +#endif + +/* ---------------------------------------------------------------- */ +/* STRUCT RELATED */ +/* ---------------------------------------------------------------- */ + +/* Define this if you have struct sockaddr_storage */ +/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */ + +/* Define this if you have struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define this if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* ---------------------------------------------------------------- */ +/* COMPILER SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Undef keyword 'const' if it does not work. */ +/* #undef const */ + +/* Define to avoid VS2005 complaining about portable C functions */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +/* VS2005 and later dafault size for time_t is 64-bit, unless */ +/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# ifndef _USE_32BIT_TIME_T +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* LARGE FILE SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) +# define USE_WIN32_SMALL_FILES +#endif + +/* ---------------------------------------------------------------- */ +/* LDAP SUPPORT */ +/* ---------------------------------------------------------------- */ + +#define USE_WIN32_LDAP 1 +#undef HAVE_LDAP_URL_PARSE + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* Define cpu-machine-OS */ +#undef OS +#define OS "i386-pc-win32ce" + +/* Name of package */ +#define PACKAGE "curl" + +/* ---------------------------------------------------------------- */ +/* WinCE */ +/* ---------------------------------------------------------------- */ + +#ifndef UNICODE +# define UNICODE +#endif + +#ifndef _UNICODE +# define _UNICODE +#endif + +#define CURL_DISABLE_FILE 1 +#define CURL_DISABLE_TELNET 1 +#define CURL_DISABLE_LDAP 1 + +#define ENOSPC 1 +#define ENOMEM 2 +#define EAGAIN 3 + +extern int stat(const char *path, struct stat *buffer); + +#endif /* HEADER_CURL_CONFIG_WIN32CE_H */ diff --git a/libcurl/src/lib/config-winrt.h b/libcurl/src/lib/config-winrt.h new file mode 100644 index 0000000..8694d3d --- /dev/null +++ b/libcurl/src/lib/config-winrt.h @@ -0,0 +1,468 @@ +#ifndef HEADER_CURL_CONFIG_WIN32CE_H +#define HEADER_CURL_CONFIG_WIN32CE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* lib/config-win32ce.h - Hand crafted config file for windows ce */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* HEADER FILES */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the header file. */ +/* #define HAVE_ARPA_INET_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_CRYPTO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_ERR_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_GETOPT_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you need the malloc.h header header file even with stdlib.h */ +#define NEED_MALLOC_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_NETDB_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_NETINET_IN_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SGTTY_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SSL_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_PROCESS_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKIO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TYPES_H 1 */ + +/* Define if you have the header file */ +#define HAVE_SYS_UTIME_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_TERMIO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_TERMIOS_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) +#define HAVE_UNISTD_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_WINSOCK_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_WINSOCK2_H 1 + +/* Define if you have the header file. */ +#define HAVE_WS2TCPIP_H 1 + +/* ---------------------------------------------------------------- */ +/* OTHER HEADER INFO */ +/* ---------------------------------------------------------------- */ + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +/* #define TIME_WITH_SYS_TIME 1 */ + +/* ---------------------------------------------------------------- */ +/* FUNCTIONS */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the closesocket function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #define HAVE_DOPRNT 1 */ + +/* Define if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the getpass function. */ +/* #define HAVE_GETPASS 1 */ + +/* Define if you have the getservbyname function. */ +#define HAVE_GETSERVBYNAME 1 + +/* Define if you have the gettimeofday function. */ +/* #define HAVE_GETTIMEOFDAY 1 */ + +/* Define if you have the inet_addr function. */ +#define HAVE_INET_ADDR 1 + +/* Define if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define if you have the perror function. */ +#define HAVE_PERROR 1 + +/* Define if you have the RAND_screen function when using SSL */ +#define HAVE_RAND_SCREEN 1 + +/* Define if you have the `RAND_status' function when using SSL. */ +#define HAVE_RAND_STATUS 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the setvbuf function. */ +#define HAVE_SETVBUF 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strcasecmp function. */ +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strftime function. */ +/* #define HAVE_STRFTIME 1 */ + +/* Define if you have the stricmp function. */ +/* #define HAVE_STRICMP 1 */ + +/* Define if you have the strncasecmp function. */ +/* #define HAVE_STRNCASECMP 1 */ + +/* Define if you have the strnicmp function. */ +/* #define HAVE_STRNICMP 1 */ + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtoll function. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) +#define HAVE_STRTOLL 1 +#endif + +/* Define if you have the tcgetattr function. */ +/* #define HAVE_TCGETATTR 1 */ + +/* Define if you have the tcsetattr function. */ +/* #define HAVE_TCSETATTR 1 */ + +/* Define if you have the utime function */ +#define HAVE_UTIME 1 + +/* Define if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 DWORD + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* ---------------------------------------------------------------- */ +/* TYPEDEF REPLACEMENTS */ +/* ---------------------------------------------------------------- */ + +/* Define this if in_addr_t is not an available 'typedefed' type */ +#define in_addr_t unsigned long + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define ssize_t if it is not an available 'typedefed' type */ +#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__) +#elif defined(_WIN64) +#define ssize_t __int64 +#else +#define ssize_t int +#endif + +/* ---------------------------------------------------------------- */ +/* TYPE SIZES */ +/* ---------------------------------------------------------------- */ + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* The size of `long long', as computed by sizeof. */ +/* #define SIZEOF_LONG_LONG 8 */ + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#if defined(_WIN64) +# define SIZEOF_SIZE_T 8 +#else +# define SIZEOF_SIZE_T 4 +#endif + +/* ---------------------------------------------------------------- */ +/* STRUCT RELATED */ +/* ---------------------------------------------------------------- */ + +/* Define this if you have struct sockaddr_storage */ +/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */ + +/* Define this if you have struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define this if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +#define HAVE_STRUCT_POLLFD 1 + +/* ---------------------------------------------------------------- */ +/* COMPILER SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Undef keyword 'const' if it does not work. */ +/* #undef const */ + +/* Define to avoid VS2005 complaining about portable C functions */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +/* VS2005 and later dafault size for time_t is 64-bit, unless */ +/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# ifndef _USE_32BIT_TIME_T +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +#endif + +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 + +/* ---------------------------------------------------------------- */ +/* LARGE FILE SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) +# define USE_WIN32_SMALL_FILES +#endif + +/* ---------------------------------------------------------------- */ +/* DNS RESOLVER SPECIALTY */ +/* ---------------------------------------------------------------- */ + +/* + * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS. + */ + +/* Define to enable c-ares asynchronous DNS lookups. */ +/* #define USE_ARES 1 */ + +/* Default define to enable threaded asynchronous DNS lookups. */ +#if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \ + !defined(USE_THREADS_WIN32) +//# define USE_THREADS_WIN32 1 +#endif + +#if defined(USE_ARES) && defined(USE_THREADS_WIN32) +# error "Only one DNS lookup specialty may be defined at most" +#endif + +/* ---------------------------------------------------------------- */ +/* LDAP SUPPORT */ +/* ---------------------------------------------------------------- */ + +#define CURL_LDAP_WIN 1 +#undef HAVE_LDAP_URL_PARSE + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* Define cpu-machine-OS */ +#undef OS +#define OS "unknown-pc-winrt" + +/* Name of package */ +#define PACKAGE "curl" + +/* ---------------------------------------------------------------- */ +/* WinRT */ +/* ---------------------------------------------------------------- */ + +#ifndef UNICODE +# define UNICODE +#endif + +#ifndef _UNICODE +# define _UNICODE +#endif + +extern int stat(const char *path,struct stat *buffer ); + +#endif /* HEADER_CURL_CONFIG_WIN32CE_H */ diff --git a/libcurl/src/lib/conncache.c b/libcurl/src/lib/conncache.c new file mode 100644 index 0000000..e536782 --- /dev/null +++ b/libcurl/src/lib/conncache.c @@ -0,0 +1,289 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Linus Nielsen Feltzing, + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "multiif.h" +#include "sendf.h" +#include "rawstr.h" +#include "bundles.h" +#include "conncache.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +static void free_bundle_hash_entry(void *freethis) +{ + struct connectbundle *b = (struct connectbundle *) freethis; + + Curl_bundle_destroy(b); +} + +CURL_STATIC struct conncache *Curl_conncache_init(int size) +{ + struct conncache *connc; + + connc = calloc(1, sizeof(struct conncache)); + if(!connc) + return NULL; + + connc->hash = Curl_hash_alloc(size, Curl_hash_str, + Curl_str_key_compare, free_bundle_hash_entry); + + if(!connc->hash) { + free(connc); + return NULL; + } + + return connc; +} + +CURL_STATIC void Curl_conncache_destroy(struct conncache *connc) +{ + if(connc) { + Curl_hash_destroy(connc->hash); + connc->hash = NULL; + free(connc); + } +} + +CURL_STATIC struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + struct conncache *connc) +{ + struct connectbundle *bundle = NULL; + + char *hostname = conn->bits.proxy?conn->proxy.name:conn->host.name; + + if(connc) + bundle = Curl_hash_pick(connc->hash, hostname, strlen(hostname)+1); + + return bundle; +} + +static bool conncache_add_bundle(struct conncache *connc, + char *hostname, + struct connectbundle *bundle) +{ + void *p; + + p = Curl_hash_add(connc->hash, hostname, strlen(hostname)+1, bundle); + + return p?TRUE:FALSE; +} + +static void conncache_remove_bundle(struct conncache *connc, + struct connectbundle *bundle) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + + if(!connc) + return; + + Curl_hash_start_iterate(connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + if(he->ptr == bundle) { + /* The bundle is destroyed by the hash destructor function, + free_bundle_hash_entry() */ + Curl_hash_delete(connc->hash, he->key, he->key_len); + return; + } + + he = Curl_hash_next_element(&iter); + } +} + +CURL_STATIC CURLcode Curl_conncache_add_conn(struct conncache *connc, + struct connectdata *conn) +{ + CURLcode result; + struct connectbundle *bundle; + struct connectbundle *new_bundle = NULL; + struct SessionHandle *data = conn->data; + + bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache); + if(!bundle) { + char *hostname = conn->bits.proxy?conn->proxy.name:conn->host.name; + + result = Curl_bundle_create(data, &new_bundle); + if(result) + return result; + + if(!conncache_add_bundle(data->state.conn_cache, hostname, new_bundle)) { + Curl_bundle_destroy(new_bundle); + return CURLE_OUT_OF_MEMORY; + } + bundle = new_bundle; + } + + result = Curl_bundle_add_conn(bundle, conn); + if(result) { + if(new_bundle) + conncache_remove_bundle(data->state.conn_cache, new_bundle); + return result; + } + + conn->connection_id = connc->next_connection_id++; + connc->num_connections++; + + DEBUGF(infof(conn->data, "Added connection %ld. " + "The cache now contains %" CURL_FORMAT_CURL_OFF_TU " members\n", + conn->connection_id, (curl_off_t) connc->num_connections)); + + return CURLE_OK; +} + +CURL_STATIC void Curl_conncache_remove_conn(struct conncache *connc, + struct connectdata *conn) +{ + struct connectbundle *bundle = conn->bundle; + + /* The bundle pointer can be NULL, since this function can be called + due to a failed connection attempt, before being added to a bundle */ + if(bundle) { + Curl_bundle_remove_conn(bundle, conn); + if(bundle->num_connections == 0) { + conncache_remove_bundle(connc, bundle); + } + + if(connc) { + connc->num_connections--; + + DEBUGF(infof(conn->data, "The cache now contains %" + CURL_FORMAT_CURL_OFF_TU " members\n", + (curl_off_t) connc->num_connections)); + } + } +} + +/* This function iterates the entire connection cache and calls the + function func() with the connection pointer as the first argument + and the supplied 'param' argument as the other, + + Return 0 from func() to continue the loop, return 1 to abort it. + */ +CURL_STATIC void Curl_conncache_foreach(struct conncache *connc, + void *param, + int (*func)(struct connectdata *conn, void *param)) +{ + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + + if(!connc) + return; + + Curl_hash_start_iterate(connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectbundle *bundle; + + bundle = he->ptr; + he = Curl_hash_next_element(&iter); + + curr = bundle->conn_list->head; + while(curr) { + /* Yes, we need to update curr before calling func(), because func() + might decide to remove the connection */ + struct connectdata *conn = curr->ptr; + curr = curr->next; + + if(1 == func(conn, param)) + return; + } + } +} + +/* Return the first connection found in the cache. Used when closing all + connections */ +CURL_STATIC struct connectdata * +Curl_conncache_find_first_connection(struct conncache *connc) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + struct connectbundle *bundle; + + Curl_hash_start_iterate(connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct curl_llist_element *curr; + bundle = he->ptr; + + curr = bundle->conn_list->head; + if(curr) { + return curr->ptr; + } + + he = Curl_hash_next_element(&iter); + } + + return NULL; +} + + +#if 0 +/* Useful for debugging the connection cache */ +CURL_STATIC void Curl_conncache_print(struct conncache *connc) +{ + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + + if(!connc) + return; + + fprintf(stderr, "=Bundle cache=\n"); + + Curl_hash_start_iterate(connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectbundle *bundle; + struct connectdata *conn; + + bundle = he->ptr; + + fprintf(stderr, "%s -", he->key); + curr = bundle->conn_list->head; + while(curr) { + conn = curr->ptr; + + fprintf(stderr, " [%p %d]", (void *)conn, conn->inuse); + curr = curr->next; + } + fprintf(stderr, "\n"); + + he = Curl_hash_next_element(&iter); + } +} +#endif diff --git a/libcurl/src/lib/conncache.h b/libcurl/src/lib/conncache.h new file mode 100644 index 0000000..2ccdd00 --- /dev/null +++ b/libcurl/src/lib/conncache.h @@ -0,0 +1,57 @@ +#ifndef HEADER_CURL_CONNCACHE_H +#define HEADER_CURL_CONNCACHE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, + * + * 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. + * + ***************************************************************************/ + +struct conncache { + struct curl_hash *hash; + size_t num_connections; + long next_connection_id; + struct timeval last_cleanup; +}; + +CURL_STATIC struct conncache *Curl_conncache_init(int size); + +CURL_STATIC void Curl_conncache_destroy(struct conncache *connc); + +/* return the correct bundle, to a host or a proxy */ +CURL_STATIC struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + struct conncache *connc); + +CURL_STATIC CURLcode Curl_conncache_add_conn(struct conncache *connc, + struct connectdata *conn); + +CURL_STATIC void Curl_conncache_remove_conn(struct conncache *connc, + struct connectdata *conn); + +CURL_STATIC void Curl_conncache_foreach(struct conncache *connc, + void *param, + int (*func)(struct connectdata *conn, + void *param)); + +CURL_STATIC struct connectdata * +Curl_conncache_find_first_connection(struct conncache *connc); + +CURL_STATIC void Curl_conncache_print(struct conncache *connc); + +#endif /* HEADER_CURL_CONNCACHE_H */ diff --git a/libcurl/src/lib/connect.c b/libcurl/src/lib/connect.c new file mode 100644 index 0000000..eaaac4e --- /dev/null +++ b/libcurl/src/lib/connect.c @@ -0,0 +1,1377 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include /* may need it */ +#endif +#ifdef HAVE_SYS_UN_H +#include /* for sockaddr_un */ +#endif +#ifdef HAVE_NETINET_TCP_H +#include /* for TCP_NODELAY */ +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) +#include +#endif +#ifdef NETWARE +#undef in_addr_t +#define in_addr_t unsigned long +#endif +#ifdef __VMS +#include +#include +#endif + +#include "curl_printf.h" +#include "urldata.h" +#include "sendf.h" +#include "if2ip.h" +#include "strerror.h" +#include "connect.h" +#include "select.h" +#include "url.h" /* for Curl_safefree() */ +#include "multiif.h" +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "inet_ntop.h" +#include "inet_pton.h" +#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */ +#include "progress.h" +#include "warnless.h" +#include "conncache.h" +#include "multihandle.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef __SYMBIAN32__ +/* This isn't actually supported under Symbian OS */ +#undef SO_NOSIGPIPE +#endif + +static bool verifyconnect(curl_socket_t sockfd, int *error); + +#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H) +/* DragonFlyBSD and Windows use millisecond units */ +#define KEEPALIVE_FACTOR(x) (x *= 1000) +#else +#define KEEPALIVE_FACTOR(x) +#endif + +#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS) +#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) + +struct tcp_keepalive { + u_long onoff; + u_long keepalivetime; + u_long keepaliveinterval; +}; +#endif + +static void +tcpkeepalive(struct SessionHandle *data, + curl_socket_t sockfd) +{ + int optval = data->set.tcp_keepalive?1:0; + + /* only set IDLE and INTVL if setting KEEPALIVE is successful */ + if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); + } + else { +#if defined(SIO_KEEPALIVE_VALS) + struct tcp_keepalive vals; + DWORD dummy; + vals.onoff = 1; + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + vals.keepalivetime = optval; + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + vals.keepaliveinterval = optval; + if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals), + NULL, 0, &dummy, NULL, NULL) != 0) { + infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n", + (int)sockfd, WSAGetLastError()); + } +#else +#ifdef TCP_KEEPIDLE + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); + } +#endif +#ifdef TCP_KEEPINTVL + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); + } +#endif +#ifdef TCP_KEEPALIVE + /* Mac OS X style */ + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd); + } +#endif +#endif + } +} + +static CURLcode +singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, /* start connecting to this */ + curl_socket_t *sock); + +/* + * Curl_timeleft() returns the amount of milliseconds left allowed for the + * transfer/connection. If the value is negative, the timeout time has already + * elapsed. + * + * The start time is stored in progress.t_startsingle - as set with + * Curl_pgrsTime(..., TIMER_STARTSINGLE); + * + * If 'nowp' is non-NULL, it points to the current time. + * 'duringconnect' is FALSE if not during a connect, as then of course the + * connect timeout is not taken into account! + * + * @unittest: 1303 + */ +CURL_STATIC long Curl_timeleft(struct SessionHandle *data, + struct timeval *nowp, + bool duringconnect) +{ + int timeout_set = 0; + long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; + struct timeval now; + + /* if a timeout is set, use the most restrictive one */ + + if(data->set.timeout > 0) + timeout_set |= 1; + if(duringconnect && (data->set.connecttimeout > 0)) + timeout_set |= 2; + + switch (timeout_set) { + case 1: + timeout_ms = data->set.timeout; + break; + case 2: + timeout_ms = data->set.connecttimeout; + break; + case 3: + if(data->set.timeout < data->set.connecttimeout) + timeout_ms = data->set.timeout; + else + timeout_ms = data->set.connecttimeout; + break; + default: + /* use the default */ + if(!duringconnect) + /* if we're not during connect, there's no default timeout so if we're + at zero we better just return zero and not make it a negative number + by the math below */ + return 0; + break; + } + + if(!nowp) { + now = Curl_tvnow(); + nowp = &now; + } + + /* subtract elapsed time */ + if(duringconnect) + /* since this most recent connect started */ + timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle); + else + /* since the entire operation started */ + timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; + + return timeout_ms; +} + +static CURLcode bindlocal(struct connectdata *conn, + curl_socket_t sockfd, int af, unsigned int scope) +{ + struct SessionHandle *data = conn->data; + + struct Curl_sockaddr_storage sa; + struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ + curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ + struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; +#endif + + struct Curl_dns_entry *h=NULL; + unsigned short port = data->set.localport; /* use this port number, 0 for + "random" */ + /* how many port numbers to try to bind to, increasing one at a time */ + int portnum = data->set.localportrange; + const char *dev = data->set.str[STRING_DEVICE]; + int error; + + /************************************************************* + * Select device to bind socket to + *************************************************************/ + if(!dev && !port) + /* no local kind of binding was requested */ + return CURLE_OK; + + memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); + + if(dev && (strlen(dev)<255) ) { + char myhost[256] = ""; + int done = 0; /* -1 for error, 1 for address found */ + bool is_interface = FALSE; + bool is_host = FALSE; + static const char *if_prefix = "if!"; + static const char *host_prefix = "host!"; + + if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) { + dev += strlen(if_prefix); + is_interface = TRUE; + } + else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) { + dev += strlen(host_prefix); + is_host = TRUE; + } + + /* interface */ + if(!is_host) { + switch(Curl_if2ip(af, scope, conn->scope_id, dev, + myhost, sizeof(myhost))) { + case IF2IP_NOT_FOUND: + if(is_interface) { + /* Do not fall back to treating it as a host name */ + failf(data, "Couldn't bind to interface '%s'", dev); + return CURLE_INTERFACE_FAILED; + } + break; + case IF2IP_AF_NOT_SUPPORTED: + /* Signal the caller to try another address family if available */ + return CURLE_UNSUPPORTED_PROTOCOL; + case IF2IP_FOUND: + is_interface = TRUE; + /* + * We now have the numerical IP address in the 'myhost' buffer + */ + infof(data, "Local Interface %s is ip %s using address family %i\n", + dev, myhost, af); + done = 1; + +#ifdef SO_BINDTODEVICE + /* I am not sure any other OSs than Linux that provide this feature, + * and at the least I cannot test. --Ben + * + * This feature allows one to tightly bind the local socket to a + * particular interface. This will force even requests to other + * local interfaces to go out the external interface. + * + * + * Only bind to the interface when specified as interface, not just + * as a hostname or ip address. + */ + if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, + dev, (curl_socklen_t)strlen(dev)+1) != 0) { + error = SOCKERRNO; + infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;" + " will do regular bind\n", + dev, error, Curl_strerror(conn, error)); + /* This is typically "errno 1, error: Operation not permitted" if + you're not running as root or another suitable privileged + user */ + } +#endif + break; + } + } + if(!is_interface) { + /* + * This was not an interface, resolve the name as a host name + * or IP number + * + * Temporarily force name resolution to use only the address type + * of the connection. The resolve functions should really be changed + * to take a type parameter instead. + */ + long ipver = conn->ip_version; + int rc; + + if(af == AF_INET) + conn->ip_version = CURL_IPRESOLVE_V4; +#ifdef ENABLE_IPV6 + else if(af == AF_INET6) + conn->ip_version = CURL_IPRESOLVE_V6; +#endif + + rc = Curl_resolv(conn, dev, 0, &h); + if(rc == CURLRESOLV_PENDING) + (void)Curl_resolver_wait_resolv(conn, &h); + conn->ip_version = ipver; + + if(h) { + /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ + Curl_printable_address(h->addr, myhost, sizeof(myhost)); + infof(data, "Name '%s' family %i resolved to '%s' family %i\n", + dev, af, myhost, h->addr->ai_family); + Curl_resolv_unlock(data, h); + done = 1; + } + else { + /* + * provided dev was no interface (or interfaces are not supported + * e.g. solaris) no ip address and no domain we fail here + */ + done = -1; + } + } + + if(done > 0) { +#ifdef ENABLE_IPV6 + /* IPv6 address */ + if(af == AF_INET6) { +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + char *scope_ptr = strchr(myhost, '%'); + if(scope_ptr) + *(scope_ptr++) = 0; +#endif + if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + if(scope_ptr) + /* The "myhost" string either comes from Curl_if2ip or from + Curl_printable_address. The latter returns only numeric scope + IDs and the former returns none at all. So the scope ID, if + present, is known to be numeric */ + si6->sin6_scope_id = atoi(scope_ptr); +#endif + } + sizeof_sa = sizeof(struct sockaddr_in6); + } + else +#endif + /* IPv4 address */ + if((af == AF_INET) && + (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in); + } + } + + if(done < 1) { + failf(data, "Couldn't bind to '%s'", dev); + return CURLE_INTERFACE_FAILED; + } + } + else { + /* no device was given, prepare sa to match af's needs */ +#ifdef ENABLE_IPV6 + if(af == AF_INET6) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in6); + } + else +#endif + if(af == AF_INET) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in); + } + } + + for(;;) { + if(bind(sockfd, sock, sizeof_sa) >= 0) { + /* we succeeded to bind */ + struct Curl_sockaddr_storage add; + curl_socklen_t size = sizeof(add); + memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); + if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { + data->state.os_errno = error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return CURLE_INTERFACE_FAILED; + } + infof(data, "Local port: %hu\n", port); + conn->bits.bound = TRUE; + return CURLE_OK; + } + + if(--portnum > 0) { + infof(data, "Bind to local port %hu failed, trying next\n", port); + port++; /* try next port */ + /* We re-use/clobber the port variable here below */ + if(sock->sa_family == AF_INET) + si4->sin_port = ntohs(port); +#ifdef ENABLE_IPV6 + else + si6->sin6_port = ntohs(port); +#endif + } + else + break; + } + + data->state.os_errno = error = SOCKERRNO; + failf(data, "bind failed with errno %d: %s", + error, Curl_strerror(conn, error)); + + return CURLE_INTERFACE_FAILED; +} + +/* + * verifyconnect() returns TRUE if the connect really has happened. + */ +static bool verifyconnect(curl_socket_t sockfd, int *error) +{ + bool rc = TRUE; +#ifdef SO_ERROR + int err = 0; + curl_socklen_t errSize = sizeof(err); + +#ifdef WIN32 + /* + * In October 2003 we effectively nullified this function on Windows due to + * problems with it using all CPU in multi-threaded cases. + * + * In May 2004, we bring it back to offer more info back on connect failures. + * Gisle Vanem could reproduce the former problems with this function, but + * could avoid them by adding this SleepEx() call below: + * + * "I don't have Rational Quantify, but the hint from his post was + * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe + * just Sleep(0) would be enough?) would release whatever + * mutex/critical-section the ntdll call is waiting on. + * + * Someone got to verify this on Win-NT 4.0, 2000." + */ + +#ifdef _WIN32_WCE + Sleep(0); +#elif !defined(CURL_WINRT) + SleepEx(0, FALSE); +#endif + +#endif + + if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) + err = SOCKERRNO; +#ifdef _WIN32_WCE + /* Old WinCE versions don't support SO_ERROR */ + if(WSAENOPROTOOPT == err) { + SET_SOCKERRNO(0); + err = 0; + } +#endif +#ifdef __minix + /* Minix 3.1.x doesn't support getsockopt on UDP sockets */ + if(EBADIOCTL == err) { + SET_SOCKERRNO(0); + err = 0; + } +#endif + if((0 == err) || (EISCONN == err)) + /* we are connected, awesome! */ + rc = TRUE; + else + /* This wasn't a successful connect */ + rc = FALSE; + if(error) + *error = err; +#else + (void)sockfd; + if(error) + *error = SOCKERRNO; +#endif + return rc; +} + +/* Used within the multi interface. Try next IP address, return TRUE if no + more address exists or error */ +static CURLcode trynextip(struct connectdata *conn, + int sockindex, + int tempindex) +{ + const int other = tempindex ^ 1; + CURLcode result = CURLE_COULDNT_CONNECT; + + /* First clean up after the failed socket. + Don't close it yet to ensure that the next IP's socket gets a different + file descriptor, which can prevent bugs when the curl_multi_socket_action + interface is used with certain select() replacements such as kqueue. */ + curl_socket_t fd_to_close = conn->tempsock[tempindex]; + conn->tempsock[tempindex] = CURL_SOCKET_BAD; + + if(sockindex == FIRSTSOCKET) { + Curl_addrinfo *ai = NULL; + int family = AF_UNSPEC; + + if(conn->tempaddr[tempindex]) { + /* find next address in the same protocol family */ + family = conn->tempaddr[tempindex]->ai_family; + ai = conn->tempaddr[tempindex]->ai_next; + } +#ifdef ENABLE_IPV6 + else if(conn->tempaddr[0]) { + /* happy eyeballs - try the other protocol family */ + int firstfamily = conn->tempaddr[0]->ai_family; + family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET; + ai = conn->tempaddr[0]->ai_next; + } +#endif + + while(ai) { + if(conn->tempaddr[other]) { + /* we can safely skip addresses of the other protocol family */ + while(ai && ai->ai_family != family) + ai = ai->ai_next; + } + + if(ai) { + result = singleipconnect(conn, ai, &conn->tempsock[tempindex]); + if(result == CURLE_COULDNT_CONNECT) { + ai = ai->ai_next; + continue; + } + + conn->tempaddr[tempindex] = ai; + } + break; + } + } + + if(fd_to_close != CURL_SOCKET_BAD) + Curl_closesocket(conn, fd_to_close); + + return result; +} + +/* Copies connection info into the session handle to make it available + when the session handle is no longer associated with a connection. */ +CURL_STATIC void Curl_persistconninfo(struct connectdata *conn) +{ + memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); + memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); + conn->data->info.conn_primary_port = conn->primary_port; + conn->data->info.conn_local_port = conn->local_port; +} + +/* retrieves ip address and port from a sockaddr structure */ +static bool getaddressinfo(struct sockaddr* sa, char* addr, + long* port) +{ + unsigned short us_port; + struct sockaddr_in* si = NULL; +#ifdef ENABLE_IPV6 + struct sockaddr_in6* si6 = NULL; +#endif +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + struct sockaddr_un* su = NULL; +#endif + + switch (sa->sa_family) { + case AF_INET: + si = (struct sockaddr_in*) sa; + if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, + addr, MAX_IPADR_LEN)) { + us_port = ntohs(si->sin_port); + *port = us_port; + return TRUE; + } + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + si6 = (struct sockaddr_in6*)sa; + if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, + addr, MAX_IPADR_LEN)) { + us_port = ntohs(si6->sin6_port); + *port = us_port; + return TRUE; + } + break; +#endif +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + case AF_UNIX: + su = (struct sockaddr_un*)sa; + snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); + *port = 0; + return TRUE; +#endif + default: + break; + } + + addr[0] = '\0'; + *port = 0; + + return FALSE; +} + +/* retrieves the start/end point information of a socket of an established + connection */ +CURL_STATIC void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) +{ + curl_socklen_t len; + struct Curl_sockaddr_storage ssrem; + struct Curl_sockaddr_storage ssloc; + struct SessionHandle *data = conn->data; + + if(conn->socktype == SOCK_DGRAM) + /* there's no connection! */ + return; + + if(!conn->bits.reuse) { + int error; + + len = sizeof(struct Curl_sockaddr_storage); + if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { + error = SOCKERRNO; + failf(data, "getpeername() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } + + len = sizeof(struct Curl_sockaddr_storage); + memset(&ssloc, 0, sizeof(ssloc)); + if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { + error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } + + if(!getaddressinfo((struct sockaddr*)&ssrem, + conn->primary_ip, &conn->primary_port)) { + error = ERRNO; + failf(data, "ssrem inet_ntop() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } + memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); + + if(!getaddressinfo((struct sockaddr*)&ssloc, + conn->local_ip, &conn->local_port)) { + error = ERRNO; + failf(data, "ssloc inet_ntop() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } + + } + + /* persist connection info in session handle */ + Curl_persistconninfo(conn); +} + +/* + * Curl_is_connected() checks if the socket has connected. + */ + +CURL_STATIC CURLcode Curl_is_connected(struct connectdata *conn, + int sockindex, + bool *connected) +{ + struct SessionHandle *data = conn->data; + CURLcode result = CURLE_OK; + long allow; + int error = 0; + struct timeval now; + int rc; + int i; + + DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); + + *connected = FALSE; /* a very negative world view is best */ + + if(conn->bits.tcpconnect[sockindex]) { + /* we are connected already! */ + *connected = TRUE; + return CURLE_OK; + } + + now = Curl_tvnow(); + + /* figure out how long time we have left to connect */ + allow = Curl_timeleft(data, &now, TRUE); + + if(allow < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + for(i=0; i<2; i++) { + const int other = i ^ 1; + if(conn->tempsock[i] == CURL_SOCKET_BAD) + continue; + +#ifdef mpeix + /* Call this function once now, and ignore the results. We do this to + "clear" the error state on the socket so that we can later read it + reliably. This is reported necessary on the MPE/iX operating system. */ + (void)verifyconnect(conn->tempsock[i], NULL); +#endif + + /* check socket for connect */ + rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0); + + if(rc == 0) { /* no connection yet */ + if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) { + infof(data, "After %ldms connect time, move on!\n", + conn->timeoutms_per_addr); + error = ETIMEDOUT; + } + + /* should we try another protocol family? */ + if(i == 0 && conn->tempaddr[1] == NULL && + curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) { + trynextip(conn, sockindex, 1); + } + } + else if(rc == CURL_CSELECT_OUT) { + if(verifyconnect(conn->tempsock[i], &error)) { + /* we are connected with TCP, awesome! */ + + /* use this socket from now on */ + conn->sock[sockindex] = conn->tempsock[i]; + conn->ip_addr = conn->tempaddr[i]; + conn->tempsock[i] = CURL_SOCKET_BAD; + + /* close the other socket, if open */ + if(conn->tempsock[other] != CURL_SOCKET_BAD) { + Curl_closesocket(conn, conn->tempsock[other]); + conn->tempsock[other] = CURL_SOCKET_BAD; + } + + /* see if we need to do any proxy magic first once we connected */ + result = Curl_connected_proxy(conn, sockindex); + if(result) + return result; + + conn->bits.tcpconnect[sockindex] = TRUE; + + *connected = TRUE; + if(sockindex == FIRSTSOCKET) + Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ + Curl_updateconninfo(conn, conn->sock[sockindex]); + Curl_verboseconnect(conn); + + return CURLE_OK; + } + else + infof(data, "Connection failed\n"); + } + else if(rc & CURL_CSELECT_ERR) + (void)verifyconnect(conn->tempsock[i], &error); + + /* + * The connection failed here, we should attempt to connect to the "next + * address" for the given host. But first remember the latest error. + */ + if(error) { + data->state.os_errno = error; + SET_SOCKERRNO(error); + if(conn->tempaddr[i]) { + CURLcode status; + char ipaddress[MAX_IPADR_LEN]; + Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN); + infof(data, "connect to %s port %ld failed: %s\n", + ipaddress, conn->port, Curl_strerror(conn, error)); + + conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ? + allow : allow / 2; + + status = trynextip(conn, sockindex, i); + if(status != CURLE_COULDNT_CONNECT + || conn->tempsock[other] == CURL_SOCKET_BAD) + /* the last attempt failed and no other sockets remain open */ + result = status; + } + } + } + + if(result) { + /* no more addresses to try */ + + /* if the first address family runs out of addresses to try before + the happy eyeball timeout, go ahead and try the next family now */ + if(conn->tempaddr[1] == NULL) { + result = trynextip(conn, sockindex, 1); + if(!result) + return result; + } + + failf(data, "Failed to connect to %s port %ld: %s", + conn->bits.proxy?conn->proxy.name:conn->host.name, + conn->port, Curl_strerror(conn, error)); + } + + return result; +} + +static void tcpnodelay(struct connectdata *conn, + curl_socket_t sockfd) +{ +#ifdef TCP_NODELAY + struct SessionHandle *data= conn->data; + curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay; + int level = IPPROTO_TCP; + +#if 0 + /* The use of getprotobyname() is disabled since it isn't thread-safe on + numerous systems. On these getprotobyname_r() should be used instead, but + that exists in at least one 4 arg version and one 5 arg version, and + since the proto number rarely changes anyway we now just use the hard + coded number. The "proper" fix would need a configure check for the + correct function much in the same style the gethostbyname_r versions are + detected. */ + struct protoent *pe = getprotobyname("tcp"); + if(pe) + level = pe->p_proto; +#endif + + if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, + sizeof(onoff)) < 0) + infof(data, "Could not set TCP_NODELAY: %s\n", + Curl_strerror(conn, SOCKERRNO)); + else + infof(data, "TCP_NODELAY set\n"); +#else + (void)conn; + (void)sockfd; +#endif +} + +#ifdef SO_NOSIGPIPE +/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when + sending data to a dead peer (instead of relying on the 4th argument to send + being MSG_NOSIGNAL). Possibly also existing and in use on other BSD + systems? */ +static void nosigpipe(struct connectdata *conn, + curl_socket_t sockfd) +{ + struct SessionHandle *data= conn->data; + int onoff = 1; + if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, + sizeof(onoff)) < 0) + infof(data, "Could not set SO_NOSIGPIPE: %s\n", + Curl_strerror(conn, SOCKERRNO)); +} +#else +#define nosigpipe(x,y) Curl_nop_stmt +#endif + +#ifdef USE_WINSOCK +/* When you run a program that uses the Windows Sockets API, you may + experience slow performance when you copy data to a TCP server. + + http://support.microsoft.com/kb/823764 + + Work-around: Make the Socket Send Buffer Size Larger Than the Program Send + Buffer Size + + The problem described in this knowledge-base is applied only to pre-Vista + Windows. Following function trying to detect OS version and skips + SO_SNDBUF adjustment for Windows Vista and above. +*/ +#define DETECT_OS_NONE 0 +#define DETECT_OS_PREVISTA 1 +#define DETECT_OS_VISTA_OR_LATER 2 + +CURL_STATIC void Curl_sndbufset(curl_socket_t sockfd) +{ + int val = CURL_MAX_WRITE_SIZE + 32; + int curval = 0; + int curlen = sizeof(curval); + DWORD majorVersion = 6; + + static int detectOsState = DETECT_OS_NONE; + + if(detectOsState == DETECT_OS_NONE) { +#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \ + (_WIN32_WINNT < _WIN32_WINNT_WIN2K) + OSVERSIONINFO osver; + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + + detectOsState = DETECT_OS_PREVISTA; + if(GetVersionEx(&osver)) { + if(osver.dwMajorVersion >= majorVersion) + detectOsState = DETECT_OS_VISTA_OR_LATER; + } +#elif defined(CURL_WINRT) + detectOsState = DETECT_OS_VISTA_OR_LATER; +#else + ULONGLONG majorVersionMask; + OSVERSIONINFOEX osver; + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + osver.dwMajorVersion = majorVersion; + majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION, + VER_GREATER_EQUAL); + + if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask)) + detectOsState = DETECT_OS_VISTA_OR_LATER; + else + detectOsState = DETECT_OS_PREVISTA; +#endif + } + + if(detectOsState == DETECT_OS_VISTA_OR_LATER) + return; + + if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) + if(curval > val) + return; + + setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); +} +#endif + +/* + * singleipconnect() + * + * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to + * CURL_SOCKET_BAD. Other errors will however return proper errors. + * + * singleipconnect() connects to the given IP only, and it may return without + * having connected. + */ +static CURLcode singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, + curl_socket_t *sockp) +{ + struct Curl_sockaddr_ex addr; + int rc; + int error = 0; + bool isconnected = FALSE; + struct SessionHandle *data = conn->data; + curl_socket_t sockfd; + CURLcode result; + char ipaddress[MAX_IPADR_LEN]; + long port; + bool is_tcp; + + *sockp = CURL_SOCKET_BAD; + + result = Curl_socket(conn, ai, &addr, &sockfd); + if(result) + /* Failed to create the socket, but still return OK since we signal the + lack of socket as well. This allows the parent function to keep looping + over alternative addresses/socket families etc. */ + return CURLE_OK; + + /* store remote address and port used in this connection attempt */ + if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, + ipaddress, &port)) { + /* malformed address or bug in inet_ntop, try next address */ + error = ERRNO; + failf(data, "sa_addr inet_ntop() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + Curl_closesocket(conn, sockfd); + return CURLE_OK; + } + infof(data, " Trying %s...\n", ipaddress); + +#ifdef ENABLE_IPV6 + is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) && + addr.socktype == SOCK_STREAM; +#else + is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM; +#endif + if(is_tcp && data->set.tcp_nodelay) + tcpnodelay(conn, sockfd); + + nosigpipe(conn, sockfd); + + Curl_sndbufset(sockfd); + + if(is_tcp && data->set.tcp_keepalive) + tcpkeepalive(data, sockfd); + + if(data->set.fsockopt) { + /* activate callback for setting socket options */ + error = data->set.fsockopt(data->set.sockopt_client, + sockfd, + CURLSOCKTYPE_IPCXN); + + if(error == CURL_SOCKOPT_ALREADY_CONNECTED) + isconnected = TRUE; + else if(error) { + Curl_closesocket(conn, sockfd); /* close the socket and bail out */ + return CURLE_ABORTED_BY_CALLBACK; + } + } + + /* possibly bind the local end to an IP, interface or port */ + if(addr.family == AF_INET +#ifdef ENABLE_IPV6 + || addr.family == AF_INET6 +#endif + ) { + result = bindlocal(conn, sockfd, addr.family, + Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr)); + if(result) { + Curl_closesocket(conn, sockfd); /* close socket and bail out */ + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + /* The address family is not supported on this interface. + We can continue trying addresses */ + return CURLE_COULDNT_CONNECT; + } + return result; + } + } + + /* set socket non-blocking */ + (void)curlx_nonblock(sockfd, TRUE); + + conn->connecttime = Curl_tvnow(); + if(conn->num_addr > 1) + Curl_expire_latest(data, conn->timeoutms_per_addr); + + /* Connect TCP sockets, bind UDP */ + if(!isconnected && (conn->socktype == SOCK_STREAM)) { + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + if(-1 == rc) + error = SOCKERRNO; + } + else { + *sockp = sockfd; + return CURLE_OK; + } + +#ifdef ENABLE_IPV6 + conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE; +#endif + + if(-1 == rc) { + switch(error) { + case EINPROGRESS: + case EWOULDBLOCK: +#if defined(EAGAIN) +#if (EAGAIN) != (EWOULDBLOCK) + /* On some platforms EAGAIN and EWOULDBLOCK are the + * same value, and on others they are different, hence + * the odd #if + */ + case EAGAIN: +#endif +#endif + result = CURLE_OK; + break; + + default: + /* unknown error, fallthrough and try another address! */ + infof(data, "Immediate connect fail for %s: %s\n", + ipaddress, Curl_strerror(conn, error)); + data->state.os_errno = error; + + /* connect failed */ + Curl_closesocket(conn, sockfd); + result = CURLE_COULDNT_CONNECT; + } + } + + if(!result) + *sockp = sockfd; + + return result; +} + +/* + * TCP connect to the given host with timeout, proxy or remote doesn't matter. + * There might be more than one IP address to try out. Fill in the passed + * pointer with the connected socket. + */ + +CURL_STATIC CURLcode Curl_connecthost(struct connectdata *conn, /* context */ + const struct Curl_dns_entry *remotehost) +{ + struct SessionHandle *data = conn->data; + struct timeval before = Curl_tvnow(); + CURLcode result = CURLE_COULDNT_CONNECT; + + long timeout_ms = Curl_timeleft(data, &before, TRUE); + + if(timeout_ms < 0) { + /* a precaution, no need to continue if time already is up */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + conn->num_addr = Curl_num_addresses(remotehost->addr); + conn->tempaddr[0] = remotehost->addr; + conn->tempaddr[1] = NULL; + conn->tempsock[0] = CURL_SOCKET_BAD; + conn->tempsock[1] = CURL_SOCKET_BAD; + Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT); + + /* Max time for the next connection attempt */ + conn->timeoutms_per_addr = + conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2; + + /* start connecting to first IP */ + while(conn->tempaddr[0]) { + result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0])); + if(!result) + break; + conn->tempaddr[0] = conn->tempaddr[0]->ai_next; + } + + if(conn->tempsock[0] == CURL_SOCKET_BAD) + return result; + + data->info.numconnects++; /* to track the number of connections made */ + + return CURLE_OK; +} + +struct connfind { + struct connectdata *tofind; + bool found; +}; + +static int conn_is_conn(struct connectdata *conn, void *param) +{ + struct connfind *f = (struct connfind *)param; + if(conn == f->tofind) { + f->found = TRUE; + return 1; + } + return 0; +} + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given SessionHandle. + * + * The returned socket will be CURL_SOCKET_BAD in case of failure! + */ +CURL_STATIC curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, + struct connectdata **connp) +{ + curl_socket_t sockfd; + + DEBUGASSERT(data); + + /* this works for an easy handle: + * - that has been used for curl_easy_perform() + * - that is associated with a multi handle, and whose connection + * was detached with CURLOPT_CONNECT_ONLY + */ + if(data->state.lastconnect && (data->multi_easy || data->multi)) { + struct connectdata *c = data->state.lastconnect; + struct connfind find; + find.tofind = data->state.lastconnect; + find.found = FALSE; + + Curl_conncache_foreach(data->multi_easy? + data->multi_easy->conn_cache: + data->multi->conn_cache, &find, conn_is_conn); + + if(!find.found) { + data->state.lastconnect = NULL; + return CURL_SOCKET_BAD; + } + + if(connp) + /* only store this if the caller cares for it */ + *connp = c; + sockfd = c->sock[FIRSTSOCKET]; + /* we have a socket connected, let's determine if the server shut down */ + /* determine if ssl */ + if(c->ssl[FIRSTSOCKET].use) { + /* use the SSL context */ + if(!Curl_ssl_check_cxn(c)) + return CURL_SOCKET_BAD; /* FIN received */ + } +/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ +#ifdef MSG_PEEK + else { + /* use the socket */ + char buf; + if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { + return CURL_SOCKET_BAD; /* FIN received */ + } + } +#endif + } + else + return CURL_SOCKET_BAD; + + return sockfd; +} + +/* + * Close a socket. + * + * 'conn' can be NULL, beware! + */ +CURL_STATIC int Curl_closesocket(struct connectdata *conn, + curl_socket_t sock) +{ + if(conn && conn->fclosesocket) { + if((sock == conn->sock[SECONDARYSOCKET]) && + conn->sock_accepted[SECONDARYSOCKET]) + /* if this socket matches the second socket, and that was created with + accept, then we MUST NOT call the callback but clear the accepted + status */ + conn->sock_accepted[SECONDARYSOCKET] = FALSE; + else { + Curl_multi_closed(conn, sock); + return conn->fclosesocket(conn->closesocket_client, sock); + } + } + + if(conn) + /* tell the multi-socket code about this */ + Curl_multi_closed(conn, sock); + + sclose(sock); + + return 0; +} + +/* + * Create a socket based on info from 'conn' and 'ai'. + * + * 'addr' should be a pointer to the correct struct to get data back, or NULL. + * 'sockfd' must be a pointer to a socket descriptor. + * + * If the open socket callback is set, used that! + * + */ +CURL_STATIC CURLcode Curl_socket(struct connectdata *conn, + const Curl_addrinfo *ai, + struct Curl_sockaddr_ex *addr, + curl_socket_t *sockfd) +{ + struct SessionHandle *data = conn->data; + struct Curl_sockaddr_ex dummy; + + if(!addr) + /* if the caller doesn't want info back, use a local temp copy */ + addr = &dummy; + + /* + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold + * any protocol-specific address structures. The variable declared here + * will be used to pass / receive data to/from the fopensocket callback + * if this has been set, before that, it is initialized from parameters. + */ + + addr->family = ai->ai_family; + addr->socktype = conn->socktype; + addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; + addr->addrlen = ai->ai_addrlen; + + if(addr->addrlen > sizeof(struct Curl_sockaddr_storage)) + addr->addrlen = sizeof(struct Curl_sockaddr_storage); + memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen); + + if(data->set.fopensocket) + /* + * If the opensocket callback is set, all the destination address + * information is passed to the callback. Depending on this information the + * callback may opt to abort the connection, this is indicated returning + * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When + * the callback returns a valid socket the destination address information + * might have been changed and this 'new' address will actually be used + * here to connect. + */ + *sockfd = data->set.fopensocket(data->set.opensocket_client, + CURLSOCKTYPE_IPCXN, + (struct curl_sockaddr *)addr); + else + /* opensocket callback not set, so simply create the socket now */ + *sockfd = socket(addr->family, addr->socktype, addr->protocol); + + if(*sockfd == CURL_SOCKET_BAD) + /* no socket, no connection */ + return CURLE_COULDNT_CONNECT; + +#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) + if(conn->scope_id && (addr->family == AF_INET6)) { + struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr; + sa6->sin6_scope_id = conn->scope_id; + } +#endif + + return CURLE_OK; + +} + +#ifdef CURLDEBUG +/* + * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It + * MUST be called with the connclose() or connkeep() macros with a stated + * reason. The reason is only shown in debug builds but helps to figure out + * decision paths when connections are or aren't re-used as expected. + */ +CURL_STATIC void Curl_conncontrol(struct connectdata *conn, bool closeit, + const char *reason) +{ +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) reason; +#endif + if(closeit != conn->bits.close) { + infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive", + reason); + + conn->bits.close = closeit; /* the only place in the source code that + should assign this bit */ + } +} +#endif diff --git a/libcurl/src/lib/connect.h b/libcurl/src/lib/connect.h new file mode 100644 index 0000000..f18ed55 --- /dev/null +++ b/libcurl/src/lib/connect.h @@ -0,0 +1,122 @@ +#ifndef HEADER_CURL_CONNECT_H +#define HEADER_CURL_CONNECT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */ +#include "sockaddr.h" + +CURL_STATIC CURLcode Curl_is_connected(struct connectdata *conn, + int sockindex, + bool *connected); + +CURL_STATIC CURLcode Curl_connecthost(struct connectdata *conn, + const struct Curl_dns_entry *host); + +/* generic function that returns how much time there's left to run, according + to the timeouts set */ +CURL_STATIC long Curl_timeleft(struct SessionHandle *data, + struct timeval *nowp, + bool duringconnect); + +#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ +#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between + IPv4/IPv6 connection attempts */ + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given SessionHandle. + * + * The returned socket will be CURL_SOCKET_BAD in case of failure! + */ +CURL_STATIC curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, + struct connectdata **connp); + +#ifdef USE_WINSOCK +/* When you run a program that uses the Windows Sockets API, you may + experience slow performance when you copy data to a TCP server. + + http://support.microsoft.com/kb/823764 + + Work-around: Make the Socket Send Buffer Size Larger Than the Program Send + Buffer Size + +*/ +CURL_STATIC void Curl_sndbufset(curl_socket_t sockfd); +#else +#define Curl_sndbufset(y) Curl_nop_stmt +#endif + +CURL_STATIC void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); +CURL_STATIC void Curl_persistconninfo(struct connectdata *conn); +CURL_STATIC int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); + +/* + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold any + * protocol-specific address structures. The variable declared here will be + * used to pass / receive data to/from the fopensocket callback if this has + * been set, before that, it is initialized from parameters. + */ +struct Curl_sockaddr_ex { + int family; + int socktype; + int protocol; + unsigned int addrlen; + union { + struct sockaddr addr; + struct Curl_sockaddr_storage buff; + } _sa_ex_u; +}; +#define sa_addr _sa_ex_u.addr + +/* + * Create a socket based on info from 'conn' and 'ai'. + * + * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open + * socket callback is set, used that! + * + */ +CURL_STATIC CURLcode Curl_socket(struct connectdata *conn, + const Curl_addrinfo *ai, + struct Curl_sockaddr_ex *addr, + curl_socket_t *sockfd); + +#ifdef CURLDEBUG +/* + * Curl_connclose() sets the bit.close bit to TRUE with an explanation. + * Nothing else. + */ +CURL_STATIC void Curl_conncontrol(struct connectdata *conn, + bool closeit, + const char *reason); +#define connclose(x,y) Curl_conncontrol(x,TRUE, y) +#define connkeep(x,y) Curl_conncontrol(x, FALSE, y) +#else /* if !CURLDEBUG */ + +#define connclose(x,y) (x)->bits.close = TRUE +#define connkeep(x,y) (x)->bits.close = FALSE + +#endif + +#endif /* HEADER_CURL_CONNECT_H */ diff --git a/libcurl/src/lib/content_encoding.c b/libcurl/src/lib/content_encoding.c new file mode 100644 index 0000000..0da02c8 --- /dev/null +++ b/libcurl/src/lib/content_encoding.c @@ -0,0 +1,435 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_LIBZ + +#include "urldata.h" +#include +#include "sendf.h" +#include "content_encoding.h" +#include "curl_memory.h" + +#include "memdebug.h" + +/* Comment this out if zlib is always going to be at least ver. 1.2.0.4 + (doing so will reduce code size slightly). */ +#define OLD_ZLIB_SUPPORT 1 + +#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */ + +#define GZIP_MAGIC_0 0x1f +#define GZIP_MAGIC_1 0x8b + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +static voidpf +zalloc_cb(voidpf opaque, unsigned int items, unsigned int size) +{ + (void) opaque; + /* not a typo, keep it calloc() */ + return (voidpf) calloc(items, size); +} + +static void +zfree_cb(voidpf opaque, voidpf ptr) +{ + (void) opaque; + free(ptr); +} + +static CURLcode +process_zlib_error(struct connectdata *conn, z_stream *z) +{ + struct SessionHandle *data = conn->data; + if(z->msg) + failf (data, "Error while processing content unencoding: %s", + z->msg); + else + failf (data, "Error while processing content unencoding: " + "Unknown failure within decompression software."); + + return CURLE_BAD_CONTENT_ENCODING; +} + +static CURLcode +exit_zlib(z_stream *z, zlibInitState *zlib_init, CURLcode result) +{ + inflateEnd(z); + *zlib_init = ZLIB_UNINIT; + return result; +} + +static CURLcode +inflate_stream(struct connectdata *conn, + struct SingleRequest *k) +{ + int allow_restart = 1; + z_stream *z = &k->z; /* zlib state structure */ + uInt nread = z->avail_in; + Bytef *orig_in = z->next_in; + int status; /* zlib status */ + CURLcode result = CURLE_OK; /* Curl_client_write status */ + char *decomp; /* Put the decompressed data here. */ + + /* Dynamically allocate a buffer for decompression because it's uncommonly + large to hold on the stack */ + decomp = malloc(DSIZ); + if(decomp == NULL) { + return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); + } + + /* because the buffer size is fixed, iteratively decompress and transfer to + the client via client_write. */ + for(;;) { + /* (re)set buffer for decompressed output for every iteration */ + z->next_out = (Bytef *)decomp; + z->avail_out = DSIZ; + + status = inflate(z, Z_SYNC_FLUSH); + if(status == Z_OK || status == Z_STREAM_END) { + allow_restart = 0; + if((DSIZ - z->avail_out) && (!k->ignorebody)) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp, + DSIZ - z->avail_out); + /* if !CURLE_OK, clean up, return */ + if(result) { + free(decomp); + return exit_zlib(z, &k->zlib_init, result); + } + } + + /* Done? clean up, return */ + if(status == Z_STREAM_END) { + free(decomp); + if(inflateEnd(z) == Z_OK) + return exit_zlib(z, &k->zlib_init, result); + else + return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); + } + + /* Done with these bytes, exit */ + + /* status is always Z_OK at this point! */ + if(z->avail_in == 0) { + free(decomp); + return result; + } + } + else if(allow_restart && status == Z_DATA_ERROR) { + /* some servers seem to not generate zlib headers, so this is an attempt + to fix and continue anyway */ + + (void) inflateEnd(z); /* don't care about the return code */ + if(inflateInit2(z, -MAX_WBITS) != Z_OK) { + free(decomp); + return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); + } + z->next_in = orig_in; + z->avail_in = nread; + allow_restart = 0; + continue; + } + else { /* Error; exit loop, handle below */ + free(decomp); + return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); + } + } + /* Will never get here */ +} + +CURL_STATIC CURLcode +Curl_unencode_deflate_write(struct connectdata *conn, + struct SingleRequest *k, + ssize_t nread) +{ + z_stream *z = &k->z; /* zlib state structure */ + + /* Initialize zlib? */ + if(k->zlib_init == ZLIB_UNINIT) { + memset(z, 0, sizeof(z_stream)); + z->zalloc = (alloc_func)zalloc_cb; + z->zfree = (free_func)zfree_cb; + + if(inflateInit(z) != Z_OK) + return process_zlib_error(conn, z); + k->zlib_init = ZLIB_INIT; + } + + /* Set the compressed input when this function is called */ + z->next_in = (Bytef *)k->str; + z->avail_in = (uInt)nread; + + /* Now uncompress the data */ + return inflate_stream(conn, k); +} + +#ifdef OLD_ZLIB_SUPPORT +/* Skip over the gzip header */ +static enum { + GZIP_OK, + GZIP_BAD, + GZIP_UNDERFLOW +} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen) +{ + int method, flags; + const ssize_t totallen = len; + + /* The shortest header is 10 bytes */ + if(len < 10) + return GZIP_UNDERFLOW; + + if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1)) + return GZIP_BAD; + + method = data[2]; + flags = data[3]; + + if(method != Z_DEFLATED || (flags & RESERVED) != 0) { + /* Can't handle this compression method or unknown flag */ + return GZIP_BAD; + } + + /* Skip over time, xflags, OS code and all previous bytes */ + len -= 10; + data += 10; + + if(flags & EXTRA_FIELD) { + ssize_t extra_len; + + if(len < 2) + return GZIP_UNDERFLOW; + + extra_len = (data[1] << 8) | data[0]; + + if(len < (extra_len+2)) + return GZIP_UNDERFLOW; + + len -= (extra_len + 2); + data += (extra_len + 2); + } + + if(flags & ORIG_NAME) { + /* Skip over NUL-terminated file name */ + while(len && *data) { + --len; + ++data; + } + if(!len || *data) + return GZIP_UNDERFLOW; + + /* Skip over the NUL */ + --len; + ++data; + } + + if(flags & COMMENT) { + /* Skip over NUL-terminated comment */ + while(len && *data) { + --len; + ++data; + } + if(!len || *data) + return GZIP_UNDERFLOW; + + /* Skip over the NUL */ + --len; + } + + if(flags & HEAD_CRC) { + if(len < 2) + return GZIP_UNDERFLOW; + + len -= 2; + } + + *headerlen = totallen - len; + return GZIP_OK; +} +#endif + +CURL_STATIC CURLcode +Curl_unencode_gzip_write(struct connectdata *conn, + struct SingleRequest *k, + ssize_t nread) +{ + z_stream *z = &k->z; /* zlib state structure */ + + /* Initialize zlib? */ + if(k->zlib_init == ZLIB_UNINIT) { + memset(z, 0, sizeof(z_stream)); + z->zalloc = (alloc_func)zalloc_cb; + z->zfree = (free_func)zfree_cb; + + if(strcmp(zlibVersion(), "1.2.0.4") >= 0) { + /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ + if(inflateInit2(z, MAX_WBITS+32) != Z_OK) { + return process_zlib_error(conn, z); + } + k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ + } + else { + /* we must parse the gzip header ourselves */ + if(inflateInit2(z, -MAX_WBITS) != Z_OK) { + return process_zlib_error(conn, z); + } + k->zlib_init = ZLIB_INIT; /* Initial call state */ + } + } + + if(k->zlib_init == ZLIB_INIT_GZIP) { + /* Let zlib handle the gzip decompression entirely */ + z->next_in = (Bytef *)k->str; + z->avail_in = (uInt)nread; + /* Now uncompress the data */ + return inflate_stream(conn, k); + } + +#ifndef OLD_ZLIB_SUPPORT + /* Support for old zlib versions is compiled away and we are running with + an old version, so return an error. */ + return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND); + +#else + /* This next mess is to get around the potential case where there isn't + * enough data passed in to skip over the gzip header. If that happens, we + * malloc a block and copy what we have then wait for the next call. If + * there still isn't enough (this is definitely a worst-case scenario), we + * make the block bigger, copy the next part in and keep waiting. + * + * This is only required with zlib versions < 1.2.0.4 as newer versions + * can handle the gzip header themselves. + */ + + switch (k->zlib_init) { + /* Skip over gzip header? */ + case ZLIB_INIT: + { + /* Initial call state */ + ssize_t hlen; + + switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) { + case GZIP_OK: + z->next_in = (Bytef *)k->str + hlen; + z->avail_in = (uInt)(nread - hlen); + k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ + break; + + case GZIP_UNDERFLOW: + /* We need more data so we can find the end of the gzip header. It's + * possible that the memory block we malloc here will never be freed if + * the transfer abruptly aborts after this point. Since it's unlikely + * that circumstances will be right for this code path to be followed in + * the first place, and it's even more unlikely for a transfer to fail + * immediately afterwards, it should seldom be a problem. + */ + z->avail_in = (uInt)nread; + z->next_in = malloc(z->avail_in); + if(z->next_in == NULL) { + return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); + } + memcpy(z->next_in, k->str, z->avail_in); + k->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ + /* We don't have any data to inflate yet */ + return CURLE_OK; + + case GZIP_BAD: + default: + return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); + } + + } + break; + + case ZLIB_GZIP_HEADER: + { + /* Need more gzip header data state */ + ssize_t hlen; + unsigned char *oldblock = z->next_in; + + z->avail_in += (uInt)nread; + z->next_in = realloc(z->next_in, z->avail_in); + if(z->next_in == NULL) { + free(oldblock); + return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); + } + /* Append the new block of data to the previous one */ + memcpy(z->next_in + z->avail_in - nread, k->str, nread); + + switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) { + case GZIP_OK: + /* This is the zlib stream data */ + free(z->next_in); + /* Don't point into the malloced block since we just freed it */ + z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in; + z->avail_in = (uInt)(z->avail_in - hlen); + k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ + break; + + case GZIP_UNDERFLOW: + /* We still don't have any data to inflate! */ + return CURLE_OK; + + case GZIP_BAD: + default: + free(z->next_in); + return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); + } + + } + break; + + case ZLIB_GZIP_INFLATING: + default: + /* Inflating stream state */ + z->next_in = (Bytef *)k->str; + z->avail_in = (uInt)nread; + break; + } + + if(z->avail_in == 0) { + /* We don't have any data to inflate; wait until next time */ + return CURLE_OK; + } + + /* We've parsed the header, now uncompress the data */ + return inflate_stream(conn, k); +#endif +} + +CURL_STATIC void Curl_unencode_cleanup(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + struct SingleRequest *k = &data->req; + z_stream *z = &k->z; + if(k->zlib_init != ZLIB_UNINIT) + (void) exit_zlib(z, &k->zlib_init, CURLE_OK); +} + +#endif /* HAVE_LIBZ */ diff --git a/libcurl/src/lib/content_encoding.h b/libcurl/src/lib/content_encoding.h new file mode 100644 index 0000000..433e8d7 --- /dev/null +++ b/libcurl/src/lib/content_encoding.h @@ -0,0 +1,48 @@ +#ifndef HEADER_CURL_CONTENT_ENCODING_H +#define HEADER_CURL_CONTENT_ENCODING_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* + * Comma-separated list all supported Content-Encodings ('identity' is implied) + */ +#ifdef HAVE_LIBZ +#define ALL_CONTENT_ENCODINGS "deflate, gzip" +/* force a cleanup */ +CURL_STATIC void Curl_unencode_cleanup(struct connectdata *conn); +#else +#define ALL_CONTENT_ENCODINGS "identity" +#define Curl_unencode_cleanup(x) Curl_nop_stmt +#endif + +CURL_STATIC CURLcode Curl_unencode_deflate_write(struct connectdata *conn, + struct SingleRequest *req, + ssize_t nread); + +CURL_STATIC CURLcode +Curl_unencode_gzip_write(struct connectdata *conn, + struct SingleRequest *k, + ssize_t nread); + + +#endif /* HEADER_CURL_CONTENT_ENCODING_H */ diff --git a/libcurl/src/lib/cookie.c b/libcurl/src/lib/cookie.c new file mode 100644 index 0000000..61fc759 --- /dev/null +++ b/libcurl/src/lib/cookie.c @@ -0,0 +1,1365 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/*** + + +RECEIVING COOKIE INFORMATION +============================ + +struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, + const char *file, struct CookieInfo *inc, bool newsession); + + Inits a cookie struct to store data in a local file. This is always + called before any cookies are set. + +struct Cookie *Curl_cookie_add(struct SessionHandle *data, + struct CookieInfo *c, bool httpheader, char *lineptr, + const char *domain, const char *path); + + The 'lineptr' parameter is a full "Set-cookie:" line as + received from a server. + + The function need to replace previously stored lines that this new + line superceeds. + + It may remove lines that are expired. + + It should return an indication of success/error. + + +SENDING COOKIE INFORMATION +========================== + +struct Cookies *Curl_cookie_getlist(struct CookieInfo *cookie, + char *host, char *path, bool secure); + + For a given host and path, return a linked list of cookies that + the client should send to the server if used now. The secure + boolean informs the cookie if a secure connection is achieved or + not. + + It shall only return cookies that haven't expired. + + +Example set of cookies: + + Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure + Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/ftgw; secure + Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: + Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday, + 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure +****/ + + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + +#include "curl_printf.h" +#include "urldata.h" +#include "cookie.h" +#include "strequal.h" +#include "strtok.h" +#include "sendf.h" +#include "slist.h" +#include "share.h" +#include "strtoofft.h" +#include "rawstr.h" +#include "curl_memrchr.h" +#include "inet_pton.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +static void freecookie(struct Cookie *co) +{ + free(co->expirestr); + free(co->domain); + free(co->path); + free(co->spath); + free(co->name); + free(co->value); + free(co->maxage); + free(co->version); + free(co); +} + +static bool tailmatch(const char *cooke_domain, const char *hostname) +{ + size_t cookie_domain_len = strlen(cooke_domain); + size_t hostname_len = strlen(hostname); + + if(hostname_len < cookie_domain_len) + return FALSE; + + if(!Curl_raw_equal(cooke_domain, hostname+hostname_len-cookie_domain_len)) + return FALSE; + + /* A lead char of cookie_domain is not '.'. + RFC6265 4.1.2.3. The Domain Attribute says: + For example, if the value of the Domain attribute is + "example.com", the user agent will include the cookie in the Cookie + header when making HTTP requests to example.com, www.example.com, and + www.corp.example.com. + */ + if(hostname_len == cookie_domain_len) + return TRUE; + if('.' == *(hostname + hostname_len - cookie_domain_len - 1)) + return TRUE; + return FALSE; +} + +/* + * matching cookie path and url path + * RFC6265 5.1.4 Paths and Path-Match + */ +static bool pathmatch(const char* cookie_path, const char* request_uri) +{ + size_t cookie_path_len; + size_t uri_path_len; + char* uri_path = NULL; + char* pos; + bool ret = FALSE; + + /* cookie_path must not have last '/' separator. ex: /sample */ + cookie_path_len = strlen(cookie_path); + if(1 == cookie_path_len) { + /* cookie_path must be '/' */ + return TRUE; + } + + uri_path = strdup(request_uri); + if(!uri_path) + return FALSE; + pos = strchr(uri_path, '?'); + if(pos) + *pos = 0x0; + + /* #-fragments are already cut off! */ + if(0 == strlen(uri_path) || uri_path[0] != '/') { + free(uri_path); + uri_path = strdup("/"); + if(!uri_path) + return FALSE; + } + + /* here, RFC6265 5.1.4 says + 4. Output the characters of the uri-path from the first character up + to, but not including, the right-most %x2F ("/"). + but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site + without redirect. + Ignore this algorithm because /hoge is uri path for this case + (uri path is not /). + */ + + uri_path_len = strlen(uri_path); + + if(uri_path_len < cookie_path_len) { + ret = FALSE; + goto pathmatched; + } + + /* not using checkprefix() because matching should be case-sensitive */ + if(strncmp(cookie_path, uri_path, cookie_path_len)) { + ret = FALSE; + goto pathmatched; + } + + /* The cookie-path and the uri-path are identical. */ + if(cookie_path_len == uri_path_len) { + ret = TRUE; + goto pathmatched; + } + + /* here, cookie_path_len < url_path_len */ + if(uri_path[cookie_path_len] == '/') { + ret = TRUE; + goto pathmatched; + } + + ret = FALSE; + +pathmatched: + free(uri_path); + return ret; +} + +/* + * cookie path sanitize + */ +static char *sanitize_cookie_path(const char *cookie_path) +{ + size_t len; + char *new_path = strdup(cookie_path); + if(!new_path) + return NULL; + + /* some stupid site sends path attribute with '"'. */ + len = strlen(new_path); + if(new_path[0] == '\"') { + memmove((void *)new_path, (const void *)(new_path + 1), len); + len--; + } + if(len && (new_path[len - 1] == '\"')) { + new_path[len - 1] = 0x0; + len--; + } + + /* RFC6265 5.2.4 The Path Attribute */ + if(new_path[0] != '/') { + /* Let cookie-path be the default-path. */ + free(new_path); + new_path = strdup("/"); + return new_path; + } + + /* convert /hoge/ to /hoge */ + if(len && new_path[len - 1] == '/') { + new_path[len - 1] = 0x0; + } + + return new_path; +} + +/* + * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). + * + * NOTE: OOM or cookie parsing failures are ignored. + */ +CURL_STATIC void Curl_cookie_loadfiles(struct SessionHandle *data) +{ + struct curl_slist *list = data->change.cookielist; + if(list) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + while(list) { + struct CookieInfo *newcookies = Curl_cookie_init(data, + list->data, + data->cookies, + data->set.cookiesession); + if(!newcookies) + /* Failure may be due to OOM or a bad cookie; both are ignored + * but only the first should be + */ + infof(data, "ignoring failed cookie_init for %s\n", list->data); + else + data->cookies = newcookies; + list = list->next; + } + curl_slist_free_all(data->change.cookielist); /* clean up list */ + data->change.cookielist = NULL; /* don't do this again! */ + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +} + +/* + * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL + * that will be freed before the allocated string is stored there. + * + * It is meant to easily replace strdup() + */ +static void strstore(char **str, const char *newstr) +{ + free(*str); + *str = strdup(newstr); +} + +/* + * remove_expired() removes expired cookies. + */ +static void remove_expired(struct CookieInfo *cookies) +{ + struct Cookie *co, *nx, *pv; + curl_off_t now = (curl_off_t)time(NULL); + + co = cookies->cookies; + pv = NULL; + while(co) { + nx = co->next; + if((co->expirestr || co->maxage) && co->expires < now) { + if(co == cookies->cookies) { + cookies->cookies = co->next; + } + else { + pv->next = co->next; + } + cookies->numcookies--; + freecookie(co); + } + else { + pv = co; + } + co = nx; + } +} + +/* + * 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() + * + * Add a single cookie line to the cookie keeping object. + * + * Be aware that sometimes we get an IP-only host name, and that might also be + * a numerical IPv6 address. + * + * Returns NULL on out of memory or invalid cookie. This is suboptimal, + * as they should be treated separately. + ***************************************************************************/ + +struct Cookie * +Curl_cookie_add(struct SessionHandle *data, + /* The 'data' pointer here may be NULL at times, and thus + must only be used very carefully for things that can deal + with data being NULL. Such as infof() and similar */ + + struct CookieInfo *c, + bool httpheader, /* TRUE if HTTP header-style line */ + char *lineptr, /* first character of the line */ + const char *domain, /* default domain */ + const char *path) /* full path used when this cookie is set, + used to get default path for the cookie + unless set */ +{ + struct Cookie *clist; + char name[MAX_NAME]; + struct Cookie *co; + struct Cookie *lastc=NULL; + time_t now = time(NULL); + bool replace_old = FALSE; + bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */ + +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)data; +#endif + + /* First, alloc and init a new struct for it */ + co = calloc(1, sizeof(struct Cookie)); + if(!co) + return NULL; /* bail out if we're this low on memory */ + + if(httpheader) { + /* This line was read off a HTTP-header */ + const char *ptr; + const char *semiptr; + char *what; + + what = malloc(MAX_COOKIE_LINE); + if(!what) { + free(co); + return NULL; + } + + semiptr=strchr(lineptr, ';'); /* first, find a semicolon */ + + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + + ptr = lineptr; + do { + /* we have a = pair or a stand-alone word here */ + name[0]=what[0]=0; /* init the buffers */ + if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n =] =%" + MAX_COOKIE_LINE_TXT "[^;\r\n]", + name, what)) { + /* Use strstore() below to properly deal with received cookie + headers that have the same string property set more than once, + and then we use the last one. */ + const char *whatptr; + bool done = FALSE; + bool sep; + size_t len=strlen(what); + const char *endofn = &ptr[ strlen(name) ]; + + /* skip trailing spaces in name */ + while(*endofn && ISBLANK(*endofn)) + endofn++; + + /* name ends with a '=' ? */ + sep = (*endofn == '=')?TRUE:FALSE; + + /* Strip off trailing whitespace from the 'what' */ + while(len && ISBLANK(what[len-1])) { + what[len-1]=0; + len--; + } + + /* Skip leading whitespace from the 'what' */ + whatptr=what; + while(*whatptr && ISBLANK(*whatptr)) + whatptr++; + + if(!len) { + /* this was a "=" with no content, and we must allow + 'secure' and 'httponly' specified this weirdly */ + done = TRUE; + if(Curl_raw_equal("secure", name)) + co->secure = TRUE; + else if(Curl_raw_equal("httponly", name)) + co->httponly = TRUE; + else if(sep) + /* there was a '=' so we're not done parsing this field */ + done = FALSE; + } + if(done) + ; + else if(Curl_raw_equal("path", name)) { + strstore(&co->path, whatptr); + if(!co->path) { + badcookie = TRUE; /* out of memory bad */ + break; + } + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) { + badcookie = TRUE; /* out of memory bad */ + break; + } + } + 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, + or the given domain is not valid and thus cannot be set. */ + + if('.' == whatptr[0]) + whatptr++; /* ignore preceding dot */ + + is_ip = isip(domain ? domain : whatptr); + + /* check for more dots */ + dotp = strchr(whatptr, '.'); + if(!dotp) + domain=":"; + + if(!domain + || (is_ip && !strcmp(whatptr, domain)) + || (!is_ip && tailmatch(whatptr, domain))) { + strstore(&co->domain, whatptr); + if(!co->domain) { + badcookie = TRUE; + break; + } + if(!is_ip) + co->tailmatch=TRUE; /* we always do that if the domain name was + given */ + } + else { + /* we did not get a tailmatch and then the attempted set domain + is not a domain to which the current host belongs. Mark as + bad. */ + badcookie=TRUE; + infof(data, "skipped cookie with bad tailmatch domain: %s\n", + whatptr); + } + } + else if(Curl_raw_equal("version", name)) { + strstore(&co->version, whatptr); + if(!co->version) { + badcookie = TRUE; + break; + } + } + else if(Curl_raw_equal("max-age", name)) { + /* Defined in RFC2109: + + Optional. The Max-Age attribute defines the lifetime of the + cookie, in seconds. The delta-seconds value is a decimal non- + negative integer. After delta-seconds seconds elapse, the + client should discard the cookie. A value of zero means the + cookie should be discarded immediately. + + */ + strstore(&co->maxage, whatptr); + if(!co->maxage) { + badcookie = TRUE; + break; + } + } + else if(Curl_raw_equal("expires", name)) { + strstore(&co->expirestr, whatptr); + if(!co->expirestr) { + badcookie = TRUE; + break; + } + } + else if(!co->name) { + co->name = strdup(name); + co->value = strdup(whatptr); + if(!co->name || !co->value) { + badcookie = TRUE; + break; + } + } + /* + else this is the second (or more) name we don't know + about! */ + } + else { + /* this is an "illegal" = pair */ + } + + if(!semiptr || !*semiptr) { + /* we already know there are no more cookies */ + semiptr = NULL; + continue; + } + + ptr=semiptr+1; + while(*ptr && ISBLANK(*ptr)) + ptr++; + semiptr=strchr(ptr, ';'); /* now, find the next semicolon */ + + if(!semiptr && *ptr) + /* There are no more semicolons, but there's a final name=value pair + coming up */ + semiptr=strchr(ptr, '\0'); + } while(semiptr); + + if(co->maxage) { + co->expires = + curlx_strtoofft((*co->maxage=='\"')? + &co->maxage[1]:&co->maxage[0], NULL, 10); + if(CURL_OFF_T_MAX - now < co->expires) + /* avoid overflow */ + co->expires = CURL_OFF_T_MAX; + else + co->expires += now; + } + else if(co->expirestr) { + /* Note that if the date couldn't get parsed for whatever reason, + the cookie will be treated as a session cookie */ + co->expires = curl_getdate(co->expirestr, NULL); + + /* Session cookies have expires set to 0 so if we get that back + from the date parser let's add a second to make it a + non-session cookie */ + if(co->expires == 0) + co->expires = 1; + else if(co->expires < 0) + co->expires = 0; + } + + if(!badcookie && !co->domain) { + if(domain) { + /* no domain was given in the header line, set the default */ + co->domain=strdup(domain); + if(!co->domain) + badcookie = TRUE; + } + } + + if(!badcookie && !co->path && path) { + /* No path was given in the header line, set the default. + Note that the passed-in path to this function MAY have a '?' and + following part that MUST not be stored as part of the path. */ + char *queryp = strchr(path, '?'); + + /* queryp is where the interesting part of the path ends, so now we + want to the find the last */ + char *endslash; + if(!queryp) + endslash = strrchr(path, '/'); + else + endslash = memrchr(path, '/', (size_t)(queryp - path)); + if(endslash) { + size_t pathlen = (size_t)(endslash-path+1); /* include ending slash */ + co->path=malloc(pathlen+1); /* one extra for the zero byte */ + if(co->path) { + memcpy(co->path, path, pathlen); + co->path[pathlen]=0; /* zero terminate */ + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) + badcookie = TRUE; /* out of memory bad */ + } + else + badcookie = TRUE; + } + } + + free(what); + + if(badcookie || !co->name) { + /* we didn't get a cookie name or a bad one, + this is an illegal line, bail out */ + freecookie(co); + return NULL; + } + + } + else { + /* This line is NOT a HTTP header style line, we do offer support for + reading the odd netscape cookies-file format here */ + char *ptr; + char *firstptr; + char *tok_buf=NULL; + int fields; + + /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies + marked with httpOnly after the domain name are not accessible + from javascripts, but since curl does not operate at javascript + level, we include them anyway. In Firefox's cookie files, these + lines are preceded with #HttpOnly_ and then everything is + as usual, so we skip 10 characters of the line.. + */ + if(strncmp(lineptr, "#HttpOnly_", 10) == 0) { + lineptr += 10; + co->httponly = TRUE; + } + + if(lineptr[0]=='#') { + /* don't even try the comments */ + free(co); + return NULL; + } + /* strip off the possible end-of-line characters */ + ptr=strchr(lineptr, '\r'); + if(ptr) + *ptr=0; /* clear it */ + ptr=strchr(lineptr, '\n'); + if(ptr) + *ptr=0; /* clear it */ + + firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ + + /* Now loop through the fields and init the struct we already have + allocated */ + for(ptr=firstptr, fields=0; ptr && !badcookie; + ptr=strtok_r(NULL, "\t", &tok_buf), fields++) { + switch(fields) { + case 0: + if(ptr[0]=='.') /* skip preceding dots */ + ptr++; + co->domain = strdup(ptr); + if(!co->domain) + badcookie = TRUE; + break; + case 1: + /* This field got its explanation on the 23rd of May 2001 by + Andr�s Garc�a: + + flag: A TRUE/FALSE value indicating if all machines within a given + domain can access the variable. This value is set automatically by + the browser, depending on the value you set for the domain. + + As far as I can see, it is set to true when the cookie says + .domain.com and to false when the domain is complete www.domain.com + */ + co->tailmatch = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE; + break; + case 2: + /* It turns out, that sometimes the file format allows the path + field to remain not filled in, we try to detect this and work + around it! Andr�s Garc�a made us aware of this... */ + if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) { + /* only if the path doesn't look like a boolean option! */ + co->path = strdup(ptr); + if(!co->path) + badcookie = TRUE; + else { + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) { + badcookie = TRUE; /* out of memory bad */ + } + } + break; + } + /* this doesn't look like a path, make one up! */ + co->path = strdup("/"); + if(!co->path) + badcookie = TRUE; + co->spath = strdup("/"); + if(!co->spath) + badcookie = TRUE; + fields++; /* add a field and fall down to secure */ + /* FALLTHROUGH */ + case 3: + co->secure = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE; + break; + case 4: + co->expires = curlx_strtoofft(ptr, NULL, 10); + break; + case 5: + co->name = strdup(ptr); + if(!co->name) + badcookie = TRUE; + break; + case 6: + co->value = strdup(ptr); + if(!co->value) + badcookie = TRUE; + break; + } + } + if(6 == fields) { + /* we got a cookie with blank contents, fix it */ + co->value = strdup(""); + if(!co->value) + badcookie = TRUE; + else + fields++; + } + + if(!badcookie && (7 != fields)) + /* we did not find the sufficient number of fields */ + badcookie = TRUE; + + if(badcookie) { + freecookie(co); + return NULL; + } + + } + + if(!c->running && /* read from a file */ + c->newsession && /* clean session cookies */ + !co->expires) { /* this is a session cookie since it doesn't expire! */ + freecookie(co); + return NULL; + } + + co->livecookie = c->running; + + /* now, we have parsed the incoming line, we must now check if this + superceeds an already existing cookie, which it may if the previous have + the same domain and path as this */ + + /* at first, remove expired cookies */ + remove_expired(c); + + clist = c->cookies; + replace_old = FALSE; + while(clist) { + if(Curl_raw_equal(clist->name, co->name)) { + /* the names are identical */ + + if(clist->domain && co->domain) { + if(Curl_raw_equal(clist->domain, co->domain)) + /* The domains are identical */ + replace_old=TRUE; + } + else if(!clist->domain && !co->domain) + replace_old = TRUE; + + if(replace_old) { + /* the domains were identical */ + + if(clist->spath && co->spath) { + if(Curl_raw_equal(clist->spath, co->spath)) { + replace_old = TRUE; + } + else + replace_old = FALSE; + } + else if(!clist->spath && !co->spath) + replace_old = TRUE; + else + replace_old = FALSE; + + } + + if(replace_old && !co->livecookie && clist->livecookie) { + /* Both cookies matched fine, except that the already present + cookie is "live", which means it was set from a header, while + the new one isn't "live" and thus only read from a file. We let + live cookies stay alive */ + + /* Free the newcomer and get out of here! */ + freecookie(co); + return NULL; + } + + if(replace_old) { + co->next = clist->next; /* get the next-pointer first */ + + /* then free all the old pointers */ + free(clist->name); + free(clist->value); + free(clist->domain); + free(clist->path); + free(clist->spath); + free(clist->expirestr); + free(clist->version); + free(clist->maxage); + + *clist = *co; /* then store all the new data */ + + free(co); /* free the newly alloced memory */ + co = clist; /* point to the previous struct instead */ + + /* We have replaced a cookie, now skip the rest of the list but + make sure the 'lastc' pointer is properly set */ + do { + lastc = clist; + clist = clist->next; + } while(clist); + break; + } + } + lastc = clist; + clist = clist->next; + } + + if(c->running) + /* Only show this when NOT reading the cookies from a file */ + infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, " + "expire %" CURL_FORMAT_CURL_OFF_T "\n", + replace_old?"Replaced":"Added", co->name, co->value, + co->domain, co->path, co->expires); + + if(!replace_old) { + /* then make the last item point on this new one */ + if(lastc) + lastc->next = co; + else + c->cookies = co; + c->numcookies++; /* one more cookie in the jar */ + } + + return co; +} + +/***************************************************************************** + * + * Curl_cookie_init() + * + * Inits a cookie struct to read data from a local file. This is always + * called before any cookies are set. File may be NULL. + * + * If 'newsession' is TRUE, discard all "session cookies" on read from file. + * + * Returns NULL on out of memory. Invalid cookies are ignored. + ****************************************************************************/ +CURL_STATIC struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, + const char *file, + struct CookieInfo *inc, + bool newsession) +{ + struct CookieInfo *c; + FILE *fp = NULL; + bool fromfile=TRUE; + char *line = NULL; + + if(NULL == inc) { + /* we didn't get a struct, create one */ + c = calloc(1, sizeof(struct CookieInfo)); + if(!c) + return NULL; /* failed to get memory */ + c->filename = strdup(file?file:"none"); /* copy the name just in case */ + if(!c->filename) + goto fail; /* failed to get memory */ + } + else { + /* we got an already existing one, use that */ + c = inc; + } + c->running = FALSE; /* this is not running, this is init */ + + if(file && strequal(file, "-")) { + fp = stdin; + fromfile=FALSE; + } + else if(file && !*file) { + /* points to a "" string */ + fp = NULL; + } + else + fp = file?fopen(file, "r"):NULL; + + c->newsession = newsession; /* new session? */ + + if(fp) { + char *lineptr; + bool headerline; + + line = malloc(MAX_COOKIE_LINE); + if(!line) + goto fail; + while(fgets(line, MAX_COOKIE_LINE, fp)) { + if(checkprefix("Set-Cookie:", line)) { + /* This is a cookie line, get it! */ + lineptr=&line[11]; + headerline=TRUE; + } + else { + lineptr=line; + headerline=FALSE; + } + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + + Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL); + } + free(line); /* free the line buffer */ + + if(fromfile) + fclose(fp); + } + + c->running = TRUE; /* now, we're running */ + + return c; + +fail: + free(line); + if(!inc) + /* Only clean up if we allocated it here, as the original could still be in + * use by a share handle */ + Curl_cookie_cleanup(c); + if(fromfile && fp) + fclose(fp); + return NULL; /* out of memory */ +} + +/* sort this so that the longest path gets before the shorter path */ +static int cookie_sort(const void *p1, const void *p2) +{ + struct Cookie *c1 = *(struct Cookie **)p1; + struct Cookie *c2 = *(struct Cookie **)p2; + size_t l1, l2; + + /* 1 - compare cookie path lengths */ + l1 = c1->path ? strlen(c1->path) : 0; + l2 = c2->path ? strlen(c2->path) : 0; + + if(l1 != l2) + return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */ + + /* 2 - compare cookie domain lengths */ + l1 = c1->domain ? strlen(c1->domain) : 0; + l2 = c2->domain ? strlen(c2->domain) : 0; + + if(l1 != l2) + return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */ + + /* 3 - compare cookie names */ + if(c1->name && c2->name) + return strcmp(c1->name, c2->name); + + /* sorry, can't be more deterministic */ + return 0; +} + +/***************************************************************************** + * + * Curl_cookie_getlist() + * + * For a given host and path, return a linked list of cookies that the + * client should send to the server if used now. The secure boolean informs + * the cookie if a secure connection is achieved or not. + * + * It shall only return cookies that haven't expired. + * + ****************************************************************************/ + +CURL_STATIC struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + const char *host, const char *path, + bool secure) +{ + struct Cookie *newco; + struct Cookie *co; + time_t now = time(NULL); + struct Cookie *mainco=NULL; + size_t matches = 0; + bool is_ip; + + if(!c || !c->cookies) + return NULL; /* no cookie struct or no cookies in the struct */ + + /* at first, remove expired cookies */ + remove_expired(c); + + /* check if host is an IP(v4|v6) address */ + is_ip = isip(host); + + co = c->cookies; + + while(co) { + /* only process this cookie if it is not expired or had no expire + date AND that if the cookie requires we're secure we must only + continue if we are! */ + if((!co->expires || (co->expires > now)) && + (co->secure?secure:TRUE)) { + + /* now check if the domain is correct */ + if(!co->domain || + (co->tailmatch && !is_ip && tailmatch(co->domain, host)) || + ((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) { + /* the right part of the host matches the domain stuff in the + cookie data */ + + /* now check the left part of the path with the cookies path + requirement */ + if(!co->spath || pathmatch(co->spath, path) ) { + + /* and now, we know this is a match and we should create an + entry for the return-linked-list */ + + newco = malloc(sizeof(struct Cookie)); + if(newco) { + /* first, copy the whole source cookie: */ + memcpy(newco, co, sizeof(struct Cookie)); + + /* then modify our next */ + newco->next = mainco; + + /* point the main to us */ + mainco = newco; + + matches++; + } + else { + fail: + /* failure, clear up the allocated chain and return NULL */ + while(mainco) { + co = mainco->next; + free(mainco); + mainco = co; + } + + return NULL; + } + } + } + } + co = co->next; + } + + if(matches) { + /* Now we need to make sure that if there is a name appearing more than + once, the longest specified path version comes first. To make this + the swiftest way, we just sort them all based on path length. */ + struct Cookie **array; + size_t i; + + /* alloc an array and store all cookie pointers */ + array = malloc(sizeof(struct Cookie *) * matches); + if(!array) + goto fail; + + co = mainco; + + for(i=0; co; co = co->next) + array[i++] = co; + + /* now sort the cookie pointers in path length order */ + qsort(array, matches, sizeof(struct Cookie *), cookie_sort); + + /* remake the linked list order according to the new order */ + + mainco = array[0]; /* start here */ + for(i=0; inext = array[i+1]; + array[matches-1]->next = NULL; /* terminate the list */ + + free(array); /* remove the temporary data again */ + } + + return mainco; /* return the new list */ +} + +/***************************************************************************** + * + * Curl_cookie_clearall() + * + * Clear all existing cookies and reset the counter. + * + ****************************************************************************/ +CURL_STATIC void Curl_cookie_clearall(struct CookieInfo *cookies) +{ + if(cookies) { + Curl_cookie_freelist(cookies->cookies, TRUE); + cookies->cookies = NULL; + cookies->numcookies = 0; + } +} + +/***************************************************************************** + * + * Curl_cookie_freelist() + * + * Free a list of cookies previously returned by Curl_cookie_getlist(); + * + * The 'cookiestoo' argument tells this function whether to just free the + * list or actually also free all cookies within the list as well. + * + ****************************************************************************/ + +CURL_STATIC void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo) +{ + struct Cookie *next; + while(co) { + next = co->next; + if(cookiestoo) + freecookie(co); + else + free(co); /* we only free the struct since the "members" are all just + pointed out in the main cookie list! */ + co = next; + } +} + + +/***************************************************************************** + * + * Curl_cookie_clearsess() + * + * Free all session cookies in the cookies list. + * + ****************************************************************************/ +CURL_STATIC void Curl_cookie_clearsess(struct CookieInfo *cookies) +{ + struct Cookie *first, *curr, *next, *prev = NULL; + + if(!cookies || !cookies->cookies) + return; + + first = curr = prev = cookies->cookies; + + for(; curr; curr = next) { + next = curr->next; + if(!curr->expires) { + if(first == curr) + first = next; + + if(prev == curr) + prev = next; + else + prev->next = next; + + freecookie(curr); + cookies->numcookies--; + } + else + prev = curr; + } + + cookies->cookies = first; +} + + +/***************************************************************************** + * + * Curl_cookie_cleanup() + * + * Free a "cookie object" previous created with Curl_cookie_init(). + * + ****************************************************************************/ +CURL_STATIC void Curl_cookie_cleanup(struct CookieInfo *c) +{ + if(c) { + free(c->filename); + Curl_cookie_freelist(c->cookies, TRUE); + free(c); /* free the base struct as well */ + } +} + +/* get_netscape_format() + * + * Formats a string for Netscape output file, w/o a newline at the end. + * + * Function returns a char * to a formatted line. Has to be free()d +*/ +static char *get_netscape_format(const struct Cookie *co) +{ + return aprintf( + "%s" /* httponly preamble */ + "%s%s\t" /* domain */ + "%s\t" /* tailmatch */ + "%s\t" /* path */ + "%s\t" /* secure */ + "%" CURL_FORMAT_CURL_OFF_T "\t" /* expires */ + "%s\t" /* name */ + "%s", /* value */ + co->httponly?"#HttpOnly_":"", + /* Make sure all domains are prefixed with a dot if they allow + tailmatching. This is Mozilla-style. */ + (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"", + co->domain?co->domain:"unknown", + co->tailmatch?"TRUE":"FALSE", + co->path?co->path:"/", + co->secure?"TRUE":"FALSE", + co->expires, + co->name, + co->value?co->value:""); +} + +/* + * cookie_output() + * + * Writes all internally known cookies to the specified file. Specify + * "-" as file name to write to stdout. + * + * The function returns non-zero on write failure. + */ +static int cookie_output(struct CookieInfo *c, const char *dumphere) +{ + struct Cookie *co; + FILE *out; + bool use_stdout=FALSE; + + if((NULL == c) || (0 == c->numcookies)) + /* If there are no known cookies, we don't write or even create any + destination file */ + return 0; + + /* at first, remove expired cookies */ + remove_expired(c); + + if(strequal("-", dumphere)) { + /* use stdout */ + out = stdout; + use_stdout=TRUE; + } + else { + out = fopen(dumphere, "w"); + if(!out) + return 1; /* failure */ + } + + if(c) { + char *format_ptr; + + fputs("# Netscape HTTP Cookie File\n" + "# http://curl.haxx.se/docs/http-cookies.html\n" + "# This file was generated by libcurl! Edit at your own risk.\n\n", + out); + co = c->cookies; + + while(co) { + format_ptr = get_netscape_format(co); + if(format_ptr == NULL) { + fprintf(out, "#\n# Fatal libcurl error\n"); + if(!use_stdout) + fclose(out); + return 1; + } + fprintf(out, "%s\n", format_ptr); + free(format_ptr); + co=co->next; + } + } + + if(!use_stdout) + fclose(out); + + return 0; +} + +CURL_STATIC struct curl_slist *Curl_cookie_list(struct SessionHandle *data) +{ + struct curl_slist *list = NULL; + struct curl_slist *beg; + struct Cookie *c; + char *line; + + if((data->cookies == NULL) || + (data->cookies->numcookies == 0)) + return NULL; + + c = data->cookies->cookies; + + while(c) { + /* fill the list with _all_ the cookies we know */ + line = get_netscape_format(c); + if(!line) { + curl_slist_free_all(list); + return NULL; + } + beg = Curl_slist_append_nodup(list, line); + if(!beg) { + free(line); + curl_slist_free_all(list); + return NULL; + } + list = beg; + c = c->next; + } + + return list; +} + +CURL_STATIC void Curl_flush_cookies(struct SessionHandle *data, int cleanup) +{ + if(data->set.str[STRING_COOKIEJAR]) { + if(data->change.cookielist) { + /* If there is a list of cookie files to read, do it first so that + we have all the told files read before we write the new jar. + Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */ + Curl_cookie_loadfiles(data); + } + + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + + /* if we have a destination file for all the cookies to get dumped to */ + if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR])) + infof(data, "WARNING: failed to save cookies in %s\n", + data->set.str[STRING_COOKIEJAR]); + } + else { + if(cleanup && data->change.cookielist) { + /* since nothing is written, we can just free the list of cookie file + names */ + curl_slist_free_all(data->change.cookielist); /* clean up list */ + data->change.cookielist = NULL; + } + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + } + + if(cleanup && (!data->share || (data->cookies != data->share->cookies))) { + Curl_cookie_cleanup(data->cookies); + } + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); +} + +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */ diff --git a/libcurl/src/lib/cookie.h b/libcurl/src/lib/cookie.h new file mode 100644 index 0000000..bc60ba4 --- /dev/null +++ b/libcurl/src/lib/cookie.h @@ -0,0 +1,104 @@ +#ifndef HEADER_CURL_COOKIE_H +#define HEADER_CURL_COOKIE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#include + +struct Cookie { + struct Cookie *next; /* next in the chain */ + char *name; /* = value */ + char *value; /* name = */ + char *path; /* path = which is in Set-Cookie: */ + char *spath; /* sanitized cookie path */ + char *domain; /* domain = */ + curl_off_t expires; /* expires = */ + char *expirestr; /* the plain text version */ + bool tailmatch; /* weather we do tail-matchning of the domain name */ + + /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ + char *version; /* Version = */ + char *maxage; /* Max-Age = */ + + bool secure; /* whether the 'secure' keyword was used */ + bool livecookie; /* updated from a server, not a stored file */ + bool httponly; /* true if the httponly directive is present */ +}; + +struct CookieInfo { + /* linked list of cookies we know of */ + struct Cookie *cookies; + + char *filename; /* file we read from/write to */ + bool running; /* state info, for cookie adding information */ + long numcookies; /* number of cookies in the "jar" */ + bool newsession; /* new session, discard session cookies on load */ +}; + +/* This is the maximum line length we accept for a cookie line. RFC 2109 + section 6.3 says: + + "at least 4096 bytes per cookie (as measured by the size of the characters + that comprise the cookie non-terminal in the syntax description of the + Set-Cookie header)" + +*/ +#define MAX_COOKIE_LINE 5000 +#define MAX_COOKIE_LINE_TXT "4999" + +/* This is the maximum length of a cookie name we deal with: */ +#define MAX_NAME 1024 +#define MAX_NAME_TXT "1023" + +struct SessionHandle; +/* + * Add a cookie to the internal list of cookies. The domain and path arguments + * are only used if the header boolean is TRUE. + */ + +CURL_STATIC struct Cookie *Curl_cookie_add(struct SessionHandle *data, + struct CookieInfo *, bool header, char *lineptr, + const char *domain, const char *path); + +CURL_STATIC struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, + const char *, bool); +CURL_STATIC void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo); +CURL_STATIC void Curl_cookie_clearall(struct CookieInfo *cookies); +CURL_STATIC void Curl_cookie_clearsess(struct CookieInfo *cookies); + +#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) +#define Curl_cookie_list(x) NULL +#define Curl_cookie_loadfiles(x) Curl_nop_stmt +#define Curl_cookie_init(x,y,z,w) NULL +#define Curl_cookie_cleanup(x) Curl_nop_stmt +#define Curl_flush_cookies(x,y) Curl_nop_stmt +#else +CURL_STATIC void Curl_flush_cookies(struct SessionHandle *data, int cleanup); +CURL_STATIC void Curl_cookie_cleanup(struct CookieInfo *); +CURL_STATIC struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, + const char *, struct CookieInfo *, bool); +CURL_STATIC struct curl_slist *Curl_cookie_list(struct SessionHandle *data); +CURL_STATIC void Curl_cookie_loadfiles(struct SessionHandle *data); +#endif + +#endif /* HEADER_CURL_COOKIE_H */ diff --git a/libcurl/src/lib/curl_addrinfo.c b/libcurl/src/lib/curl_addrinfo.c new file mode 100644 index 0000000..e572fdc --- /dev/null +++ b/libcurl/src/lib/curl_addrinfo.c @@ -0,0 +1,558 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_SYS_UN_H +# include +#endif + +#ifdef __VMS +# include +# include +#endif + +#if defined(NETWARE) && defined(__NOVELL_LIBC__) +# undef in_addr_t +# define in_addr_t unsigned long +#endif + +#include "curl_addrinfo.h" +#include "inet_pton.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Curl_freeaddrinfo() + * + * This is used to free a linked list of Curl_addrinfo structs along + * with all its associated allocated storage. This function should be + * called once for each successful call to Curl_getaddrinfo_ex() or to + * any function call which actually allocates a Curl_addrinfo struct. + */ + +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ + defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) + /* workaround icc 9.1 optimizer issue */ +# define vqualifier volatile +#else +# define vqualifier +#endif + +CURL_STATIC void +Curl_freeaddrinfo(Curl_addrinfo *cahead) +{ + Curl_addrinfo *vqualifier canext; + Curl_addrinfo *ca; + + for(ca = cahead; ca != NULL; ca = canext) { + free(ca->ai_addr); + free(ca->ai_canonname); + canext = ca->ai_next; + + free(ca); + } +} + + +#ifdef HAVE_GETADDRINFO +/* + * Curl_getaddrinfo_ex() + * + * This is a wrapper function around system's getaddrinfo(), with + * the only difference that instead of returning a linked list of + * addrinfo structs this one returns a linked list of Curl_addrinfo + * ones. The memory allocated by this function *MUST* be free'd with + * Curl_freeaddrinfo(). For each successful call to this function + * there must be an associated call later to Curl_freeaddrinfo(). + * + * There should be no single call to system's getaddrinfo() in the + * whole library, any such call should be 'routed' through this one. + */ + +CURL_STATIC int +Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + Curl_addrinfo **result) +{ + const struct addrinfo *ai; + struct addrinfo *aihead; + Curl_addrinfo *cafirst = NULL; + Curl_addrinfo *calast = NULL; + Curl_addrinfo *ca; + size_t ss_size; + int error; + + *result = NULL; /* assume failure */ + + error = getaddrinfo(nodename, servname, hints, &aihead); + if(error) + return error; + + /* traverse the addrinfo list */ + + for(ai = aihead; ai != NULL; ai = ai->ai_next) { + + /* ignore elements with unsupported address family, */ + /* settle family-specific sockaddr structure size. */ + if(ai->ai_family == AF_INET) + ss_size = sizeof(struct sockaddr_in); +#ifdef ENABLE_IPV6 + else if(ai->ai_family == AF_INET6) + ss_size = sizeof(struct sockaddr_in6); +#endif + else + continue; + + /* ignore elements without required address info */ + if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0)) + continue; + + /* ignore elements with bogus address size */ + if((size_t)ai->ai_addrlen < ss_size) + continue; + + if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) { + error = EAI_MEMORY; + break; + } + + /* copy each structure member individually, member ordering, */ + /* size, or padding might be different for each platform. */ + + ca->ai_flags = ai->ai_flags; + ca->ai_family = ai->ai_family; + ca->ai_socktype = ai->ai_socktype; + ca->ai_protocol = ai->ai_protocol; + ca->ai_addrlen = (curl_socklen_t)ss_size; + ca->ai_addr = NULL; + ca->ai_canonname = NULL; + ca->ai_next = NULL; + + if((ca->ai_addr = malloc(ss_size)) == NULL) { + error = EAI_MEMORY; + free(ca); + break; + } + memcpy(ca->ai_addr, ai->ai_addr, ss_size); + + if(ai->ai_canonname != NULL) { + if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) { + error = EAI_MEMORY; + free(ca->ai_addr); + free(ca); + break; + } + } + + /* if the return list is empty, this becomes the first element */ + if(!cafirst) + cafirst = ca; + + /* add this element last in the return list */ + if(calast) + calast->ai_next = ca; + calast = ca; + + } + + /* destroy the addrinfo list */ + if(aihead) + freeaddrinfo(aihead); + + /* if we failed, also destroy the Curl_addrinfo list */ + if(error) { + Curl_freeaddrinfo(cafirst); + cafirst = NULL; + } + else if(!cafirst) { +#ifdef EAI_NONAME + /* rfc3493 conformant */ + error = EAI_NONAME; +#else + /* rfc3493 obsoleted */ + error = EAI_NODATA; +#endif +#ifdef USE_WINSOCK + SET_SOCKERRNO(error); +#endif + } + + *result = cafirst; + + /* This is not a CURLcode */ + return error; +} +#endif /* HAVE_GETADDRINFO */ + + +/* + * Curl_he2ai() + * + * This function returns a pointer to the first element of a newly allocated + * Curl_addrinfo struct linked list filled with the data of a given hostent. + * Curl_addrinfo is meant to work like the addrinfo struct does for a IPv6 + * stack, but usable also for IPv4, all hosts and environments. + * + * The memory allocated by this function *MUST* be free'd later on calling + * Curl_freeaddrinfo(). For each successful call to this function there + * must be an associated call later to Curl_freeaddrinfo(). + * + * Curl_addrinfo defined in "lib/curl_addrinfo.h" + * + * struct Curl_addrinfo { + * int ai_flags; + * int ai_family; + * int ai_socktype; + * int ai_protocol; + * curl_socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo * + * char *ai_canonname; + * struct sockaddr *ai_addr; + * struct Curl_addrinfo *ai_next; + * }; + * typedef struct Curl_addrinfo Curl_addrinfo; + * + * hostent defined in + * + * struct hostent { + * char *h_name; + * char **h_aliases; + * int h_addrtype; + * int h_length; + * char **h_addr_list; + * }; + * + * for backward compatibility: + * + * #define h_addr h_addr_list[0] + */ + +CURL_STATIC Curl_addrinfo * +Curl_he2ai(const struct hostent *he, int port) +{ + Curl_addrinfo *ai; + Curl_addrinfo *prevai = NULL; + Curl_addrinfo *firstai = NULL; + struct sockaddr_in *addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *addr6; +#endif + CURLcode result = CURLE_OK; + int i; + char *curr; + + if(!he) + /* no input == no output! */ + return NULL; + + DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL)); + + for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) { + + size_t ss_size; +#ifdef ENABLE_IPV6 + if(he->h_addrtype == AF_INET6) + ss_size = sizeof (struct sockaddr_in6); + else +#endif + ss_size = sizeof (struct sockaddr_in); + + if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) { + result = CURLE_OUT_OF_MEMORY; + break; + } + if((ai->ai_canonname = strdup(he->h_name)) == NULL) { + result = CURLE_OUT_OF_MEMORY; + free(ai); + break; + } + if((ai->ai_addr = calloc(1, ss_size)) == NULL) { + result = CURLE_OUT_OF_MEMORY; + free(ai->ai_canonname); + free(ai); + break; + } + + if(!firstai) + /* store the pointer we want to return from this function */ + firstai = ai; + + if(prevai) + /* make the previous entry point to this */ + prevai->ai_next = ai; + + ai->ai_family = he->h_addrtype; + + /* we return all names as STREAM, so when using this address for TFTP + the type must be ignored and conn->socktype be used instead! */ + ai->ai_socktype = SOCK_STREAM; + + ai->ai_addrlen = (curl_socklen_t)ss_size; + + /* leave the rest of the struct filled with zero */ + + switch (ai->ai_family) { + case AF_INET: + addr = (void *)ai->ai_addr; /* storage area for this info */ + + memcpy(&addr->sin_addr, curr, sizeof(struct in_addr)); + addr->sin_family = (unsigned short)(he->h_addrtype); + addr->sin_port = htons((unsigned short)port); + break; + +#ifdef ENABLE_IPV6 + case AF_INET6: + addr6 = (void *)ai->ai_addr; /* storage area for this info */ + + memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr)); + addr6->sin6_family = (unsigned short)(he->h_addrtype); + addr6->sin6_port = htons((unsigned short)port); + break; +#endif + } + + prevai = ai; + } + + if(result) { + Curl_freeaddrinfo(firstai); + firstai = NULL; + } + + return firstai; +} + + +struct namebuff { + struct hostent hostentry; + union { + struct in_addr ina4; +#ifdef ENABLE_IPV6 + struct in6_addr ina6; +#endif + } addrentry; + char *h_addr_list[2]; +}; + + +/* + * Curl_ip2addr() + * + * This function takes an internet address, in binary form, as input parameter + * along with its address family and the string version of the address, and it + * returns a Curl_addrinfo chain filled in correctly with information for the + * given address/host + */ + +CURL_STATIC Curl_addrinfo * +Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) +{ + Curl_addrinfo *ai; + +#if defined(__VMS) && \ + defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) +#pragma pointer_size save +#pragma pointer_size short +#pragma message disable PTRMISMATCH +#endif + + struct hostent *h; + struct namebuff *buf; + char *addrentry; + char *hoststr; + size_t addrsize; + + DEBUGASSERT(inaddr && hostname); + + buf = malloc(sizeof(struct namebuff)); + if(!buf) + return NULL; + + hoststr = strdup(hostname); + if(!hoststr) { + free(buf); + return NULL; + } + + switch(af) { + case AF_INET: + addrsize = sizeof(struct in_addr); + addrentry = (void *)&buf->addrentry.ina4; + memcpy(addrentry, inaddr, sizeof(struct in_addr)); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + addrsize = sizeof(struct in6_addr); + addrentry = (void *)&buf->addrentry.ina6; + memcpy(addrentry, inaddr, sizeof(struct in6_addr)); + break; +#endif + default: + free(hoststr); + free(buf); + return NULL; + } + + h = &buf->hostentry; + h->h_name = hoststr; + h->h_aliases = NULL; + h->h_addrtype = (short)af; + h->h_length = (short)addrsize; + h->h_addr_list = &buf->h_addr_list[0]; + h->h_addr_list[0] = addrentry; + h->h_addr_list[1] = NULL; /* terminate list of entries */ + +#if defined(__VMS) && \ + defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) +#pragma pointer_size restore +#pragma message enable PTRMISMATCH +#endif + + ai = Curl_he2ai(h, port); + + free(hoststr); + free(buf); + + return ai; +} + +/* + * Given an IPv4 or IPv6 dotted string address, this converts it to a proper + * allocated Curl_addrinfo struct and returns it. + */ +CURL_STATIC Curl_addrinfo *Curl_str2addr(char *address, int port) +{ + struct in_addr in; + if(Curl_inet_pton(AF_INET, address, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, address, port); +#ifdef ENABLE_IPV6 + else { + struct in6_addr in6; + if(Curl_inet_pton(AF_INET6, address, &in6) > 0) + /* This is a dotted IPv6 address ::1-style */ + return Curl_ip2addr(AF_INET6, &in6, address, port); + } +#endif + return NULL; /* bad input format */ +} + +#ifdef USE_UNIX_SOCKETS +/** + * Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo + * struct initialized with this path. + */ +CURL_STATIC Curl_addrinfo *Curl_unix2addr(const char *path) +{ + Curl_addrinfo *ai; + struct sockaddr_un *sa_un; + size_t path_len; + + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) + return NULL; + if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) { + free(ai); + return NULL; + } + /* sun_path must be able to store the NUL-terminated path */ + path_len = strlen(path); + if(path_len >= sizeof(sa_un->sun_path)) { + free(ai->ai_addr); + free(ai); + return NULL; + } + + ai->ai_family = AF_UNIX; + ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */ + ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un); + sa_un = (void *) ai->ai_addr; + sa_un->sun_family = AF_UNIX; + memcpy(sa_un->sun_path, path, path_len + 1); /* copy NUL byte */ + return ai; +} +#endif + +#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) +/* + * curl_dofreeaddrinfo() + * + * This is strictly for memory tracing and are using the same style as the + * family otherwise present in memdebug.c. I put these ones here since they + * require a bunch of structs I didn't want to include in memdebug.c + */ + +void +curl_dofreeaddrinfo(struct addrinfo *freethis, + int line, const char *source) +{ + (freeaddrinfo)(freethis); + curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n", + source, line, (void *)freethis); +} +#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */ + + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) +/* + * curl_dogetaddrinfo() + * + * This is strictly for memory tracing and are using the same style as the + * family otherwise present in memdebug.c. I put these ones here since they + * require a bunch of structs I didn't want to include in memdebug.c + */ + +int +curl_dogetaddrinfo(const char *hostname, + const char *service, + const struct addrinfo *hints, + struct addrinfo **result, + int line, const char *source) +{ + int res=(getaddrinfo)(hostname, service, hints, result); + if(0 == res) + /* success */ + curl_memlog("ADDR %s:%d getaddrinfo() = %p\n", + source, line, (void *)*result); + else + curl_memlog("ADDR %s:%d getaddrinfo() failed\n", + source, line); + return res; +} +#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */ + diff --git a/libcurl/src/lib/curl_addrinfo.h b/libcurl/src/lib/curl_addrinfo.h new file mode 100644 index 0000000..5f4f0f9 --- /dev/null +++ b/libcurl/src/lib/curl_addrinfo.h @@ -0,0 +1,101 @@ +#ifndef HEADER_CURL_ADDRINFO_H +#define HEADER_CURL_ADDRINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#ifdef __VMS +# include +# include +# include +#endif + + +/* + * Curl_addrinfo is our internal struct definition that we use to allow + * consistent internal handling of this data. We use this even when the + * system provides an addrinfo structure definition. And we use this for + * all sorts of IPv4 and IPV6 builds. + */ + +struct Curl_addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + curl_socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */ + char *ai_canonname; + struct sockaddr *ai_addr; + struct Curl_addrinfo *ai_next; +}; +typedef struct Curl_addrinfo Curl_addrinfo; + +CURL_STATIC void +Curl_freeaddrinfo(Curl_addrinfo *cahead); + +#ifdef HAVE_GETADDRINFO +CURL_STATIC int +Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + Curl_addrinfo **result); +#endif + +CURL_STATIC Curl_addrinfo * +Curl_he2ai(const struct hostent *he, int port); + +CURL_STATIC Curl_addrinfo * +Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); + +CURL_STATIC Curl_addrinfo *Curl_str2addr(char *dotted, int port); + +#ifdef USE_UNIX_SOCKETS +CURL_STATIC Curl_addrinfo *Curl_unix2addr(const char *path); +#endif + +#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) +void +curl_dofreeaddrinfo(struct addrinfo *freethis, + int line, const char *source); +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) +int +curl_dogetaddrinfo(const char *hostname, + const char *service, + const struct addrinfo *hints, + struct addrinfo **result, + int line, const char *source); +#endif + +#endif /* HEADER_CURL_ADDRINFO_H */ diff --git a/libcurl/src/lib/curl_base64.h b/libcurl/src/lib/curl_base64.h new file mode 100644 index 0000000..c40b245 --- /dev/null +++ b/libcurl/src/lib/curl_base64.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_BASE64_H +#define HEADER_CURL_BASE64_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURL_STATIC CURLcode Curl_base64_encode(struct SessionHandle *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen); +CURL_STATIC CURLcode Curl_base64url_encode(struct SessionHandle *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen); + +CURL_STATIC CURLcode Curl_base64_decode(const char *src, + unsigned char **outptr, size_t *outlen); + +#endif /* HEADER_CURL_BASE64_H */ diff --git a/libcurl/src/lib/curl_config.h.cmake b/libcurl/src/lib/curl_config.h.cmake new file mode 100644 index 0000000..f60f79f --- /dev/null +++ b/libcurl/src/lib/curl_config.h.cmake @@ -0,0 +1,952 @@ +/* lib/curl_config.h.in. Generated somehow by cmake. */ + +/* when building libcurl itself */ +#cmakedefine BUILDING_LIBCURL 1 + +/* Location of default ca bundle */ +#cmakedefine CURL_CA_BUNDLE ${CURL_CA_BUNDLE} + +/* Location of default ca path */ +#cmakedefine CURL_CA_PATH ${CURL_CA_PATH} + +/* to disable cookies support */ +#cmakedefine CURL_DISABLE_COOKIES 1 + +/* to disable cryptographic authentication */ +#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1 + +/* to disable DICT */ +#cmakedefine CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#cmakedefine CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#cmakedefine CURL_DISABLE_FTP 1 + +/* to disable HTTP */ +#cmakedefine CURL_DISABLE_HTTP 1 + +/* to disable LDAP */ +#cmakedefine CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#cmakedefine CURL_DISABLE_LDAPS 1 + +/* to disable proxies */ +#cmakedefine CURL_DISABLE_PROXY 1 + +/* to disable TELNET */ +#cmakedefine CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#cmakedefine CURL_DISABLE_TFTP 1 + +/* to disable verbose strings */ +#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1 + +/* to make a symbol visible */ +#cmakedefine CURL_EXTERN_SYMBOL 1 +/* Ensure using CURL_EXTERN_SYMBOL is possible */ +#ifndef CURL_EXTERN_SYMBOL +#define CURL_EXTERN_SYMBOL +#endif + +/* Use Windows LDAP implementation */ +#cmakedefine USE_WIN32_LDAP 1 + +/* when not building a shared library */ +#cmakedefine CURL_STATICLIB 1 + +/* Set to explicitly specify we don't want to use thread-safe functions */ +#cmakedefine DISABLED_THREADSAFE 1 + +/* your Entropy Gathering Daemon socket pathname */ +#cmakedefine EGD_SOCKET ${EGD_SOCKET} + +/* Define if you want to enable IPv6 support */ +#cmakedefine ENABLE_IPV6 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1} + +/* Define to the type of arg 1 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1} + +/* Define to the type of arg 2 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2} + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46} + +/* Define to the type of arg 7 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7} + +/* Specifies the number of arguments to getservbyport_r */ +#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS} + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#cmakedefine GETSERVBYPORT_R_BUFSIZE ${GETSERVBYPORT_R_BUFSIZE} + +/* Define to 1 if you have the alarm function. */ +#cmakedefine HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +#cmakedefine HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#cmakedefine HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the `closesocket' function. */ +#cmakedefine HAVE_CLOSESOCKET 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +#cmakedefine HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERR_H 1 + +/* Define to 1 if you have the fcntl function. */ +#cmakedefine HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#cmakedefine HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#cmakedefine HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#cmakedefine HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#cmakedefine HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#cmakedefine HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the ftruncate function. */ +#cmakedefine HAVE_FTRUNCATE 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#cmakedefine HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +#cmakedefine HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#cmakedefine HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#cmakedefine HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_5 1 + +/* gethostbyaddr_r() takes 7 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_7 1 + +/* gethostbyaddr_r() takes 8 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#cmakedefine HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +#cmakedefine HAVE_GETHOSTBYNAME_R 1 + +/* gethostbyname_r() takes 3 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_3 1 + +/* gethostbyname_r() takes 5 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_5 1 + +/* gethostbyname_r() takes 6 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_6 1 + +/* Define to 1 if you have the gethostname function. */ +#cmakedefine HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#cmakedefine HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#cmakedefine HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +#cmakedefine HAVE_GETPASS_R 1 + +/* Define to 1 if you have the `getppid' function. */ +#cmakedefine HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#cmakedefine HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#cmakedefine HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#cmakedefine HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +#cmakedefine HAVE_GETSERVBYPORT_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +#cmakedefine HAVE_GLIBC_STRERROR_R 1 + +/* Define to 1 if you have a working gmtime_r function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +#cmakedefine HAVE_GSSAPI 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_GENERIC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_KRB5_H 1 + +/* if you have the GNU gssapi libraries */ +#cmakedefine HAVE_GSSGNU 1 + +/* if you have the Heimdal gssapi libraries */ +#cmakedefine HAVE_GSSHEIMDAL 1 + +/* if you have the MIT gssapi libraries */ +#cmakedefine HAVE_GSSMIT 1 + +/* Define to 1 if you have the `idna_strerror' function. */ +#cmakedefine HAVE_IDNA_STRERROR 1 + +/* Define to 1 if you have the `idn_free' function. */ +#cmakedefine HAVE_IDN_FREE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IDN_FREE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#cmakedefine HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +#cmakedefine HAVE_INET_NTOA_R 1 + +/* inet_ntoa_r() takes 2 args */ +#cmakedefine HAVE_INET_NTOA_R_2 1 + +/* inet_ntoa_r() takes 3 args */ +#cmakedefine HAVE_INET_NTOA_R_3 1 + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#cmakedefine HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#cmakedefine HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#cmakedefine HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +#cmakedefine HAVE_IOCTLSOCKET 1 + +/* Define to 1 if you have the IoctlSocket camel case function. */ +#cmakedefine HAVE_IOCTLSOCKET_CAMEL 1 + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +#cmakedefine HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1 + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +#cmakedefine HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#cmakedefine HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#cmakedefine HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IO_H 1 + +/* if you have the Kerberos4 libraries (including -ldes) */ +#cmakedefine HAVE_KRB4 1 + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_KRB_H 1 + +/* Define to 1 if you have the lber.h header file. */ +#cmakedefine HAVE_LBER_H 1 + +/* Define to 1 if you have the ldapssl.h header file. */ +#cmakedefine HAVE_LDAPSSL_H 1 + +/* Define to 1 if you have the ldap.h header file. */ +#cmakedefine HAVE_LDAP_H 1 + +/* Use LDAPS implementation */ +#cmakedefine HAVE_LDAP_SSL 1 + +/* Define to 1 if you have the ldap_ssl.h header file. */ +#cmakedefine HAVE_LDAP_SSL_H 1 + +/* Define to 1 if you have the `ldap_url_parse' function. */ +#cmakedefine HAVE_LDAP_URL_PARSE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +#cmakedefine HAVE_LIBIDN 1 + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#cmakedefine HAVE_LIBRESOLV 1 + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +#cmakedefine HAVE_LIBRESOLVE 1 + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#cmakedefine HAVE_LIBSOCKET 1 + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +#cmakedefine HAVE_LIBSSH2 1 + +/* Define to 1 if libssh2 provides `libssh2_version'. */ +#cmakedefine HAVE_LIBSSH2_VERSION 1 + +/* Define to 1 if libssh2 provides `libssh2_init'. */ +#cmakedefine HAVE_LIBSSH2_INIT 1 + +/* Define to 1 if libssh2 provides `libssh2_exit'. */ +#cmakedefine HAVE_LIBSSH2_EXIT 1 + +/* Define to 1 if libssh2 provides `libssh2_scp_send64'. */ +#cmakedefine HAVE_LIBSSH2_SCP_SEND64 1 + +/* Define to 1 if libssh2 provides `libssh2_session_handshake'. */ +#cmakedefine HAVE_LIBSSH2_SESSION_HANDSHAKE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBSSH2_H 1 + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#cmakedefine HAVE_LIBSSL 1 + +/* if zlib is available */ +#cmakedefine HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#cmakedefine HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#cmakedefine HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#cmakedefine HAVE_MALLOC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#cmakedefine HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +#cmakedefine HAVE_NI_WITHSCOPEID 1 + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */ +#cmakedefine HAVE_OLD_GSSMIT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PEM_H 1 + +/* Define to 1 if you have the `perror' function. */ +#cmakedefine HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#cmakedefine HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#cmakedefine HAVE_POLL 1 + +/* If you have a fine poll */ +#cmakedefine HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#cmakedefine HAVE_POSIX_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +#cmakedefine HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +#cmakedefine HAVE_RAND_SCREEN 1 + +/* Define to 1 if you have the `RAND_status' function. */ +#cmakedefine HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the recv function. */ +#cmakedefine HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#cmakedefine HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_RSA_H 1 + +/* Define to 1 if you have the select function. */ +#cmakedefine HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#cmakedefine HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#cmakedefine HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#cmakedefine HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#cmakedefine HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#cmakedefine HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#cmakedefine HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#cmakedefine HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#cmakedefine HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#cmakedefine HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#cmakedefine HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1 + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the `socket' function. */ +#cmakedefine HAVE_SOCKET 1 + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +#cmakedefine HAVE_SSL_GET_SHUTDOWN 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#cmakedefine HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcasestr function. */ +#cmakedefine HAVE_STRCASESTR 1 + +/* Define to 1 if you have the strcmpi function. */ +#cmakedefine HAVE_STRCMPI 1 + +/* Define to 1 if you have the strdup function. */ +#cmakedefine HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#cmakedefine HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +#cmakedefine HAVE_STRICMP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the strlcat function. */ +#cmakedefine HAVE_STRLCAT 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#cmakedefine HAVE_STRLCPY 1 + +/* Define to 1 if you have the strncasecmp function. */ +#cmakedefine HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +#cmakedefine HAVE_STRNCMPI 1 + +/* Define to 1 if you have the strnicmp function. */ +#cmakedefine HAVE_STRNICMP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STROPTS_H 1 + +/* Define to 1 if you have the strstr function. */ +#cmakedefine HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#cmakedefine HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#cmakedefine HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#cmakedefine HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TLD_H 1 + +/* Define to 1 if you have the `tld_strerror' function. */ +#cmakedefine HAVE_TLD_STRERROR 1 + +/* Define to 1 if you have the `uname' function. */ +#cmakedefine HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#cmakedefine HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#cmakedefine HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#cmakedefine HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +#cmakedefine HAVE_WINBER_H 1 + +/* Define to 1 if you have the windows.h header file. */ +#cmakedefine HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the winldap.h header file. */ +#cmakedefine HAVE_WINLDAP_H 1 + +/* Define to 1 if you have the winsock2.h header file. */ +#cmakedefine HAVE_WINSOCK2_H 1 + +/* Define to 1 if you have the winsock.h header file. */ +#cmakedefine HAVE_WINSOCK_H 1 + +/* Define this symbol if your OS supports changing the contents of argv */ +#cmakedefine HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#cmakedefine HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +#cmakedefine HAVE_WS2TCPIP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_X509_H 1 + +/* Define if you have the header file. */ +#cmakedefine HAVE_PROCESS_H 1 + +/* if you have the zlib.h header file */ +#cmakedefine HAVE_ZLIB_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#cmakedefine LT_OBJDIR ${LT_OBJDIR} + +/* If you lack a fine basename() prototype */ +#cmakedefine NEED_BASENAME_PROTO 1 + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +#cmakedefine NEED_LBER_H 1 + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +#cmakedefine NEED_MALLOC_H 1 + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +#cmakedefine NEED_REENTRANT 1 + +/* cpu-machine-OS */ +#cmakedefine OS ${OS} + +/* Name of package */ +#cmakedefine PACKAGE ${PACKAGE} + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT} + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME ${PACKAGE_NAME} + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING ${PACKAGE_STRING} + +/* Define to the one symbol short name of this package. */ +#cmakedefine PACKAGE_TARNAME ${PACKAGE_TARNAME} + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION} + +/* a suitable file to read random data from */ +#cmakedefine RANDOM_FILE "${RANDOM_FILE}" + +/* Define to the type of arg 1 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG1 ${RECVFROM_TYPE_ARG1} + +/* Define to the type pointed by arg 2 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG2 ${RECVFROM_TYPE_ARG2} + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG3 ${RECVFROM_TYPE_ARG3} + +/* Define to the type of arg 4 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG4 ${RECVFROM_TYPE_ARG4} + +/* Define to the type pointed by arg 5 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG5 ${RECVFROM_TYPE_ARG5} + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG5_IS_VOID 1 + +/* Define to the type pointed by arg 6 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG6 ${RECVFROM_TYPE_ARG6} + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG6_IS_VOID 1 + +/* Define to the function return type for recvfrom. */ +#cmakedefine RECVFROM_TYPE_RETV ${RECVFROM_TYPE_RETV} + +/* Define to the type of arg 1 for recv. */ +#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1} + +/* Define to the type of arg 2 for recv. */ +#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2} + +/* Define to the type of arg 3 for recv. */ +#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3} + +/* Define to the type of arg 4 for recv. */ +#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4} + +/* Define to the function return type for recv. */ +#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV} + +/* Define as the return type of signal handlers (`int' or `void'). */ +#cmakedefine RETSIGTYPE ${RETSIGTYPE} + +/* Define to the type qualifier of arg 5 for select. */ +#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5} + +/* Define to the type of arg 1 for select. */ +#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1} + +/* Define to the type of args 2, 3 and 4 for select. */ +#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234} + +/* Define to the type of arg 5 for select. */ +#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5} + +/* Define to the function return type for select. */ +#cmakedefine SELECT_TYPE_RETV ${SELECT_TYPE_RETV} + +/* Define to the type qualifier of arg 2 for send. */ +#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2} + +/* Define to the type of arg 1 for send. */ +#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1} + +/* Define to the type of arg 2 for send. */ +#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2} + +/* Define to the type of arg 3 for send. */ +#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3} + +/* Define to the type of arg 4 for send. */ +#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4} + +/* Define to the function return type for send. */ +#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV} + +/* The size of `int', as computed by sizeof. */ +#cmakedefine SIZEOF_INT ${SIZEOF_INT} + +/* The size of `short', as computed by sizeof. */ +#cmakedefine SIZEOF_SHORT ${SIZEOF_SHORT} + +/* The size of `long', as computed by sizeof. */ +#cmakedefine SIZEOF_LONG ${SIZEOF_LONG} + +/* The size of `off_t', as computed by sizeof. */ +#cmakedefine SIZEOF_OFF_T ${SIZEOF_OFF_T} + +/* The size of `size_t', as computed by sizeof. */ +#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T} + +/* The size of `time_t', as computed by sizeof. */ +#cmakedefine SIZEOF_TIME_T ${SIZEOF_TIME_T} + +/* The size of `void*', as computed by sizeof. */ +#cmakedefine SIZEOF_VOIDP ${SIZEOF_VOIDP} + +/* Define to 1 if you have the ANSI C header files. */ +#cmakedefine STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#cmakedefine STRERROR_R_TYPE_ARG3 ${STRERROR_R_TYPE_ARG3} + +/* Define to 1 if you can safely include both and . */ +#cmakedefine TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable c-ares support */ +#cmakedefine USE_ARES 1 + +/* Define to disable non-blocking sockets. */ +#cmakedefine USE_BLOCKING_SOCKETS 1 + +/* if GnuTLS is enabled */ +#cmakedefine USE_GNUTLS 1 + +/* if PolarSSL is enabled */ +#cmakedefine USE_POLARSSL 1 + +/* if libSSH2 is in use */ +#cmakedefine USE_LIBSSH2 1 + +/* If you want to build curl with the built-in manual */ +#cmakedefine USE_MANUAL 1 + +/* if NSS is enabled */ +#cmakedefine USE_NSS 1 + +/* if you want to use OpenLDAP code instead of legacy ldap implementation */ +#cmakedefine USE_OPENLDAP 1 + +/* if OpenSSL is in use */ +#cmakedefine USE_OPENSSL 1 + +/* Define to 1 if you are building a Windows target without large file + support. */ +#cmakedefine USE_WIN32_LARGE_FILES 1 + +/* to enable SSPI support */ +#cmakedefine USE_WINDOWS_SSPI 1 + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +#cmakedefine USE_YASSLEMUL 1 + +/* Version number of package */ +#cmakedefine VERSION ${VERSION} + +/* Define to avoid automatic inclusion of winsock.h */ +#cmakedefine WIN32_LEAN_AND_MEAN 1 + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} + +/* Define for large files, on AIX-style hosts. */ +#cmakedefine _LARGE_FILES ${_LARGE_FILES} + +/* define this if you need it to compile thread-safe code */ +#cmakedefine _THREAD_SAFE ${_THREAD_SAFE} + +/* Define to empty if `const' does not conform to ANSI C. */ +#cmakedefine const ${const} + +/* Type to use in place of in_addr_t when system does not provide it. */ +#cmakedefine in_addr_t ${in_addr_t} + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `unsigned int' if does not define. */ +#cmakedefine size_t ${size_t} + +/* the signed version of size_t */ +#cmakedefine ssize_t ${ssize_t} diff --git a/libcurl/src/lib/curl_config.h.in b/libcurl/src/lib/curl_config.h.in new file mode 100644 index 0000000..feb582e --- /dev/null +++ b/libcurl/src/lib/curl_config.h.in @@ -0,0 +1,1024 @@ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +#undef CURL_CA_BUNDLE + +/* Location of default ca path */ +#undef CURL_CA_PATH + +/* to disable cookies support */ +#undef CURL_DISABLE_COOKIES + +/* to disable cryptographic authentication */ +#undef CURL_DISABLE_CRYPTO_AUTH + +/* to disable DICT */ +#undef CURL_DISABLE_DICT + +/* to disable FILE */ +#undef CURL_DISABLE_FILE + +/* to disable FTP */ +#undef CURL_DISABLE_FTP + +/* to disable Gopher */ +#undef CURL_DISABLE_GOPHER + +/* to disable HTTP */ +#undef CURL_DISABLE_HTTP + +/* to disable IMAP */ +#undef CURL_DISABLE_IMAP + +/* to disable LDAP */ +#undef CURL_DISABLE_LDAP + +/* to disable LDAPS */ +#undef CURL_DISABLE_LDAPS + +/* to disable --libcurl C code generation option */ +#undef CURL_DISABLE_LIBCURL_OPTION + +/* to disable POP3 */ +#undef CURL_DISABLE_POP3 + +/* to disable proxies */ +#undef CURL_DISABLE_PROXY + +/* to disable RTSP */ +#undef CURL_DISABLE_RTSP + +/* to disable SMB/CIFS */ +#undef CURL_DISABLE_SMB + +/* to disable SMTP */ +#undef CURL_DISABLE_SMTP + +/* to disable TELNET */ +#undef CURL_DISABLE_TELNET + +/* to disable TFTP */ +#undef CURL_DISABLE_TFTP + +/* to disable TLS-SRP authentication */ +#undef CURL_DISABLE_TLS_SRP + +/* to disable verbose strings */ +#undef CURL_DISABLE_VERBOSE_STRINGS + +/* Definition to make a library symbol externally visible. */ +#undef CURL_EXTERN_SYMBOL + +/* your Entropy Gathering Daemon socket pathname */ +#undef EGD_SOCKET + +/* Define if you want to enable IPv6 support */ +#undef ENABLE_IPV6 + +/* Define to the type of arg 2 for gethostname. */ +#undef GETHOSTNAME_TYPE_ARG2 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#undef GETNAMEINFO_QUAL_ARG1 + +/* Define to the type of arg 1 for getnameinfo. */ +#undef GETNAMEINFO_TYPE_ARG1 + +/* Define to the type of arg 2 for getnameinfo. */ +#undef GETNAMEINFO_TYPE_ARG2 + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#undef GETNAMEINFO_TYPE_ARG46 + +/* Define to the type of arg 7 for getnameinfo. */ +#undef GETNAMEINFO_TYPE_ARG7 + +/* Specifies the number of arguments to getservbyport_r */ +#undef GETSERVBYPORT_R_ARGS + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#undef GETSERVBYPORT_R_BUFSIZE + +/* Define to 1 if you have the alarm function. */ +#undef HAVE_ALARM + +/* Define to 1 if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_TFTP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the basename function. */ +#undef HAVE_BASENAME + +/* Define to 1 if bool is an available type. */ +#undef HAVE_BOOL_T + +/* Define to 1 if using BoringSSL. */ +#undef HAVE_BORINGSSL + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#undef HAVE_CLOCK_GETTIME_MONOTONIC + +/* Define to 1 if you have the closesocket function. */ +#undef HAVE_CLOSESOCKET + +/* Define to 1 if you have the CloseSocket camel case function. */ +#undef HAVE_CLOSESOCKET_CAMEL + +/* Define to 1 if you have the connect function. */ +#undef HAVE_CONNECT + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRYPTO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_CYASSL_ERROR_SSL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_CYASSL_OPTIONS_H + +/* Define to 1 if you have the `DES_set_odd_parity' function. */ +#undef HAVE_DES_SET_ODD_PARITY + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +#undef HAVE_ENGINE_CLEANUP + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +#undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERR_H + +/* Define to 1 if you have the fcntl function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#undef HAVE_FCNTL_O_NONBLOCK + +/* Define to 1 if you have the fdopen function. */ +#undef HAVE_FDOPEN + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the freeaddrinfo function. */ +#undef HAVE_FREEADDRINFO + +/* Define to 1 if you have the freeifaddrs function. */ +#undef HAVE_FREEIFADDRS + +/* Define to 1 if you have the fsetxattr function. */ +#undef HAVE_FSETXATTR + +/* fsetxattr() takes 5 args */ +#undef HAVE_FSETXATTR_5 + +/* fsetxattr() takes 6 args */ +#undef HAVE_FSETXATTR_6 + +/* Define to 1 if you have the ftruncate function. */ +#undef HAVE_FTRUNCATE + +/* Define to 1 if you have the gai_strerror function. */ +#undef HAVE_GAI_STRERROR + +/* Define to 1 if you have a working getaddrinfo function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#undef HAVE_GETADDRINFO_THREADSAFE + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the gethostbyaddr function. */ +#undef HAVE_GETHOSTBYADDR + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#undef HAVE_GETHOSTBYADDR_R + +/* gethostbyaddr_r() takes 5 args */ +#undef HAVE_GETHOSTBYADDR_R_5 + +/* gethostbyaddr_r() takes 7 args */ +#undef HAVE_GETHOSTBYADDR_R_7 + +/* gethostbyaddr_r() takes 8 args */ +#undef HAVE_GETHOSTBYADDR_R_8 + +/* Define to 1 if you have the gethostbyname function. */ +#undef HAVE_GETHOSTBYNAME + +/* Define to 1 if you have the gethostbyname_r function. */ +#undef HAVE_GETHOSTBYNAME_R + +/* gethostbyname_r() takes 3 args */ +#undef HAVE_GETHOSTBYNAME_R_3 + +/* gethostbyname_r() takes 5 args */ +#undef HAVE_GETHOSTBYNAME_R_5 + +/* gethostbyname_r() takes 6 args */ +#undef HAVE_GETHOSTBYNAME_R_6 + +/* Define to 1 if you have the gethostname function. */ +#undef HAVE_GETHOSTNAME + +/* Define to 1 if you have a working getifaddrs function. */ +#undef HAVE_GETIFADDRS + +/* Define to 1 if you have the getnameinfo function. */ +#undef HAVE_GETNAMEINFO + +/* Define to 1 if you have the `getpass_r' function. */ +#undef HAVE_GETPASS_R + +/* Define to 1 if you have the `getppid' function. */ +#undef HAVE_GETPPID + +/* Define to 1 if you have the `getprotobyname' function. */ +#undef HAVE_GETPROTOBYNAME + +/* Define to 1 if you have the `getpwuid' function. */ +#undef HAVE_GETPWUID + +/* Define to 1 if you have the `getpwuid_r' function. */ +#undef HAVE_GETPWUID_R + +/* Define to 1 if you have the `getrlimit' function. */ +#undef HAVE_GETRLIMIT + +/* Define to 1 if you have the getservbyport_r function. */ +#undef HAVE_GETSERVBYPORT_R + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +#undef HAVE_GLIBC_STRERROR_R + +/* Define to 1 if you have a working gmtime_r function. */ +#undef HAVE_GMTIME_R + +/* if you have the function gnutls_srp_verifier */ +#undef HAVE_GNUTLS_SRP + +/* if you have GSS-API libraries */ +#undef HAVE_GSSAPI + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_GENERIC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_KRB5_H + +/* if you have GNU GSS */ +#undef HAVE_GSSGNU + +/* if you have Heimdal */ +#undef HAVE_GSSHEIMDAL + +/* if you have MIT Kerberos */ +#undef HAVE_GSSMIT + +/* Define to 1 if you have the `idna_strerror' function. */ +#undef HAVE_IDNA_STRERROR + +/* Define to 1 if you have the `idn_free' function. */ +#undef HAVE_IDN_FREE + +/* Define to 1 if you have the header file. */ +#undef HAVE_IDN_FREE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_IFADDRS_H + +/* Define to 1 if you have the `if_nametoindex' function. */ +#undef HAVE_IF_NAMETOINDEX + +/* Define to 1 if you have the `inet_addr' function. */ +#undef HAVE_INET_ADDR + +/* Define to 1 if you have the inet_ntoa_r function. */ +#undef HAVE_INET_NTOA_R + +/* inet_ntoa_r() takes 2 args */ +#undef HAVE_INET_NTOA_R_2 + +/* inet_ntoa_r() takes 3 args */ +#undef HAVE_INET_NTOA_R_3 + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the ioctl function. */ +#undef HAVE_IOCTL + +/* Define to 1 if you have the ioctlsocket function. */ +#undef HAVE_IOCTLSOCKET + +/* Define to 1 if you have the IoctlSocket camel case function. */ +#undef HAVE_IOCTLSOCKET_CAMEL + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +#undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +#undef HAVE_IOCTLSOCKET_FIONBIO + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#undef HAVE_IOCTL_FIONBIO + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#undef HAVE_IOCTL_SIOCGIFADDR + +/* Define to 1 if you have the header file. */ +#undef HAVE_IO_H + +/* Define to 1 if you have the lber.h header file. */ +#undef HAVE_LBER_H + +/* Define to 1 if you have the ldapssl.h header file. */ +#undef HAVE_LDAPSSL_H + +/* Define to 1 if you have the ldap.h header file. */ +#undef HAVE_LDAP_H + +/* Define to 1 if you have the `ldap_init_fd' function. */ +#undef HAVE_LDAP_INIT_FD + +/* Use LDAPS implementation */ +#undef HAVE_LDAP_SSL + +/* Define to 1 if you have the ldap_ssl.h header file. */ +#undef HAVE_LDAP_SSL_H + +/* Define to 1 if you have the `ldap_url_parse' function. */ +#undef HAVE_LDAP_URL_PARSE + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H + +/* Define to 1 if you have the `idn' library (-lidn). */ +#undef HAVE_LIBIDN + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +#undef HAVE_LIBRESOLVE + +/* Define to 1 if using libressl. */ +#undef HAVE_LIBRESSL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBRTMP_RTMP_H + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +#undef HAVE_LIBSSH2 + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBSSH2_H + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* if zlib is available */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* if your compiler supports LL */ +#undef HAVE_LL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have a working localtime_r function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#undef HAVE_LONGLONG + +/* Define to 1 if you have the malloc.h header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the memory.h header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the memrchr function or macro. */ +#undef HAVE_MEMRCHR + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#undef HAVE_MSG_NOSIGNAL + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NGHTTP2_NGHTTP2_H + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +#undef HAVE_NI_WITHSCOPEID + +/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +#undef HAVE_OLD_GSSMIT + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_CRYPTO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ENGINE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_PKCS12_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* if you have the function SRP_Calc_client_key */ +#undef HAVE_OPENSSL_SRP + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_X509_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PEM_H + +/* Define to 1 if you have the `perror' function. */ +#undef HAVE_PERROR + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Define to 1 if you have a working poll function. */ +#undef HAVE_POLL + +/* If you have a fine poll */ +#undef HAVE_POLL_FINE + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#undef HAVE_POSIX_STRERROR_R + +/* if you have */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define to 1 if you have the `RAND_egd' function. */ +#undef HAVE_RAND_EGD + +/* Define to 1 if you have the `RAND_screen' function. */ +#undef HAVE_RAND_SCREEN + +/* Define to 1 if you have the `RAND_status' function. */ +#undef HAVE_RAND_STATUS + +/* Define to 1 if you have the recv function. */ +#undef HAVE_RECV + +/* Define to 1 if you have the header file. */ +#undef HAVE_RSA_H + +/* Define to 1 if you have the select function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the send function. */ +#undef HAVE_SEND + +/* Define to 1 if you have the header file. */ +#undef HAVE_SETJMP_H + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `setmode' function. */ +#undef HAVE_SETMODE + +/* Define to 1 if you have the `setrlimit' function. */ +#undef HAVE_SETRLIMIT + +/* Define to 1 if you have the setsockopt function. */ +#undef HAVE_SETSOCKOPT + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +#undef HAVE_SETSOCKOPT_SO_NONBLOCK + +/* Define to 1 if you have the header file. */ +#undef HAVE_SGTTY_H + +/* Define to 1 if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the siginterrupt function. */ +#undef HAVE_SIGINTERRUPT + +/* Define to 1 if you have the signal function. */ +#undef HAVE_SIGNAL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#undef HAVE_SIGSETJMP + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#undef HAVE_SIG_ATOMIC_T + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +#undef HAVE_SIG_ATOMIC_T_VOLATILE + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + +/* Define to 1 if you have the socket function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the socketpair function. */ +#undef HAVE_SOCKETPAIR + +/* Define to 1 if you have the header file. */ +#undef HAVE_SOCKET_H + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +#undef HAVE_SSLV2_CLIENT_METHOD + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +#undef HAVE_SSL_GET_SHUTDOWN + +/* Define to 1 if you have the header file. */ +#undef HAVE_SSL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the strcmpi function. */ +#undef HAVE_STRCMPI + +/* Define to 1 if you have the strdup function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the strerror_r function. */ +#undef HAVE_STRERROR_R + +/* Define to 1 if you have the stricmp function. */ +#undef HAVE_STRICMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the strncasecmp function. */ +#undef HAVE_STRNCASECMP + +/* Define to 1 if you have the strncmpi function. */ +#undef HAVE_STRNCMPI + +/* Define to 1 if you have the strnicmp function. */ +#undef HAVE_STRNICMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STROPTS_H + +/* Define to 1 if you have the strstr function. */ +#undef HAVE_STRSTR + +/* Define to 1 if you have the strtok_r function. */ +#undef HAVE_STRTOK_R + +/* Define to 1 if you have the strtoll function. */ +#undef HAVE_STRTOLL + +/* if struct sockaddr_storage is defined */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define to 1 if you have the timeval struct. */ +#undef HAVE_STRUCT_TIMEVAL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_POLL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_XATTR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TLD_H + +/* Define to 1 if you have the `tld_strerror' function. */ +#undef HAVE_TLD_STRERROR + +/* Define to 1 if you have the `uname' function. */ +#undef HAVE_UNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `utime' function. */ +#undef HAVE_UTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#undef HAVE_VARIADIC_MACROS_C99 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#undef HAVE_VARIADIC_MACROS_GCC + +/* Define to 1 if you have the winber.h header file. */ +#undef HAVE_WINBER_H + +/* Define to 1 if you have the windows.h header file. */ +#undef HAVE_WINDOWS_H + +/* Define to 1 if you have the winldap.h header file. */ +#undef HAVE_WINLDAP_H + +/* Define to 1 if you have the winsock2.h header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to 1 if you have the winsock.h header file. */ +#undef HAVE_WINSOCK_H + +/* Define this symbol if your OS supports changing the contents of argv */ +#undef HAVE_WRITABLE_ARGV + +/* Define to 1 if you have the writev function. */ +#undef HAVE_WRITEV + +/* Define to 1 if you have the ws2tcpip.h header file. */ +#undef HAVE_WS2TCPIP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_X509_H + +/* if you have the zlib.h header file */ +#undef HAVE_ZLIB_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +#undef NEED_LBER_H + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +#undef NEED_MALLOC_H + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +#undef NEED_MEMORY_H + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +#undef NEED_REENTRANT + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +#undef NEED_THREAD_SAFE + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +#undef NTLM_WB_ENABLED + +/* Define absolute filename for winbind's ntlm_auth helper. */ +#undef NTLM_WB_FILE + +/* cpu-machine-OS */ +#undef OS + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* a suitable file to read random data from */ +#undef RANDOM_FILE + +/* Define to the type of arg 1 for recv. */ +#undef RECV_TYPE_ARG1 + +/* Define to the type of arg 2 for recv. */ +#undef RECV_TYPE_ARG2 + +/* Define to the type of arg 3 for recv. */ +#undef RECV_TYPE_ARG3 + +/* Define to the type of arg 4 for recv. */ +#undef RECV_TYPE_ARG4 + +/* Define to the function return type for recv. */ +#undef RECV_TYPE_RETV + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to the type qualifier of arg 5 for select. */ +#undef SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#undef SELECT_TYPE_ARG1 + +/* Define to the type of args 2, 3 and 4 for select. */ +#undef SELECT_TYPE_ARG234 + +/* Define to the type of arg 5 for select. */ +#undef SELECT_TYPE_ARG5 + +/* Define to the function return type for select. */ +#undef SELECT_TYPE_RETV + +/* Define to the type qualifier of arg 2 for send. */ +#undef SEND_QUAL_ARG2 + +/* Define to the type of arg 1 for send. */ +#undef SEND_TYPE_ARG1 + +/* Define to the type of arg 2 for send. */ +#undef SEND_TYPE_ARG2 + +/* Define to the type of arg 3 for send. */ +#undef SEND_TYPE_ARG3 + +/* Define to the type of arg 4 for send. */ +#undef SEND_TYPE_ARG4 + +/* Define to the function return type for send. */ +#undef SEND_TYPE_RETV + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* The size of `off_t', as computed by sizeof. */ +#undef SIZEOF_OFF_T + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* The size of `time_t', as computed by sizeof. */ +#undef SIZEOF_TIME_T + +/* The size of `void*', as computed by sizeof. */ +#undef SIZEOF_VOIDP + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to the type of arg 3 for strerror_r. */ +#undef STRERROR_R_TYPE_ARG3 + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to enable c-ares support */ +#undef USE_ARES + +/* if axTLS is enabled */ +#undef USE_AXTLS + +/* if CyaSSL is enabled */ +#undef USE_CYASSL + +/* to enable iOS/Mac OS X native SSL/TLS support */ +#undef USE_DARWINSSL + +/* if GnuTLS is enabled */ +#undef USE_GNUTLS + +/* if GnuTLS uses nettle as crypto backend */ +#undef USE_GNUTLS_NETTLE + +/* if librtmp is in use */ +#undef USE_LIBRTMP + +/* if libSSH2 is in use */ +#undef USE_LIBSSH2 + +/* If you want to build curl with the built-in manual */ +#undef USE_MANUAL + +/* Define to enable metalink support */ +#undef USE_METALINK + +/* if nghttp2 is in use */ +#undef USE_NGHTTP2 + +/* if NSS is enabled */ +#undef USE_NSS + +/* Use OpenLDAP-specific code */ +#undef USE_OPENLDAP + +/* if OpenSSL is in use */ +#undef USE_OPENSSL + +/* if PolarSSL is enabled */ +#undef USE_POLARSSL + +/* to enable Windows native SSL/TLS support */ +#undef USE_SCHANNEL + +/* if you want POSIX threaded DNS lookup */ +#undef USE_THREADS_POSIX + +/* Use TLS-SRP authentication */ +#undef USE_TLS_SRP + +/* Use Unix domain sockets */ +#undef USE_UNIX_SOCKETS + +/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ +#undef USE_WIN32_IDN + +/* Define to 1 if you are building a Windows target with large file support. + */ +#undef USE_WIN32_LARGE_FILES + +/* Use Windows LDAP implementation */ +#undef USE_WIN32_LDAP + +/* Define to 1 if you are building a Windows target without large file + support. */ +#undef USE_WIN32_SMALL_FILES + +/* to enable SSPI support */ +#undef USE_WINDOWS_SSPI + +/* Version number of package */ +#undef VERSION + +/* Define to 1 to provide own prototypes. */ +#undef WANT_IDN_PROTOTYPES + +/* Define to avoid automatic inclusion of winsock.h */ +#undef WIN32_LEAN_AND_MEAN + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Type to use in place of in_addr_t when system does not provide it. */ +#undef in_addr_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* the signed version of size_t */ +#undef ssize_t diff --git a/libcurl/src/lib/curl_des.c b/libcurl/src/lib/curl_des.c new file mode 100644 index 0000000..42c1df9 --- /dev/null +++ b/libcurl/src/lib/curl_des.c @@ -0,0 +1,63 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && (!defined(USE_OPENSSL) || defined(HAVE_BORINGSSL)) + +#include "curl_des.h" + +/* + * Curl_des_set_odd_parity() + * + * This is used to apply odd parity to the given byte array. It is typically + * used by when a cryptography engines doesn't have it's own version. + * + * The function is a port of the Java based oddParity() function over at: + * + * http://davenport.sourceforge.net/ntlm.html + * + * Parameters: + * + * bytes [in/out] - The data whose parity bits are to be adjusted for + * odd parity. + * len [out] - The length of the data. + */ +void Curl_des_set_odd_parity(unsigned char *bytes, size_t len) +{ + size_t i; + + for(i = 0; i < len; i++) { + unsigned char b = bytes[i]; + + bool needs_parity = (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ + (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ + (b >> 1)) & 0x01) == 0; + + if(needs_parity) + bytes[i] |= 0x01; + else + bytes[i] &= 0xfe; + } +} + +#endif /* USE_NTLM && (!USE_OPENSSL || HAVE_BORINGSSL) */ diff --git a/libcurl/src/lib/curl_des.h b/libcurl/src/lib/curl_des.h new file mode 100644 index 0000000..b855db4 --- /dev/null +++ b/libcurl/src/lib/curl_des.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_DES_H +#define HEADER_CURL_DES_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && (!defined(USE_OPENSSL) || defined(HAVE_BORINGSSL)) + +/* Applies odd parity to the given byte array */ +void Curl_des_set_odd_parity(unsigned char *bytes, size_t length); + +#endif /* USE_NTLM && (!USE_OPENSSL || HAVE_BORINGSSL) */ + +#endif /* HEADER_CURL_DES_H */ diff --git a/libcurl/src/lib/curl_endian.c b/libcurl/src/lib/curl_endian.c new file mode 100644 index 0000000..4279108 --- /dev/null +++ b/libcurl/src/lib/curl_endian.c @@ -0,0 +1,236 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_endian.h" + +/* + * Curl_read16_le() + * + * This function converts a 16-bit integer from the little endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 2 byte buffer. + * + * Returns the integer. + */ +CURL_STATIC unsigned short Curl_read16_le(unsigned char *buf) +{ + return (unsigned short)(((unsigned short)buf[0]) | + ((unsigned short)buf[1] << 8)); +} + +/* + * Curl_read32_le() + * + * This function converts a 32-bit integer from the little endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 4 byte buffer. + * + * Returns the integer. + */ +CURL_STATIC unsigned int Curl_read32_le(unsigned char *buf) +{ + return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | + ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); +} + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* + * Curl_read64_le() + * + * This function converts a 64-bit integer from the little endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 8 byte buffer. + * + * Returns the integer. + */ +#if defined(HAVE_LONGLONG) +CURL_STATIC unsigned long long Curl_read64_le(unsigned char *buf) +{ + return ((unsigned long long)buf[0]) | + ((unsigned long long)buf[1] << 8) | + ((unsigned long long)buf[2] << 16) | + ((unsigned long long)buf[3] << 24) | + ((unsigned long long)buf[4] << 32) | + ((unsigned long long)buf[5] << 40) | + ((unsigned long long)buf[6] << 48) | + ((unsigned long long)buf[7] << 56); +} +#else +CURL_STATIC unsigned __int64 Curl_read64_le(unsigned char *buf) +{ + return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) | + ((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) | + ((unsigned __int64)buf[4] << 32) | ((unsigned __int64)buf[5] << 40) | + ((unsigned __int64)buf[6] << 48) | ((unsigned __int64)buf[7] << 56); +} +#endif + +#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ + +/* + * Curl_read16_be() + * + * This function converts a 16-bit integer from the big endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 2 byte buffer. + * + * Returns the integer. + */ +CURL_STATIC unsigned short Curl_read16_be(unsigned char *buf) +{ + return (unsigned short)(((unsigned short)buf[0] << 8) | + ((unsigned short)buf[1])); +} + +/* + * Curl_read32_be() + * + * This function converts a 32-bit integer from the big endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 4 byte buffer. + * + * Returns the integer. + */ +CURL_STATIC unsigned int Curl_read32_be(unsigned char *buf) +{ + return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) | + ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]); +} + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* + * Curl_read64_be() + * + * This function converts a 64-bit integer from the big endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 8 byte buffer. + * + * Returns the integer. + */ +#if defined(HAVE_LONGLONG) +CURL_STATIC unsigned long long Curl_read64_be(unsigned char *buf) +{ + return ((unsigned long long)buf[0] << 56) | + ((unsigned long long)buf[1] << 48) | + ((unsigned long long)buf[2] << 40) | + ((unsigned long long)buf[3] << 32) | + ((unsigned long long)buf[4] << 24) | + ((unsigned long long)buf[5] << 16) | + ((unsigned long long)buf[6] << 8) | + ((unsigned long long)buf[7]); +} +#else +CURL_STATIC unsigned __int64 Curl_read64_be(unsigned char *buf) +{ + return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) | + ((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) | + ((unsigned __int64)buf[4] << 24) | ((unsigned __int64)buf[5] << 16) | + ((unsigned __int64)buf[6] << 8) | ((unsigned __int64)buf[7]); +} +#endif + +#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ + +/* + * Curl_write16_le() + * + * This function converts a 16-bit integer from the native endian format, + * to little endian format ready for sending down the wire. + * + * Parameters: + * + * value [in] - The 16-bit integer value. + * buffer [in] - A pointer to the output buffer. + */ +CURL_STATIC void Curl_write16_le(const short value, unsigned char *buffer) +{ + buffer[0] = (char)(value & 0x00FF); + buffer[1] = (char)((value & 0xFF00) >> 8); +} + +/* + * Curl_write32_le() + * + * This function converts a 32-bit integer from the native endian format, + * to little endian format ready for sending down the wire. + * + * Parameters: + * + * value [in] - The 32-bit integer value. + * buffer [in] - A pointer to the output buffer. + */ +CURL_STATIC void Curl_write32_le(const int value, unsigned char *buffer) +{ + buffer[0] = (char)(value & 0x000000FF); + buffer[1] = (char)((value & 0x0000FF00) >> 8); + buffer[2] = (char)((value & 0x00FF0000) >> 16); + buffer[3] = (char)((value & 0xFF000000) >> 24); +} + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* + * Curl_write64_le() + * + * This function converts a 64-bit integer from the native endian format, + * to little endian format ready for sending down the wire. + * + * Parameters: + * + * value [in] - The 64-bit integer value. + * buffer [in] - A pointer to the output buffer. + */ +#if defined(HAVE_LONGLONG) +CURL_STATIC void Curl_write64_le(const long long value, unsigned char *buffer) +#else +CURL_STATIC void Curl_write64_le(const __int64 value, unsigned char *buffer) +#endif +{ + Curl_write32_le((int)value, buffer); + Curl_write32_le((int)(value >> 32), buffer + 4); +} +#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ diff --git a/libcurl/src/lib/curl_endian.h b/libcurl/src/lib/curl_endian.h new file mode 100644 index 0000000..3246752 --- /dev/null +++ b/libcurl/src/lib/curl_endian.h @@ -0,0 +1,70 @@ +#ifndef HEADER_CURL_ENDIAN_H +#define HEADER_CURL_ENDIAN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Converts a 16-bit integer from little endian */ +CURL_STATIC unsigned short Curl_read16_le(unsigned char *buf); + +/* Converts a 32-bit integer from little endian */ +CURL_STATIC unsigned int Curl_read32_le(unsigned char *buf); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* Converts a 64-bit integer from little endian */ +#if defined(HAVE_LONGLONG) +CURL_STATIC unsigned long long Curl_read64_le(unsigned char *buf); +#else +CURL_STATIC unsigned __int64 Curl_read64_le(unsigned char *buf); +#endif +#endif + +/* Converts a 16-bit integer from big endian */ +CURL_STATIC unsigned short Curl_read16_be(unsigned char *buf); + +/* Converts a 32-bit integer from big endian */ +CURL_STATIC unsigned int Curl_read32_be(unsigned char *buf); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* Converts a 64-bit integer from big endian */ +#if defined(HAVE_LONGLONG) +CURL_STATIC unsigned long long Curl_read64_be(unsigned char *buf); +#else +CURL_STATIC unsigned __int64 Curl_read64_be(unsigned char *buf); +#endif +#endif + +/* Converts a 16-bit integer to little endian */ +CURL_STATIC void Curl_write16_le(const short value, unsigned char *buffer); + +/* Converts a 32-bit integer to little endian */ +CURL_STATIC void Curl_write32_le(const int value, unsigned char *buffer); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* Converts a 64-bit integer to little endian */ +#if defined(HAVE_LONGLONG) +CURL_STATIC void Curl_write64_le(const long long value, unsigned char *buffer); +#else +CURL_STATIC void Curl_write64_le(const __int64 value, unsigned char *buffer); +#endif +#endif + +#endif /* HEADER_CURL_ENDIAN_H */ diff --git a/libcurl/src/lib/curl_fnmatch.c b/libcurl/src/lib/curl_fnmatch.c new file mode 100644 index 0000000..d762e25 --- /dev/null +++ b/libcurl/src/lib/curl_fnmatch.c @@ -0,0 +1,424 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_fnmatch.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#define CURLFNM_CHARSET_LEN (sizeof(char) * 256) +#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15) + +#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN + +#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1) +#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2) +#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3) +#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4) +#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5) +#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6) +#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7) +#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8) +#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9) +#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10) + +typedef enum { + CURLFNM_LOOP_DEFAULT = 0, + CURLFNM_LOOP_BACKSLASH +} loop_state; + +typedef enum { + CURLFNM_SCHS_DEFAULT = 0, + CURLFNM_SCHS_MAYRANGE, + CURLFNM_SCHS_MAYRANGE2, + CURLFNM_SCHS_RIGHTBR, + CURLFNM_SCHS_RIGHTBRLEFTBR +} setcharset_state; + +typedef enum { + CURLFNM_PKW_INIT = 0, + CURLFNM_PKW_DDOT +} parsekey_state; + +#define SETCHARSET_OK 1 +#define SETCHARSET_FAIL 0 + +static int parsekeyword(unsigned char **pattern, unsigned char *charset) +{ + parsekey_state state = CURLFNM_PKW_INIT; +#define KEYLEN 10 + char keyword[KEYLEN] = { 0 }; + int found = FALSE; + int i; + unsigned char *p = *pattern; + for(i = 0; !found; i++) { + char c = *p++; + if(i >= KEYLEN) + return SETCHARSET_FAIL; + switch(state) { + case CURLFNM_PKW_INIT: + if(ISALPHA(c) && ISLOWER(c)) + keyword[i] = c; + else if(c == ':') + state = CURLFNM_PKW_DDOT; + else + return 0; + break; + case CURLFNM_PKW_DDOT: + if(c == ']') + found = TRUE; + else + return SETCHARSET_FAIL; + } + } +#undef KEYLEN + + *pattern = p; /* move caller's pattern pointer */ + if(strcmp(keyword, "digit") == 0) + charset[CURLFNM_DIGIT] = 1; + else if(strcmp(keyword, "alnum") == 0) + charset[CURLFNM_ALNUM] = 1; + else if(strcmp(keyword, "alpha") == 0) + charset[CURLFNM_ALPHA] = 1; + else if(strcmp(keyword, "xdigit") == 0) + charset[CURLFNM_XDIGIT] = 1; + else if(strcmp(keyword, "print") == 0) + charset[CURLFNM_PRINT] = 1; + else if(strcmp(keyword, "graph") == 0) + charset[CURLFNM_GRAPH] = 1; + else if(strcmp(keyword, "space") == 0) + charset[CURLFNM_SPACE] = 1; + else if(strcmp(keyword, "blank") == 0) + charset[CURLFNM_BLANK] = 1; + else if(strcmp(keyword, "upper") == 0) + charset[CURLFNM_UPPER] = 1; + else if(strcmp(keyword, "lower") == 0) + charset[CURLFNM_LOWER] = 1; + else + return SETCHARSET_FAIL; + return SETCHARSET_OK; +} + +/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */ +static int setcharset(unsigned char **p, unsigned char *charset) +{ + setcharset_state state = CURLFNM_SCHS_DEFAULT; + unsigned char rangestart = 0; + unsigned char lastchar = 0; + bool something_found = FALSE; + unsigned char c; + for(;;) { + c = **p; + switch(state) { + case CURLFNM_SCHS_DEFAULT: + if(ISALNUM(c)) { /* ASCII value */ + rangestart = c; + charset[c] = 1; + (*p)++; + state = CURLFNM_SCHS_MAYRANGE; + something_found = TRUE; + } + else if(c == ']') { + if(something_found) + return SETCHARSET_OK; + else + something_found = TRUE; + state = CURLFNM_SCHS_RIGHTBR; + charset[c] = 1; + (*p)++; + } + else if(c == '[') { + char c2 = *((*p)+1); + if(c2 == ':') { /* there has to be a keyword */ + (*p) += 2; + if(parsekeyword(p, charset)) { + state = CURLFNM_SCHS_DEFAULT; + } + else + return SETCHARSET_FAIL; + } + else { + charset[c] = 1; + (*p)++; + } + something_found = TRUE; + } + else if(c == '?' || c == '*') { + something_found = TRUE; + charset[c] = 1; + (*p)++; + } + else if(c == '^' || c == '!') { + if(!something_found) { + if(charset[CURLFNM_NEGATE]) { + charset[c] = 1; + something_found = TRUE; + } + else + charset[CURLFNM_NEGATE] = 1; /* negate charset */ + } + else + charset[c] = 1; + (*p)++; + } + else if(c == '\\') { + c = *(++(*p)); + if(ISPRINT((c))) { + something_found = TRUE; + state = CURLFNM_SCHS_MAYRANGE; + charset[c] = 1; + rangestart = c; + (*p)++; + } + else + return SETCHARSET_FAIL; + } + else if(c == '\0') { + return SETCHARSET_FAIL; + } + else { + charset[c] = 1; + (*p)++; + something_found = TRUE; + } + break; + case CURLFNM_SCHS_MAYRANGE: + if(c == '-') { + charset[c] = 1; + (*p)++; + lastchar = '-'; + state = CURLFNM_SCHS_MAYRANGE2; + } + else if(c == '[') { + state = CURLFNM_SCHS_DEFAULT; + } + else if(ISALNUM(c)) { + charset[c] = 1; + (*p)++; + } + else if(c == '\\') { + c = *(++(*p)); + if(ISPRINT(c)) { + charset[c] = 1; + (*p)++; + } + else + return SETCHARSET_FAIL; + } + else if(c == ']') { + return SETCHARSET_OK; + } + else + return SETCHARSET_FAIL; + break; + case CURLFNM_SCHS_MAYRANGE2: + if(c == '\\') { + c = *(++(*p)); + if(!ISPRINT(c)) + return SETCHARSET_FAIL; + } + if(c == ']') { + return SETCHARSET_OK; + } + else if(c == '\\') { + c = *(++(*p)); + if(ISPRINT(c)) { + charset[c] = 1; + state = CURLFNM_SCHS_DEFAULT; + (*p)++; + } + else + return SETCHARSET_FAIL; + } + if(c >= rangestart) { + if((ISLOWER(c) && ISLOWER(rangestart)) || + (ISDIGIT(c) && ISDIGIT(rangestart)) || + (ISUPPER(c) && ISUPPER(rangestart))) { + charset[lastchar] = 0; + rangestart++; + while(rangestart++ <= c) + charset[rangestart-1] = 1; + (*p)++; + state = CURLFNM_SCHS_DEFAULT; + } + else + return SETCHARSET_FAIL; + } + break; + case CURLFNM_SCHS_RIGHTBR: + if(c == '[') { + state = CURLFNM_SCHS_RIGHTBRLEFTBR; + charset[c] = 1; + (*p)++; + } + else if(c == ']') { + return SETCHARSET_OK; + } + else if(c == '\0') { + return SETCHARSET_FAIL; + } + else if(ISPRINT(c)) { + charset[c] = 1; + (*p)++; + state = CURLFNM_SCHS_DEFAULT; + } + else + /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a + * nonsense warning 'statement not reached' at end of the fnc when + * compiling on Solaris */ + goto fail; + break; + case CURLFNM_SCHS_RIGHTBRLEFTBR: + if(c == ']') { + return SETCHARSET_OK; + } + else { + state = CURLFNM_SCHS_DEFAULT; + charset[c] = 1; + (*p)++; + } + break; + } + } +fail: + return SETCHARSET_FAIL; +} + +static int loop(const unsigned char *pattern, const unsigned char *string) +{ + loop_state state = CURLFNM_LOOP_DEFAULT; + unsigned char *p = (unsigned char *)pattern; + unsigned char *s = (unsigned char *)string; + unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 }; + int rc = 0; + + for(;;) { + switch(state) { + case CURLFNM_LOOP_DEFAULT: + if(*p == '*') { + while(*(p+1) == '*') /* eliminate multiple stars */ + p++; + if(*s == '\0' && *(p+1) == '\0') + return CURL_FNMATCH_MATCH; + rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */ + if(rc == CURL_FNMATCH_MATCH) + return CURL_FNMATCH_MATCH; + if(*s) /* let the star eat up one character */ + s++; + else + return CURL_FNMATCH_NOMATCH; + } + else if(*p == '?') { + if(ISPRINT(*s)) { + s++; + p++; + } + else if(*s == '\0') + return CURL_FNMATCH_NOMATCH; + else + return CURL_FNMATCH_FAIL; /* cannot deal with other character */ + } + else if(*p == '\0') { + if(*s == '\0') + return CURL_FNMATCH_MATCH; + else + return CURL_FNMATCH_NOMATCH; + } + else if(*p == '\\') { + state = CURLFNM_LOOP_BACKSLASH; + p++; + } + else if(*p == '[') { + unsigned char *pp = p+1; /* cannot handle with pointer to register */ + if(setcharset(&pp, charset)) { + int found = FALSE; + if(charset[(unsigned int)*s]) + found = TRUE; + else if(charset[CURLFNM_ALNUM]) + found = ISALNUM(*s); + else if(charset[CURLFNM_ALPHA]) + found = ISALPHA(*s); + else if(charset[CURLFNM_DIGIT]) + found = ISDIGIT(*s); + else if(charset[CURLFNM_XDIGIT]) + found = ISXDIGIT(*s); + else if(charset[CURLFNM_PRINT]) + found = ISPRINT(*s); + else if(charset[CURLFNM_SPACE]) + found = ISSPACE(*s); + else if(charset[CURLFNM_UPPER]) + found = ISUPPER(*s); + else if(charset[CURLFNM_LOWER]) + found = ISLOWER(*s); + else if(charset[CURLFNM_BLANK]) + found = ISBLANK(*s); + else if(charset[CURLFNM_GRAPH]) + found = ISGRAPH(*s); + + if(charset[CURLFNM_NEGATE]) + found = !found; + + if(found) { + p = pp+1; + s++; + memset(charset, 0, CURLFNM_CHSET_SIZE); + } + else + return CURL_FNMATCH_NOMATCH; + } + else + return CURL_FNMATCH_FAIL; + } + else { + if(*p++ != *s++) + return CURL_FNMATCH_NOMATCH; + } + break; + case CURLFNM_LOOP_BACKSLASH: + if(ISPRINT(*p)) { + if(*p++ == *s++) + state = CURLFNM_LOOP_DEFAULT; + else + return CURL_FNMATCH_NOMATCH; + } + else + return CURL_FNMATCH_FAIL; + break; + } + } +} + +/* + * @unittest: 1307 + */ +CURL_STATIC int Curl_fnmatch(void *ptr, const char *pattern, const char *string) +{ + (void)ptr; /* the argument is specified by the curl_fnmatch_callback + prototype, but not used by Curl_fnmatch() */ + if(!pattern || !string) { + return CURL_FNMATCH_FAIL; + } + return loop((unsigned char *)pattern, (unsigned char *)string); +} diff --git a/libcurl/src/lib/curl_fnmatch.h b/libcurl/src/lib/curl_fnmatch.h new file mode 100644 index 0000000..8e9c50a --- /dev/null +++ b/libcurl/src/lib/curl_fnmatch.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_FNMATCH_H +#define HEADER_CURL_FNMATCH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define CURL_FNMATCH_MATCH 0 +#define CURL_FNMATCH_NOMATCH 1 +#define CURL_FNMATCH_FAIL 2 + +/* default pattern matching function + * ================================= + * Implemented with recursive backtracking, if you want to use Curl_fnmatch, + * please note that there is not implemented UTF/UNICODE support. + * + * Implemented features: + * '?' notation, does not match UTF characters + * '*' can also work with UTF string + * [a-zA-Z0-9] enumeration support + * + * keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space + * and upper (use as "[[:alnum:]]") + */ +CURL_STATIC int Curl_fnmatch(void *ptr, const char *pattern, const char *string); + +#endif /* HEADER_CURL_FNMATCH_H */ diff --git a/libcurl/src/lib/curl_gethostname.c b/libcurl/src/lib/curl_gethostname.c new file mode 100644 index 0000000..2d9909d --- /dev/null +++ b/libcurl/src/lib/curl_gethostname.c @@ -0,0 +1,100 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_gethostname.h" + +/* + * Curl_gethostname() is a wrapper around gethostname() which allows + * overriding the host name that the function would normally return. + * This capability is used by the test suite to verify exact matching + * of NTLM authentication, which exercises libcurl's MD4 and DES code + * as well as by the SMTP module when a hostname is not provided. + * + * For libcurl debug enabled builds host name overriding takes place + * when environment variable CURL_GETHOSTNAME is set, using the value + * held by the variable to override returned host name. + * + * Note: The function always returns the un-qualified hostname rather + * than being provider dependent. + * + * For libcurl shared library release builds the test suite preloads + * another shared library named libhostname using the LD_PRELOAD + * mechanism which intercepts, and might override, the gethostname() + * function call. In this case a given platform must support the + * LD_PRELOAD mechanism and additionally have environment variable + * CURL_GETHOSTNAME set in order to override the returned host name. + * + * For libcurl static library release builds no overriding takes place. + */ + +CURL_STATIC int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) { + +#ifndef HAVE_GETHOSTNAME + + /* Allow compilation and return failure when unavailable */ + (void) name; + (void) namelen; + return -1; + +#else + int err; + char* dot; + +#ifdef DEBUGBUILD + + /* Override host name when environment variable CURL_GETHOSTNAME is set */ + const char *force_hostname = getenv("CURL_GETHOSTNAME"); + if(force_hostname) { + strncpy(name, force_hostname, namelen); + err = 0; + } + else { + name[0] = '\0'; + err = gethostname(name, namelen); + } + +#else /* DEBUGBUILD */ + + /* The call to system's gethostname() might get intercepted by the + libhostname library when libcurl is built as a non-debug shared + library when running the test suite. */ + name[0] = '\0'; + err = gethostname(name, namelen); + +#endif + + name[namelen - 1] = '\0'; + + if(err) + return err; + + /* Truncate domain, leave only machine name */ + dot = strchr(name, '.'); + if(dot) + *dot = '\0'; + + return 0; +#endif + +} diff --git a/libcurl/src/lib/curl_gethostname.h b/libcurl/src/lib/curl_gethostname.h new file mode 100644 index 0000000..db1083b --- /dev/null +++ b/libcurl/src/lib/curl_gethostname.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_GETHOSTNAME_H +#define HEADER_CURL_GETHOSTNAME_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Hostname buffer size */ +#define HOSTNAME_MAX 1024 + +/* This returns the local machine's un-qualified hostname */ +CURL_STATIC int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen); + +#endif /* HEADER_CURL_GETHOSTNAME_H */ diff --git a/libcurl/src/lib/curl_gssapi.c b/libcurl/src/lib/curl_gssapi.c new file mode 100644 index 0000000..3707c4d --- /dev/null +++ b/libcurl/src/lib/curl_gssapi.c @@ -0,0 +1,120 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2011 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_GSSAPI + +#include "curl_gssapi.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 }; + +CURL_STATIC OM_uint32 Curl_gss_init_sec_context( + struct SessionHandle *data, + OM_uint32 *minor_status, + gss_ctx_id_t *context, + gss_name_t target_name, + gss_OID mech_type, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_buffer_t output_token, + const bool mutual_auth, + OM_uint32 *ret_flags) +{ + OM_uint32 req_flags = GSS_C_REPLAY_FLAG; + + if(mutual_auth) + req_flags |= GSS_C_MUTUAL_FLAG; + + if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) { +#ifdef GSS_C_DELEG_POLICY_FLAG + req_flags |= GSS_C_DELEG_POLICY_FLAG; +#else + infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not " + "compiled in\n"); +#endif + } + + if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG) + req_flags |= GSS_C_DELEG_FLAG; + + return gss_init_sec_context(minor_status, + GSS_C_NO_CREDENTIAL, /* cred_handle */ + context, + target_name, + mech_type, + req_flags, + 0, /* time_req */ + input_chan_bindings, + input_token, + NULL, /* actual_mech_type */ + output_token, + ret_flags, + NULL /* time_rec */); +} + +/* + * Curl_gss_log_error() + * + * This is used to log a GSS-API error status. + * + * Parameters: + * + * data [in] - The session handle. + * status [in] - The status code. + * prefix [in] - The prefix of the log message. + */ +CURL_STATIC void Curl_gss_log_error(struct SessionHandle *data, OM_uint32 status, + const char *prefix) +{ + OM_uint32 maj_stat; + OM_uint32 min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char buf[1024]; + size_t len; + + snprintf(buf, sizeof(buf), "%s", prefix); + len = strlen(buf); + do { + maj_stat = gss_display_status(&min_stat, + status, + GSS_C_MECH_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + if(sizeof(buf) > len + status_string.length + 1) { + snprintf(buf + len, sizeof(buf) - len, + ": %s", (char*)status_string.value); + len += status_string.length; + } + gss_release_buffer(&min_stat, &status_string); + } while(!GSS_ERROR(maj_stat) && msg_ctx != 0); + + infof(data, "%s\n", buf); +} + +#endif /* HAVE_GSSAPI */ diff --git a/libcurl/src/lib/curl_gssapi.h b/libcurl/src/lib/curl_gssapi.h new file mode 100644 index 0000000..b54891e --- /dev/null +++ b/libcurl/src/lib/curl_gssapi.h @@ -0,0 +1,75 @@ +#ifndef HEADER_CURL_GSSAPI_H +#define HEADER_CURL_GSSAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2011 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +#ifdef HAVE_GSSAPI + +#ifdef HAVE_GSSGNU +# include +#elif defined HAVE_GSSMIT + /* MIT style */ +# include +# include +# include +#else + /* Heimdal-style */ +# include +#endif + +extern gss_OID_desc Curl_spnego_mech_oid; +extern gss_OID_desc Curl_krb5_mech_oid; + +/* Common method for using GSS-API */ +CURL_STATIC OM_uint32 Curl_gss_init_sec_context( + struct SessionHandle *data, + OM_uint32 *minor_status, + gss_ctx_id_t *context, + gss_name_t target_name, + gss_OID mech_type, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_buffer_t output_token, + const bool mutual_auth, + OM_uint32 *ret_flags); + +/* Helper to log a GSS-API error status */ +CURL_STATIC void Curl_gss_log_error(struct SessionHandle *data, OM_uint32 status, + const char *prefix); + +/* Provide some definitions missing in old headers */ +#ifdef HAVE_OLD_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#define NCOMPAT 1 +#endif + +/* Define our privacy and integrity protection values */ +#define GSSAUTH_P_NONE 1 +#define GSSAUTH_P_INTEGRITY 2 +#define GSSAUTH_P_PRIVACY 4 + +#endif /* HAVE_GSSAPI */ + +#endif /* HEADER_CURL_GSSAPI_H */ diff --git a/libcurl/src/lib/curl_hmac.h b/libcurl/src/lib/curl_hmac.h new file mode 100644 index 0000000..e184fdf --- /dev/null +++ b/libcurl/src/lib/curl_hmac.h @@ -0,0 +1,67 @@ +#ifndef HEADER_CURL_HMAC_H +#define HEADER_CURL_HMAC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +typedef void (* HMAC_hinit_func)(void * context); +typedef void (* HMAC_hupdate_func)(void * context, + const unsigned char * data, + unsigned int len); +typedef void (* HMAC_hfinal_func)(unsigned char * result, void * context); + + +/* Per-hash function HMAC parameters. */ + +typedef struct { + HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */ + HMAC_hupdate_func hmac_hupdate; /* Update context with data. */ + HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */ + unsigned int hmac_ctxtsize; /* Context structure size. */ + unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */ + unsigned int hmac_resultlen; /* Result length (bytes). */ +} HMAC_params; + + +/* HMAC computation context. */ + +typedef struct { + const HMAC_params * hmac_hash; /* Hash function definition. */ + void * hmac_hashctxt1; /* Hash function context 1. */ + void * hmac_hashctxt2; /* Hash function context 2. */ +} HMAC_context; + + +/* Prototypes. */ + +CURL_STATIC HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams, + const unsigned char * key, + unsigned int keylen); +CURL_STATIC int Curl_HMAC_update(HMAC_context * context, + const unsigned char * data, + unsigned int len); +CURL_STATIC int Curl_HMAC_final(HMAC_context * context, unsigned char * result); + +#endif + +#endif /* HEADER_CURL_HMAC_H */ diff --git a/libcurl/src/lib/curl_ldap.h b/libcurl/src/lib/curl_ldap.h new file mode 100644 index 0000000..93fb4b0 --- /dev/null +++ b/libcurl/src/lib/curl_ldap.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_LDAP_H +#define HEADER_CURL_LDAP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_LDAP +extern const struct Curl_handler Curl_handler_ldap; + +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) +extern const struct Curl_handler Curl_handler_ldaps; +#endif + +#endif +#endif /* HEADER_CURL_LDAP_H */ + diff --git a/libcurl/src/lib/curl_md4.h b/libcurl/src/lib/curl_md4.h new file mode 100644 index 0000000..b5a6e68 --- /dev/null +++ b/libcurl/src/lib/curl_md4.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_MD4_H +#define HEADER_CURL_MD4_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so + * that we have a local implementation of it */ +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) + +CURL_STATIC void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len); + +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */ + +#endif /* HEADER_CURL_MD4_H */ diff --git a/libcurl/src/lib/curl_md5.h b/libcurl/src/lib/curl_md5.h new file mode 100644 index 0000000..3626a50 --- /dev/null +++ b/libcurl/src/lib/curl_md5.h @@ -0,0 +1,63 @@ +#ifndef HEADER_CURL_MD5_H +#define HEADER_CURL_MD5_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH +#include "curl_hmac.h" + +#define MD5_DIGEST_LEN 16 + +typedef void (* Curl_MD5_init_func)(void *context); +typedef void (* Curl_MD5_update_func)(void *context, + const unsigned char *data, + unsigned int len); +typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context); + +typedef struct { + Curl_MD5_init_func md5_init_func; /* Initialize context procedure */ + Curl_MD5_update_func md5_update_func; /* Update context with data */ + Curl_MD5_final_func md5_final_func; /* Get final result procedure */ + unsigned int md5_ctxtsize; /* Context structure size */ + unsigned int md5_resultlen; /* Result length (bytes) */ +} MD5_params; + +typedef struct { + const MD5_params *md5_hash; /* Hash function definition */ + void *md5_hashctx; /* Hash function context */ +} MD5_context; + +extern const MD5_params Curl_DIGEST_MD5[1]; +extern const HMAC_params Curl_HMAC_MD5[1]; + +CURL_STATIC void Curl_md5it(unsigned char *output, + const unsigned char *input); + +CURL_STATIC MD5_context * Curl_MD5_init(const MD5_params *md5params); +CURL_STATIC int Curl_MD5_update(MD5_context *context, + const unsigned char *data, + unsigned int len); +CURL_STATIC int Curl_MD5_final(MD5_context *context, unsigned char *result); + +#endif + +#endif /* HEADER_CURL_MD5_H */ diff --git a/libcurl/src/lib/curl_memory.h b/libcurl/src/lib/curl_memory.h new file mode 100644 index 0000000..c485591 --- /dev/null +++ b/libcurl/src/lib/curl_memory.h @@ -0,0 +1,180 @@ +#ifndef HEADER_CURL_MEMORY_H +#define HEADER_CURL_MEMORY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Nasty internal details ahead... + * + * File curl_memory.h must be included by _all_ *.c source files + * that use memory related functions strdup, malloc, calloc, realloc + * or free, and given source file is used to build libcurl library. + * It should be included immediately before memdebug.h as the last files + * included to avoid undesired interaction with other memory function + * headers in dependent libraries. + * + * There is nearly no exception to above rule. All libcurl source + * files in 'lib' subdirectory as well as those living deep inside + * 'packages' subdirectories and linked together in order to build + * libcurl library shall follow it. + * + * File lib/strdup.c is an exception, given that it provides a strdup + * clone implementation while using malloc. Extra care needed inside + * this one. TODO: revisit this paragraph and related code. + * + * The need for curl_memory.h inclusion is due to libcurl's feature + * of allowing library user to provide memory replacement functions, + * memory callbacks, at runtime with curl_global_init_mem() + * + * Any *.c source file used to build libcurl library that does not + * include curl_memory.h and uses any memory function of the five + * mentioned above will compile without any indication, but it will + * trigger weird memory related issues at runtime. + * + * OTOH some source files from 'lib' subdirectory may additionally be + * used directly as source code when using some curlx_ functions by + * third party programs that don't even use libcurl at all. When using + * these source files in this way it is necessary these are compiled + * with CURLX_NO_MEMORY_CALLBACKS defined, in order to ensure that no + * attempt of calling libcurl's memory callbacks is done from code + * which can not use this machinery. + * + * Notice that libcurl's 'memory tracking' system works chaining into + * the memory callback machinery. This implies that when compiling + * 'lib' source files with CURLX_NO_MEMORY_CALLBACKS defined this file + * disengages usage of libcurl's 'memory tracking' system, defining + * MEMDEBUG_NODEFINES and overriding CURLDEBUG purpose. + * + * CURLX_NO_MEMORY_CALLBACKS takes precedence over CURLDEBUG. This is + * done in order to allow building a 'memory tracking' enabled libcurl + * and at the same time allow building programs which do not use it. + * + * Programs and libraries in 'tests' subdirectories have specific + * purposes and needs, and as such each one will use whatever fits + * best, depending additionally wether it links with libcurl or not. + * + * Caveat emptor. Proper curlx_* separation is a work in progress + * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may + * still be required. IOW don't use them yet, there are sharp edges. + */ + +#ifdef HEADER_CURL_MEMDEBUG_H +#error "Header memdebug.h shall not be included before curl_memory.h" +#endif + +#ifndef CURLX_NO_MEMORY_CALLBACKS + +#include /* for the callback typedefs */ + +/* + * strdup (and other memory functions) is redefined in complicated + * ways, but at this point it must be defined as the system-supplied strdup + * so the callback pointer is initialized correctly. + */ +#if defined(_WIN32_WCE) +#define system_strdup _strdup +#elif !defined(HAVE_STRDUP) +#define system_strdup curlx_strdup +#else +#define system_strdup strdup +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ +#endif + +#ifndef __SYMBIAN32__ +/* + * If a memory-using function (like curl_getenv) is used before + * curl_global_init() is called, we need to have these pointers set already. + */ +CURL_STATIC_VAR curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; +CURL_STATIC_VAR curl_free_callback Curl_cfree = (curl_free_callback)free; +CURL_STATIC_VAR curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; +CURL_STATIC_VAR curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; +CURL_STATIC_VAR curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) +CURL_STATIC_VAR curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif +#else +/* + * Symbian OS doesn't support initialization to code in writeable static data. + * Initialization will occur in the curl_global_init() call. + */ +CURL_STATIC_VAR curl_malloc_callback Curl_cmalloc; +CURL_STATIC_VAR curl_free_callback Curl_cfree; +CURL_STATIC_VAR curl_realloc_callback Curl_crealloc; +CURL_STATIC_VAR curl_strdup_callback Curl_cstrdup; +CURL_STATIC_VAR curl_calloc_callback Curl_ccalloc; +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(default:4232) /* MSVC extension, dllimport identity */ +#endif + +#ifndef CURLDEBUG + +/* + * libcurl's 'memory tracking' system defines strdup, malloc, calloc, + * realloc and free, along with others, in memdebug.h in a different + * way although still using memory callbacks forward declared above. + * When using the 'memory tracking' system (CURLDEBUG defined) we do + * not define here the five memory functions given that definitions + * from memdebug.h are the ones that shall be used. + */ + +#undef strdup +#define strdup(ptr) Curl_cstrdup(ptr) +#undef malloc +#define malloc(size) Curl_cmalloc(size) +#undef calloc +#define calloc(nbelem,size) Curl_ccalloc(nbelem, size) +#undef realloc +#define realloc(ptr,size) Curl_crealloc(ptr, size) +#undef free +#define free(ptr) Curl_cfree(ptr) + +#ifdef WIN32 +# ifdef UNICODE +# undef wcsdup +# define wcsdup(ptr) Curl_cwcsdup(ptr) +# undef _wcsdup +# define _wcsdup(ptr) Curl_cwcsdup(ptr) +# undef _tcsdup +# define _tcsdup(ptr) Curl_cwcsdup(ptr) +# else +# undef _tcsdup +# define _tcsdup(ptr) Curl_cstrdup(ptr) +# endif +#endif + +#endif /* CURLDEBUG */ + +#else /* CURLX_NO_MEMORY_CALLBACKS */ + +#ifndef MEMDEBUG_NODEFINES +#define MEMDEBUG_NODEFINES +#endif + +#endif /* CURLX_NO_MEMORY_CALLBACKS */ + +#endif /* HEADER_CURL_MEMORY_H */ diff --git a/libcurl/src/lib/curl_memrchr.c b/libcurl/src/lib/curl_memrchr.c new file mode 100644 index 0000000..dbdc380 --- /dev/null +++ b/libcurl/src/lib/curl_memrchr.c @@ -0,0 +1,58 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "curl_memrchr.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef HAVE_MEMRCHR + +/* + * Curl_memrchr() + * + * Our memrchr() function clone for systems which lack this function. The + * memrchr() function is like the memchr() function, except that it searches + * backwards from the end of the n bytes pointed to by s instead of forward + * from the beginning. + */ + +CURL_STATIC void * +Curl_memrchr(const void *s, int c, size_t n) +{ + const unsigned char *p = s; + const unsigned char *q = s; + + p += n - 1; + + while(p >= q) { + if(*p == (unsigned char)c) + return (void *)p; + p--; + } + + return NULL; +} + +#endif /* HAVE_MEMRCHR */ diff --git a/libcurl/src/lib/curl_memrchr.h b/libcurl/src/lib/curl_memrchr.h new file mode 100644 index 0000000..c566f63 --- /dev/null +++ b/libcurl/src/lib/curl_memrchr.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_MEMRCHR_H +#define HEADER_CURL_MEMRCHR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_MEMRCHR + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#else /* HAVE_MEMRCHR */ + +CURL_STATIC void *Curl_memrchr(const void *s, int c, size_t n); + +#define memrchr(x,y,z) Curl_memrchr((x),(y),(z)) + +#endif /* HAVE_MEMRCHR */ + +#endif /* HEADER_CURL_MEMRCHR_H */ diff --git a/libcurl/src/lib/curl_multibyte.c b/libcurl/src/lib/curl_multibyte.c new file mode 100644 index 0000000..811e6d1 --- /dev/null +++ b/libcurl/src/lib/curl_multibyte.c @@ -0,0 +1,82 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP)) && defined(UNICODE)) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +#include "curl_multibyte.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +CURL_STATIC wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8) +{ + wchar_t *str_w = NULL; + + if(str_utf8) { + int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str_utf8, -1, NULL, 0); + if(str_w_len > 0) { + str_w = malloc(str_w_len * sizeof(wchar_t)); + if(str_w) { + if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w, + str_w_len) == 0) { + free(str_w); + return NULL; + } + } + } + } + + return str_w; +} + +CURL_STATIC char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w) +{ + char *str_utf8 = NULL; + + if(str_w) { + int str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL, + 0, NULL, NULL); + if(str_utf8_len > 0) { + str_utf8 = malloc(str_utf8_len * sizeof(wchar_t)); + if(str_utf8) { + if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len, + NULL, FALSE) == 0) { + free(str_utf8); + return NULL; + } + } + } + } + + return str_utf8; +} + +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ diff --git a/libcurl/src/lib/curl_multibyte.h b/libcurl/src/lib/curl_multibyte.h new file mode 100644 index 0000000..d660333 --- /dev/null +++ b/libcurl/src/lib/curl_multibyte.h @@ -0,0 +1,92 @@ +#ifndef HEADER_CURL_MULTIBYTE_H +#define HEADER_CURL_MULTIBYTE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP)) && defined(UNICODE)) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +CURL_STATIC wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8); +CURL_STATIC char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w); + +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ + + +#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP) + +/* + * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8() + * and Curl_unicodefree() main purpose is to minimize the number of + * preprocessor conditional directives needed by code using these + * to differentiate UNICODE from non-UNICODE builds. + * + * When building with UNICODE defined, this two macros + * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() + * return a pointer to a newly allocated memory area holding result. + * When the result is no longer needed, allocated memory is intended + * to be free'ed with Curl_unicodefree(). + * + * When building without UNICODE defined, this macros + * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() + * return the pointer received as argument. Curl_unicodefree() does + * no actual free'ing of this pointer it is simply set to NULL. + */ + +#ifdef UNICODE + +#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr)) +#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr)) +#define Curl_unicodefree(ptr) \ + do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE + +typedef union { + unsigned short *tchar_ptr; + const unsigned short *const_tchar_ptr; + unsigned short *tbyte_ptr; + const unsigned short *const_tbyte_ptr; +} xcharp_u; + +#else + +#define Curl_convert_UTF8_to_tchar(ptr) (ptr) +#define Curl_convert_tchar_to_UTF8(ptr) (ptr) +#define Curl_unicodefree(ptr) \ + do {(ptr) = NULL;} WHILE_FALSE + +typedef union { + char *tchar_ptr; + const char *const_tchar_ptr; + unsigned char *tbyte_ptr; + const unsigned char *const_tbyte_ptr; +} xcharp_u; + +#endif /* UNICODE */ + +#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */ + +#endif /* HEADER_CURL_MULTIBYTE_H */ diff --git a/libcurl/src/lib/curl_ntlm.c b/libcurl/src/lib/curl_ntlm.c new file mode 100644 index 0000000..24162bc --- /dev/null +++ b/libcurl/src/lib/curl_ntlm.c @@ -0,0 +1,232 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + +/* + * NTLM details: + * + * http://davenport.sourceforge.net/ntlm.html + * http://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#include "urldata.h" +#include "sendf.h" +#include "rawstr.h" +#include "curl_ntlm.h" +#include "curl_ntlm_msgs.h" +#include "curl_ntlm_wb.h" +#include "curl_sasl.h" +#include "url.h" +#include "curl_printf.h" + +#if defined(USE_NSS) +#include "vtls/nssg.h" +#elif defined(USE_WINDOWS_SSPI) +#include "curl_sspi.h" +#endif + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if DEBUG_ME +# define DEBUG_OUT(x) x +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +CURLcode Curl_input_ntlm(struct connectdata *conn, + bool proxy, /* if proxy or not */ + const char *header) /* rest of the www-authenticate: + header */ +{ + /* point to the correct struct with this */ + struct ntlmdata *ntlm; + CURLcode result = CURLE_OK; + + ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; + + if(checkprefix("NTLM", header)) { + header += strlen("NTLM"); + + while(*header && ISSPACE(*header)) + header++; + + if(*header) { + result = Curl_sasl_decode_ntlm_type2_message(conn->data, header, ntlm); + if(result) + return result; + + ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */ + } + else { + if(ntlm->state == NTLMSTATE_TYPE3) { + infof(conn->data, "NTLM handshake rejected\n"); + Curl_http_ntlm_cleanup(conn); + ntlm->state = NTLMSTATE_NONE; + return CURLE_REMOTE_ACCESS_DENIED; + } + else if(ntlm->state >= NTLMSTATE_TYPE1) { + infof(conn->data, "NTLM handshake failure (internal error)\n"); + return CURLE_REMOTE_ACCESS_DENIED; + } + + ntlm->state = NTLMSTATE_TYPE1; /* We should send away a type-1 */ + } + } + + return result; +} + +/* + * This is for creating ntlm header output + */ +CURL_STATIC CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) +{ + char *base64 = NULL; + size_t len = 0; + CURLcode result; + + /* point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + + /* point to the name and password for this */ + const char *userp; + const char *passwdp; + + /* point to the correct struct with this */ + struct ntlmdata *ntlm; + struct auth *authp; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + +#ifdef USE_NSS + if(CURLE_OK != Curl_nss_force_init(conn->data)) + return CURLE_OUT_OF_MEMORY; +#endif + + if(proxy) { + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->proxyuser; + passwdp = conn->proxypasswd; + ntlm = &conn->proxyntlm; + authp = &conn->data->state.authproxy; + } + else { + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + passwdp = conn->passwd; + ntlm = &conn->ntlm; + authp = &conn->data->state.authhost; + } + authp->done = FALSE; + + /* not set means empty */ + if(!userp) + userp = ""; + + if(!passwdp) + passwdp = ""; + +#ifdef USE_WINDOWS_SSPI + if(s_hSecDll == NULL) { + /* not thread safe and leaks - use curl_global_init() to avoid */ + CURLcode err = Curl_sspi_global_init(); + if(s_hSecDll == NULL) + return err; + } +#endif + + switch(ntlm->state) { + case NTLMSTATE_TYPE1: + default: /* for the weird cases we (re)start here */ + /* Create a type-1 message */ + result = Curl_sasl_create_ntlm_type1_message(userp, passwdp, ntlm, &base64, + &len); + if(result) + return result; + + if(base64) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); + } + break; + + case NTLMSTATE_TYPE2: + /* We already received the type-2 message, create a type-3 message */ + result = Curl_sasl_create_ntlm_type3_message(conn->data, userp, passwdp, + ntlm, &base64, &len); + if(result) + return result; + + if(base64) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); + + ntlm->state = NTLMSTATE_TYPE3; /* we send a type-3 */ + authp->done = TRUE; + } + break; + + case NTLMSTATE_TYPE3: + /* connection is already authenticated, + * don't send a header in future requests */ + Curl_safefree(*allocuserpwd); + authp->done = TRUE; + break; + } + + return CURLE_OK; +} + +CURL_STATIC void Curl_http_ntlm_cleanup(struct connectdata *conn) +{ + Curl_sasl_ntlm_cleanup(&conn->ntlm); + Curl_sasl_ntlm_cleanup(&conn->proxyntlm); + +#if defined(NTLM_WB_ENABLED) + Curl_ntlm_wb_cleanup(conn); +#endif +} + +#endif /* USE_NTLM */ diff --git a/libcurl/src/lib/curl_ntlm.h b/libcurl/src/lib/curl_ntlm.h new file mode 100644 index 0000000..4615b95 --- /dev/null +++ b/libcurl/src/lib/curl_ntlm.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_NTLM_H +#define HEADER_CURL_NTLM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + +/* this is for ntlm header input */ +CURL_STATIC CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating ntlm header output */ +CURL_STATIC CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); + +CURL_STATIC void Curl_http_ntlm_cleanup(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM */ + +#endif /* HEADER_CURL_NTLM_H */ diff --git a/libcurl/src/lib/curl_ntlm_core.c b/libcurl/src/lib/curl_ntlm_core.c new file mode 100644 index 0000000..bef48cf --- /dev/null +++ b/libcurl/src/lib/curl_ntlm_core.c @@ -0,0 +1,765 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) + +/* + * NTLM details: + * + * http://davenport.sourceforge.net/ntlm.html + * http://www.innovation.ch/java/ntlm.html + */ + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#ifdef USE_OPENSSL + +# ifdef USE_OPENSSL +# include +# ifndef OPENSSL_NO_MD4 +# include +# endif +# include +# include +# include +# else +# include +# ifndef OPENSSL_NO_MD4 +# include +# endif +# include +# include +# include +# endif +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) +# define DES_key_schedule des_key_schedule +# define DES_cblock des_cblock +# define DES_set_odd_parity des_set_odd_parity +# define DES_set_key des_set_key +# define DES_ecb_encrypt des_ecb_encrypt +# define DESKEY(x) x +# define DESKEYARG(x) x +# else +# define DESKEYARG(x) *x +# define DESKEY(x) &x +# endif + +#elif defined(USE_GNUTLS_NETTLE) + +# include +# include + +#elif defined(USE_GNUTLS) + +# include +# define MD5_DIGEST_LENGTH 16 +# define MD4_DIGEST_LENGTH 16 + +#elif defined(USE_NSS) + +# include +# include +# include +# include "curl_md4.h" +# define MD5_DIGEST_LENGTH MD5_LENGTH + +#elif defined(USE_DARWINSSL) + +# include +# include + +#elif defined(USE_OS400CRYPTO) +# include "cipher.mih" /* mih/cipher */ +# include "curl_md4.h" +#elif defined(USE_WIN32_CRYPTO) +# include +#else +# error "Can't compile NTLM support without a crypto library." +#endif + +#include "urldata.h" +#include "non-ascii.h" +#include "rawstr.h" +#include "curl_ntlm_core.h" +#include "curl_md5.h" +#include "curl_hmac.h" +#include "warnless.h" +#include "curl_endian.h" +#include "curl_des.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define NTLM_HMAC_MD5_LEN (16) +#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" +#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) + +/* +* Turns a 56-bit key into being 64-bit wide. +*/ +static void extend_key_56_to_64(const unsigned char *key_56, char *key) +{ + key[0] = key_56[0]; + key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); + key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); + key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); + key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); + key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); + key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); + key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); +} + +#ifdef USE_OPENSSL +/* + * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The + * key schedule ks is also set. + */ +static void setup_des_key(const unsigned char *key_56, + DES_key_schedule DESKEYARG(ks)) +{ + DES_cblock key; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, (char *) key); + + /* Set the key parity to odd */ +#if defined(HAVE_BORINGSSL) + Curl_des_set_odd_parity((unsigned char *) &key, sizeof(key)); +#else + DES_set_odd_parity(&key); +#endif + + /* Set the key */ + DES_set_key(&key, ks); +} + +#elif defined(USE_GNUTLS_NETTLE) + +static void setup_des_key(const unsigned char *key_56, + struct des_ctx *des) +{ + char key[8]; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Set the key */ + des_set_key(des, (const uint8_t *) key); +} + +#elif defined(USE_GNUTLS) + +/* + * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. + */ +static void setup_des_key(const unsigned char *key_56, + gcry_cipher_hd_t *des) +{ + char key[8]; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Set the key */ + gcry_cipher_setkey(*des, key, sizeof(key)); +} + +#elif defined(USE_NSS) + +/* + * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using + * the expanded key. The caller is responsible for giving 64 bit of valid + * data is IN and (at least) 64 bit large buffer as OUT. + */ +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */ + PK11SlotInfo *slot = NULL; + char key[8]; /* expanded 64 bit key */ + SECItem key_item; + PK11SymKey *symkey = NULL; + SECItem *param = NULL; + PK11Context *ctx = NULL; + int out_len; /* not used, required by NSS */ + bool rv = FALSE; + + /* use internal slot for DES encryption (requires NSS to be initialized) */ + slot = PK11_GetInternalKeySlot(); + if(!slot) + return FALSE; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Import the key */ + key_item.data = (unsigned char *)key; + key_item.len = sizeof(key); + symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT, + &key_item, NULL); + if(!symkey) + goto fail; + + /* Create the DES encryption context */ + param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL); + if(!param) + goto fail; + ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param); + if(!ctx) + goto fail; + + /* Perform the encryption */ + if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8, + (unsigned char *)in, /* inbuflen */ 8) + && SECSuccess == PK11_Finalize(ctx)) + rv = /* all OK */ TRUE; + +fail: + /* cleanup */ + if(ctx) + PK11_DestroyContext(ctx, PR_TRUE); + if(symkey) + PK11_FreeSymKey(symkey); + if(param) + SECITEM_FreeItem(param, PR_TRUE); + PK11_FreeSlot(slot); + return rv; +} + +#elif defined(USE_DARWINSSL) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + char key[8]; + size_t out_len; + CCCryptorStatus err; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Perform the encryption */ + err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key, + kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out, + 8 /* outbuflen */, &out_len); + + return err == kCCSuccess; +} + +#elif defined(USE_OS400CRYPTO) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + char key[8]; + _CIPHER_Control_T ctl; + + /* Setup the cipher control structure */ + ctl.Func_ID = ENCRYPT_ONLY; + ctl.Data_Len = sizeof(key); + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, ctl.Crypto_Key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len); + + /* Perform the encryption */ + _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in); + + return TRUE; +} + +#elif defined(USE_WIN32_CRYPTO) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + HCRYPTPROV hprov; + HCRYPTKEY hkey; + struct { + BLOBHEADER hdr; + unsigned int len; + char key[8]; + } blob; + DWORD len = 8; + + /* Acquire the crypto provider */ + if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + return FALSE; + + /* Setup the key blob structure */ + memset(&blob, 0, sizeof(blob)); + blob.hdr.bType = PLAINTEXTKEYBLOB; + blob.hdr.bVersion = 2; + blob.hdr.aiKeyAlg = CALG_DES; + blob.len = sizeof(blob.key); + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, blob.key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key)); + + /* Import the key */ + if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) { + CryptReleaseContext(hprov, 0); + + return FALSE; + } + + memcpy(out, in, 8); + + /* Perform the encryption */ + CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len); + + CryptDestroyKey(hkey); + CryptReleaseContext(hprov, 0); + + return TRUE; +} + +#endif /* defined(USE_WIN32_CRYPTO) */ + + /* + * takes a 21 byte array and treats it as 3 56-bit DES keys. The + * 8 byte plaintext is encrypted with each key and the resulting 24 + * bytes are stored in the results array. + */ +CURL_STATIC void Curl_ntlm_core_lm_resp(const unsigned char *keys, + const unsigned char *plaintext, + unsigned char *results) +{ +#ifdef USE_OPENSSL + DES_key_schedule ks; + + setup_des_key(keys, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(keys + 7, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8), + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(keys + 14, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16), + DESKEY(ks), DES_ENCRYPT); +#elif defined(USE_GNUTLS_NETTLE) + struct des_ctx des; + setup_des_key(keys, &des); + des_encrypt(&des, 8, results, plaintext); + setup_des_key(keys + 7, &des); + des_encrypt(&des, 8, results + 8, plaintext); + setup_des_key(keys + 14, &des); + des_encrypt(&des, 8, results + 16, plaintext); +#elif defined(USE_GNUTLS) + gcry_cipher_hd_t des; + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys, &des); + gcry_cipher_encrypt(des, results, 8, plaintext, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys + 7, &des); + gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys + 14, &des); + gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8); + gcry_cipher_close(des); +#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \ + || defined(USE_WIN32_CRYPTO) + encrypt_des(plaintext, results, keys); + encrypt_des(plaintext, results + 8, keys + 7); + encrypt_des(plaintext, results + 16, keys + 14); +#endif +} + +/* + * Set up lanmanager hashed password + */ +CURL_STATIC CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data, + const char *password, + unsigned char *lmbuffer /* 21 bytes */) +{ + CURLcode result; + unsigned char pw[14]; + static const unsigned char magic[] = { + 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ + }; + size_t len = CURLMIN(strlen(password), 14); + + Curl_strntoupper((char *)pw, password, len); + memset(&pw[len], 0, 14 - len); + + /* + * The LanManager hashed password needs to be created using the + * password in the network encoding not the host encoding. + */ + result = Curl_convert_to_network(data, (char *)pw, 14); + if(result) + return result; + + { + /* Create LanManager hashed password. */ + +#ifdef USE_OPENSSL + DES_key_schedule ks; + + setup_des_key(pw, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer, + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(pw + 7, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8), + DESKEY(ks), DES_ENCRYPT); +#elif defined(USE_GNUTLS_NETTLE) + struct des_ctx des; + setup_des_key(pw, &des); + des_encrypt(&des, 8, lmbuffer, magic); + setup_des_key(pw + 7, &des); + des_encrypt(&des, 8, lmbuffer + 8, magic); +#elif defined(USE_GNUTLS) + gcry_cipher_hd_t des; + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(pw, &des); + gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(pw + 7, &des); + gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8); + gcry_cipher_close(des); +#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \ + || defined(USE_WIN32_CRYPTO) + encrypt_des(magic, lmbuffer, pw); + encrypt_des(magic, lmbuffer + 8, pw + 7); +#endif + + memset(lmbuffer + 16, 0, 21 - 16); + } + + return CURLE_OK; +} + +#if USE_NTRESPONSES +static void ascii_to_unicode_le(unsigned char *dest, const char *src, + size_t srclen) +{ + size_t i; + for(i = 0; i < srclen; i++) { + dest[2 * i] = (unsigned char)src[i]; + dest[2 * i + 1] = '\0'; + } +} + +#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI) + +static void ascii_uppercase_to_unicode_le(unsigned char *dest, + const char *src, size_t srclen) +{ + size_t i; + for(i = 0; i < srclen; i++) { + dest[2 * i] = (unsigned char)(toupper(src[i])); + dest[2 * i + 1] = '\0'; + } +} + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +/* + * Set up nt hashed passwords + * @unittest: 1600 + */ +CURL_STATIC CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, + const char *password, + unsigned char *ntbuffer /* 21 bytes */) +{ + size_t len = strlen(password); + unsigned char *pw = malloc(len * 2); + CURLcode result; + if(!pw) + return CURLE_OUT_OF_MEMORY; + + ascii_to_unicode_le(pw, password, len); + + /* + * The NT hashed password needs to be created using the password in the + * network encoding not the host encoding. + */ + result = Curl_convert_to_network(data, (char *)pw, len * 2); + if(result) + return result; + + { + /* Create NT hashed password. */ +#ifdef USE_OPENSSL + MD4_CTX MD4pw; + MD4_Init(&MD4pw); + MD4_Update(&MD4pw, pw, 2 * len); + MD4_Final(ntbuffer, &MD4pw); +#elif defined(USE_GNUTLS_NETTLE) + struct md4_ctx MD4pw; + md4_init(&MD4pw); + md4_update(&MD4pw, (unsigned int)(2 * len), pw); + md4_digest(&MD4pw, MD4_DIGEST_SIZE, ntbuffer); +#elif defined(USE_GNUTLS) + gcry_md_hd_t MD4pw; + gcry_md_open(&MD4pw, GCRY_MD_MD4, 0); + gcry_md_write(MD4pw, pw, 2 * len); + memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH); + gcry_md_close(MD4pw); +#elif defined(USE_NSS) || defined(USE_OS400CRYPTO) + Curl_md4it(ntbuffer, pw, 2 * len); +#elif defined(USE_DARWINSSL) + (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer); +#elif defined(USE_WIN32_CRYPTO) + HCRYPTPROV hprov; + if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + HCRYPTHASH hhash; + if(CryptCreateHash(hprov, CALG_MD4, 0, 0, &hhash)) { + DWORD length = 16; + CryptHashData(hhash, pw, (unsigned int)len * 2, 0); + CryptGetHashParam(hhash, HP_HASHVAL, ntbuffer, &length, 0); + CryptDestroyHash(hhash); + } + CryptReleaseContext(hprov, 0); + } +#endif + + memset(ntbuffer + 16, 0, 21 - 16); + } + + free(pw); + + return CURLE_OK; +} + +#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI) + +/* This returns the HMAC MD5 digest */ +CURL_STATIC CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output) +{ + HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen); + + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + /* Update the digest with the given challenge */ + Curl_HMAC_update(ctxt, data, datalen); + + /* Finalise the digest */ + Curl_HMAC_final(ctxt, output); + + return CURLE_OK; +} + +/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode + * (uppercase UserName + Domain) as the data + */ +CURL_STATIC CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, + const char *domain, size_t domlen, + unsigned char *ntlmhash, + unsigned char *ntlmv2hash) +{ + /* Unicode representation */ + size_t identity_len = (userlen + domlen) * 2; + unsigned char *identity = malloc(identity_len); + CURLcode result = CURLE_OK; + + if(!identity) + return CURLE_OUT_OF_MEMORY; + + ascii_uppercase_to_unicode_le(identity, user, userlen); + ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); + + result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), + ntlmv2hash); + + free(identity); + + return result; +} + +/* + * Curl_ntlm_core_mk_ntlmv2_resp() + * + * This creates the NTLMv2 response as set in the ntlm type-3 message. + * + * Parameters: + * + * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) + * challenge_client [in] - The client nonce (8 bytes) + * ntlm [in] - The ntlm data struct being used to read TargetInfo + and Server challenge received in the type-2 message + * ntresp [out] - The address where a pointer to newly allocated + * memory holding the NTLMv2 response. + * ntresp_len [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + struct ntlmdata *ntlm, + unsigned char **ntresp, + unsigned int *ntresp_len) +{ +/* NTLMv2 response structure : +------------------------------------------------------------------------------ +0 HMAC MD5 16 bytes +------BLOB-------------------------------------------------------------------- +16 Signature 0x01010000 +20 Reserved long (0x00000000) +24 Timestamp LE, 64-bit signed value representing the number of + tenths of a microsecond since January 1, 1601. +32 Client Nonce 8 bytes +40 Unknown 4 bytes +44 Target Info N bytes (from the type-2 message) +44+N Unknown 4 bytes +------------------------------------------------------------------------------ +*/ + + unsigned int len = 0; + unsigned char *ptr = NULL; + unsigned char hmac_output[NTLM_HMAC_MD5_LEN]; +#if defined(HAVE_LONGLONG) + long long tw; +#else + __int64 tw; +#endif + CURLcode result = CURLE_OK; + + /* Calculate the timestamp */ +#ifdef DEBUGBUILD + char *force_timestamp = getenv("CURL_FORCETIME"); + if(force_timestamp) + tw = 11644473600ULL * 10000000ULL; + else +#endif + tw = ((long long)time(NULL) + 11644473600ULL) * 10000000ULL; + + /* Calculate the response len */ + len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN; + + /* Allocate the response */ + ptr = malloc(len); + if(!ptr) + return CURLE_OUT_OF_MEMORY; + + memset(ptr, 0, len); + + /* Create the BLOB structure */ + snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN, + NTLMv2_BLOB_SIGNATURE + "%c%c%c%c", /* Reserved = 0 */ + 0, 0, 0, 0); + + Curl_write64_le(tw, ptr + 24); + memcpy(ptr + 32, challenge_client, 8); + memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); + + /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ + memcpy(ptr + 8, &ntlm->nonce[0], 8); + result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, + NTLMv2_BLOB_LEN + 8, hmac_output); + if(result) { + free(ptr); + return result; + } + + /* Concatenate the HMAC MD5 output with the BLOB */ + memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN); + + /* Return the response */ + *ntresp = ptr; + *ntresp_len = len; + + return result; +} + +/* + * Curl_ntlm_core_mk_lmv2_resp() + * + * This creates the LMv2 response as used in the ntlm type-3 message. + * + * Parameters: + * + * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) + * challenge_client [in] - The client nonce (8 bytes) + * challenge_client [in] - The server challenge (8 bytes) + * lmresp [out] - The LMv2 response (24 bytes) + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp) +{ + unsigned char data[16]; + unsigned char hmac_output[16]; + CURLcode result = CURLE_OK; + + memcpy(&data[0], challenge_server, 8); + memcpy(&data[8], challenge_client, 8); + + result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); + if(result) + return result; + + /* Concatenate the HMAC MD5 output with the client nonce */ + memcpy(lmresp, hmac_output, 16); + memcpy(lmresp+16, challenge_client, 8); + + return result; +} + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +#endif /* USE_NTRESPONSES */ + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* USE_NTLM */ diff --git a/libcurl/src/lib/curl_ntlm_core.h b/libcurl/src/lib/curl_ntlm_core.h new file mode 100644 index 0000000..f089cef --- /dev/null +++ b/libcurl/src/lib/curl_ntlm_core.h @@ -0,0 +1,106 @@ +#ifndef HEADER_CURL_NTLM_CORE_H +#define HEADER_CURL_NTLM_CORE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#ifdef USE_OPENSSL +# if !defined(OPENSSL_VERSION_NUMBER) && \ + !defined(HEADER_SSL_H) && !defined(HEADER_MD5_H) +# error "curl_ntlm_core.h shall not be included before OpenSSL headers." +# endif +# ifdef OPENSSL_NO_MD4 +# define USE_NTRESPONSES 0 +# define USE_NTLM2SESSION 0 +# define USE_NTLM_V2 0 +# endif +#endif + +/* Define USE_NTRESPONSES to 1 in order to make the type-3 message include + * the NT response message. */ +#ifndef USE_NTRESPONSES +#define USE_NTRESPONSES 1 +#endif + +/* Define USE_NTLM2SESSION to 1 in order to make the type-3 message include the + NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a + Crypto engine that we have curl_ssl_md5sum() for. */ +#if !defined(USE_NTLM2SESSION) && USE_NTRESPONSES && !defined(USE_WIN32_CRYPTO) +#define USE_NTLM2SESSION 1 +#endif + +/* Define USE_NTLM_V2 to 1 in order to allow the type-3 message to include the + LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 + and support for 64-bit integers. */ +#if !defined(USE_NTLM_V2) && USE_NTRESPONSES && (CURL_SIZEOF_CURL_OFF_T > 4) +#define USE_NTLM_V2 1 +#endif + +CURL_STATIC void Curl_ntlm_core_lm_resp(const unsigned char *keys, + const unsigned char *plaintext, + unsigned char *results); + +CURL_STATIC CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data, + const char *password, + unsigned char *lmbuffer /* 21 bytes */); + +#if USE_NTRESPONSES +CURL_STATIC CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, + const char *password, + unsigned char *ntbuffer /* 21 bytes */); + +#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI) + +CURL_STATIC CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output); + +CURL_STATIC CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, + const char *domain, size_t domlen, + unsigned char *ntlmhash, + unsigned char *ntlmv2hash); + +CURL_STATIC CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + struct ntlmdata *ntlm, + unsigned char **ntresp, + unsigned int *ntresp_len); + +CURL_STATIC CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp); + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +#endif /* USE_NTRESPONSES */ + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_CURL_NTLM_CORE_H */ diff --git a/libcurl/src/lib/curl_ntlm_msgs.c b/libcurl/src/lib/curl_ntlm_msgs.c new file mode 100644 index 0000000..c46f2a0 --- /dev/null +++ b/libcurl/src/lib/curl_ntlm_msgs.c @@ -0,0 +1,819 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI) + +/* + * NTLM details: + * + * http://davenport.sourceforge.net/ntlm.html + * http://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#include "urldata.h" +#include "non-ascii.h" +#include "sendf.h" +#include "curl_base64.h" +#include "curl_ntlm_core.h" +#include "curl_gethostname.h" +#include "curl_multibyte.h" +#include "warnless.h" + +#include "vtls/vtls.h" + +#ifdef USE_NSS +#include "vtls/nssg.h" /* for Curl_nss_force_init() */ +#endif + +#define BUILDING_CURL_NTLM_MSGS_C +#include "curl_ntlm_msgs.h" +#include "curl_sasl.h" +#include "curl_endian.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* "NTLMSSP" signature is always in ASCII regardless of the platform */ +#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" + +#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff) +#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \ + (((x) >> 16) & 0xff), (((x) >> 24) & 0xff) + +#if DEBUG_ME +# define DEBUG_OUT(x) x +static void ntlm_print_flags(FILE *handle, unsigned long flags) +{ + if(flags & NTLMFLAG_NEGOTIATE_UNICODE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE "); + if(flags & NTLMFLAG_NEGOTIATE_OEM) + fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM "); + if(flags & NTLMFLAG_REQUEST_TARGET) + fprintf(handle, "NTLMFLAG_REQUEST_TARGET "); + if(flags & (1<<3)) + fprintf(handle, "NTLMFLAG_UNKNOWN_3 "); + if(flags & NTLMFLAG_NEGOTIATE_SIGN) + fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN "); + if(flags & NTLMFLAG_NEGOTIATE_SEAL) + fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL "); + if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE "); + if(flags & NTLMFLAG_NEGOTIATE_LM_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY "); + if(flags & NTLMFLAG_NEGOTIATE_NETWARE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE "); + if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY "); + if(flags & (1<<10)) + fprintf(handle, "NTLMFLAG_UNKNOWN_10 "); + if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS) + fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS "); + if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED) + fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED "); + if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED) + fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED "); + if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL) + fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL "); + if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN) + fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN "); + if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN "); + if(flags & NTLMFLAG_TARGET_TYPE_SERVER) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER "); + if(flags & NTLMFLAG_TARGET_TYPE_SHARE) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE "); + if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY "); + if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE) + fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE "); + if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE) + fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE "); + if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY) + fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY "); + if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) + fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO "); + if(flags & (1<<24)) + fprintf(handle, "NTLMFLAG_UNKNOWN_24 "); + if(flags & (1<<25)) + fprintf(handle, "NTLMFLAG_UNKNOWN_25 "); + if(flags & (1<<26)) + fprintf(handle, "NTLMFLAG_UNKNOWN_26 "); + if(flags & (1<<27)) + fprintf(handle, "NTLMFLAG_UNKNOWN_27 "); + if(flags & (1<<28)) + fprintf(handle, "NTLMFLAG_UNKNOWN_28 "); + if(flags & NTLMFLAG_NEGOTIATE_128) + fprintf(handle, "NTLMFLAG_NEGOTIATE_128 "); + if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE "); + if(flags & NTLMFLAG_NEGOTIATE_56) + fprintf(handle, "NTLMFLAG_NEGOTIATE_56 "); +} + +static void ntlm_print_hex(FILE *handle, const char *buf, size_t len) +{ + const char *p = buf; + (void)handle; + fprintf(stderr, "0x"); + while(len-- > 0) + fprintf(stderr, "%02.2x", (unsigned int)*p++); +} +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +/* + * ntlm_decode_type2_target() + * + * This is used to decode the "target info" in the ntlm type-2 message + * received. + * + * Parameters: + * + * data [in] - The session handle. + * buffer [in] - The decoded type-2 message. + * size [in] - The input buffer size, at least 32 bytes. + * ntlm [in/out] - The ntlm data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +static CURLcode ntlm_decode_type2_target(struct SessionHandle *data, + unsigned char *buffer, + size_t size, + struct ntlmdata *ntlm) +{ + unsigned short target_info_len = 0; + unsigned int target_info_offset = 0; + + Curl_safefree(ntlm->target_info); + ntlm->target_info_len = 0; + + if(size >= 48) { + target_info_len = Curl_read16_le(&buffer[40]); + target_info_offset = Curl_read32_le(&buffer[44]); + if(target_info_len > 0) { + if(((target_info_offset + target_info_len) > size) || + (target_info_offset < 48)) { + infof(data, "NTLM handshake failure (bad type-2 message). " + "Target Info Offset Len is set incorrect by the peer\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->target_info = malloc(target_info_len); + if(!ntlm->target_info) + return CURLE_OUT_OF_MEMORY; + + memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len); + } + } + + ntlm->target_info_len = target_info_len; + + return CURLE_OK; +} + +/* + NTLM message structure notes: + + A 'short' is a 'network short', a little-endian 16-bit unsigned value. + + A 'long' is a 'network long', a little-endian, 32-bit unsigned value. + + A 'security buffer' represents a triplet used to point to a buffer, + consisting of two shorts and one long: + + 1. A 'short' containing the length of the buffer content in bytes. + 2. A 'short' containing the allocated space for the buffer in bytes. + 3. A 'long' containing the offset to the start of the buffer in bytes, + from the beginning of the NTLM message. +*/ + +/* + * Curl_sasl_decode_ntlm_type2_message() + * + * This is used to decode an already encoded NTLM type-2 message. The message + * is first decoded from a base64 string into a raw NTLM message and checked + * for validity before the appropriate data for creating a type-3 message is + * written to the given NTLM data structure. + * + * Parameters: + * + * data [in] - The session handle. + * type2msg [in] - The base64 encoded type-2 message. + * ntlm [in/out] - The ntlm data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data, + const char *header, + struct ntlmdata *ntlm) +{ + static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; + + /* NTLM type-2 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x02000000) + 12 Target Name security buffer + 20 Flags long + 24 Challenge 8 bytes + (32) Context 8 bytes (two consecutive longs) (*) + (40) Target Information security buffer (*) + (48) OS Version Structure 8 bytes (*) + 32 (48) (56) Start of data block (*) + (*) -> Optional + */ + + CURLcode result = CURLE_OK; + unsigned char *type2 = NULL; + size_t type2_len = 0; + +#if defined(USE_NSS) + /* Make sure the crypto backend is initialized */ + result = Curl_nss_force_init(data); + if(result) + return result; +#elif defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)data; +#endif + + /* Decode the base-64 encoded type-2 message */ + if(strlen(type2msg) && *type2msg != '=') { + result = Curl_base64_decode(type2msg, &type2, &type2_len); + if(result) + return result; + } + + /* Ensure we have a valid type-2 message */ + if(!type2) { + infof(data, "NTLM handshake failure (empty type-2 message)\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->flags = 0; + + if((type2_len < 32) || + (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) || + (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) { + /* This was not a good enough type-2 message */ + free(type2); + infof(data, "NTLM handshake failure (bad type-2 message)\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->flags = Curl_read32_le(&type2[20]); + memcpy(ntlm->nonce, &type2[24], 8); + + if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { + result = ntlm_decode_type2_target(data, type2, type2_len, ntlm); + if(result) { + free(type2); + infof(data, "NTLM handshake failure (bad type-2 message)\n"); + return result; + } + } + + DEBUG_OUT({ + fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); + ntlm_print_flags(stderr, ntlm->flags); + fprintf(stderr, "\n nonce="); + ntlm_print_hex(stderr, (char *)ntlm->nonce, 8); + fprintf(stderr, "\n****\n"); + fprintf(stderr, "**** Header %s\n ", header); + }); + + free(type2); + + return result; +} + +/* copy the source to the destination and fill in zeroes in every + other destination byte! */ +static void unicodecpy(unsigned char *dest, const char *src, size_t length) +{ + size_t i; + for(i = 0; i < length; i++) { + dest[2 * i] = (unsigned char)src[i]; + dest[2 * i + 1] = '\0'; + } +} + +/* + * Curl_sasl_create_ntlm_type1_message() + * + * This is used to generate an already encoded NTLM type-1 message ready for + * sending to the recipient using the appropriate compile time crypto API. + * + * Parameters: + * + * userp [in] - The user name in the format User or Domain\User. + * passdwp [in] - The user's password. + * ntlm [in/out] - The ntlm data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + /* NTLM type-1 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x01000000) + 12 Flags long + (16) Supplied Domain security buffer (*) + (24) Supplied Workstation security buffer (*) + (32) OS Version Structure 8 bytes (*) + (32) (40) Start of data block (*) + (*) -> Optional + */ + + size_t size; + + unsigned char ntlmbuf[NTLM_BUFSIZE]; + const char *host = ""; /* empty */ + const char *domain = ""; /* empty */ + size_t hostlen = 0; + size_t domlen = 0; + size_t hostoff = 0; + size_t domoff = hostoff + hostlen; /* This is 0: remember that host and + domain are empty */ + (void)userp; + (void)passwdp; + + /* Clean up any former leftovers and initialise to defaults */ + Curl_sasl_ntlm_cleanup(ntlm); + +#if USE_NTRESPONSES && USE_NTLM2SESSION +#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY +#else +#define NTLM2FLAG 0 +#endif + snprintf((char *)ntlmbuf, NTLM_BUFSIZE, + NTLMSSP_SIGNATURE "%c" + "\x01%c%c%c" /* 32-bit type = 1 */ + "%c%c%c%c" /* 32-bit NTLM flag field */ + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host name offset */ + "%c%c" /* 2 zeroes */ + "%s" /* host name */ + "%s", /* domain string */ + 0, /* trailing zero */ + 0, 0, 0, /* part of type-1 long */ + + LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0, 0, + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0, 0, + host, /* this is empty */ + domain /* this is empty */); + + /* Initial packet length */ + size = 32 + hostlen + domlen; + + DEBUG_OUT({ + fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x " + "0x%08.8x ", + LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), + NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); + ntlm_print_flags(stderr, + NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); + fprintf(stderr, "\n****\n"); + }); + + /* Return with binary blob encoded into base64 */ + return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen); +} + +/* + * Curl_sasl_create_ntlm_type3_message() + * + * This is used to generate an already encoded NTLM type-3 message ready for + * sending to the recipient using the appropriate compile time crypto API. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passdwp [in] - The user's password. + * ntlm [in/out] - The ntlm data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + /* NTLM type-3 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x03000000) + 12 LM/LMv2 Response security buffer + 20 NTLM/NTLMv2 Response security buffer + 28 Target Name security buffer + 36 User Name security buffer + 44 Workstation Name security buffer + (52) Session Key security buffer (*) + (60) Flags long (*) + (64) OS Version Structure 8 bytes (*) + 52 (64) (72) Start of data block + (*) -> Optional + */ + + CURLcode result = CURLE_OK; + size_t size; + unsigned char ntlmbuf[NTLM_BUFSIZE]; + int lmrespoff; + unsigned char lmresp[24]; /* fixed-size */ +#if USE_NTRESPONSES + int ntrespoff; + unsigned int ntresplen = 24; + unsigned char ntresp[24]; /* fixed-size */ + unsigned char *ptr_ntresp = &ntresp[0]; + unsigned char *ntlmv2resp = NULL; +#endif + bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE; + char host[HOSTNAME_MAX + 1] = ""; + const char *user; + const char *domain = ""; + size_t hostoff = 0; + size_t useroff = 0; + size_t domoff = 0; + size_t hostlen = 0; + size_t userlen = 0; + size_t domlen = 0; + + user = strchr(userp, '\\'); + if(!user) + user = strchr(userp, '/'); + + if(user) { + domain = userp; + domlen = (user - domain); + user++; + } + else + user = userp; + + if(user) + userlen = strlen(user); + + /* Get the machine's un-qualified host name as NTLM doesn't like the fully + qualified domain name */ + if(Curl_gethostname(host, sizeof(host))) { + infof(data, "gethostname() failed, continuing without!\n"); + hostlen = 0; + } + else { + hostlen = strlen(host); + } + +#if USE_NTRESPONSES && USE_NTLM_V2 + if(ntlm->target_info_len) { + unsigned char ntbuffer[0x18]; + unsigned int entropy[2]; + unsigned char ntlmv2hash[0x18]; + + entropy[0] = Curl_rand(data); + entropy[1] = Curl_rand(data); + + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen, + ntbuffer, ntlmv2hash); + if(result) + return result; + + /* LMv2 response */ + result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, + (unsigned char *)&entropy[0], + &ntlm->nonce[0], lmresp); + if(result) + return result; + + /* NTLMv2 response */ + result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, + (unsigned char *)&entropy[0], + ntlm, &ntlmv2resp, &ntresplen); + if(result) + return result; + + ptr_ntresp = ntlmv2resp; + } + else +#endif + +#if USE_NTRESPONSES && USE_NTLM2SESSION + /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ + if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { + unsigned char ntbuffer[0x18]; + unsigned char tmp[0x18]; + unsigned char md5sum[MD5_DIGEST_LENGTH]; + unsigned int entropy[2]; + + /* Need to create 8 bytes random data */ + entropy[0] = Curl_rand(data); + entropy[1] = Curl_rand(data); + + /* 8 bytes random data as challenge in lmresp */ + memcpy(lmresp, entropy, 8); + + /* Pad with zeros */ + memset(lmresp + 8, 0, 0x10); + + /* Fill tmp with challenge(nonce?) + entropy */ + memcpy(tmp, &ntlm->nonce[0], 8); + memcpy(tmp + 8, entropy, 8); + + result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH); + if(!result) + /* We shall only use the first 8 bytes of md5sum, but the des code in + Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp); + + /* End of NTLM2 Session code */ + + } + else +#endif + { + +#if USE_NTRESPONSES + unsigned char ntbuffer[0x18]; +#endif + unsigned char lmbuffer[0x18]; + +#if USE_NTRESPONSES + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp); +#endif + + result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp); + + /* A safer but less compatible alternative is: + * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); + * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */ + } + + if(unicode) { + domlen = domlen * 2; + userlen = userlen * 2; + hostlen = hostlen * 2; + } + + lmrespoff = 64; /* size of the message header */ +#if USE_NTRESPONSES + ntrespoff = lmrespoff + 0x18; + domoff = ntrespoff + ntresplen; +#else + domoff = lmrespoff + 0x18; +#endif + useroff = domoff + domlen; + hostoff = useroff + userlen; + + /* Create the big type-3 message binary blob */ + size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE, + NTLMSSP_SIGNATURE "%c" + "\x03%c%c%c" /* 32-bit type = 3 */ + + "%c%c" /* LanManager length */ + "%c%c" /* LanManager allocated space */ + "%c%c" /* LanManager offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* NT-response length */ + "%c%c" /* NT-response allocated space */ + "%c%c" /* NT-response offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* user length */ + "%c%c" /* user allocated space */ + "%c%c" /* user offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* session key length (unknown purpose) */ + "%c%c" /* session key allocated space (unknown purpose) */ + "%c%c" /* session key offset (unknown purpose) */ + "%c%c" /* 2 zeroes */ + + "%c%c%c%c", /* flags */ + + /* domain string */ + /* user string */ + /* host string */ + /* LanManager response */ + /* NT response */ + + 0, /* zero termination */ + 0, 0, 0, /* type-3 long, the 24 upper bits */ + + SHORTPAIR(0x18), /* LanManager response length, twice */ + SHORTPAIR(0x18), + SHORTPAIR(lmrespoff), + 0x0, 0x0, + +#if USE_NTRESPONSES + SHORTPAIR(ntresplen), /* NT-response length, twice */ + SHORTPAIR(ntresplen), + SHORTPAIR(ntrespoff), + 0x0, 0x0, +#else + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, +#endif + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0x0, 0x0, + + SHORTPAIR(userlen), + SHORTPAIR(userlen), + SHORTPAIR(useroff), + 0x0, 0x0, + + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0x0, 0x0, + + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + + LONGQUARTET(ntlm->flags)); + + DEBUGASSERT(size == 64); + DEBUGASSERT(size == (size_t)lmrespoff); + + /* We append the binary hashes */ + if(size < (NTLM_BUFSIZE - 0x18)) { + memcpy(&ntlmbuf[size], lmresp, 0x18); + size += 0x18; + } + + DEBUG_OUT({ + fprintf(stderr, "**** TYPE3 header lmresp="); + ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18); + }); + +#if USE_NTRESPONSES + if(size < (NTLM_BUFSIZE - ntresplen)) { + DEBUGASSERT(size == (size_t)ntrespoff); + memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); + size += ntresplen; + } + + DEBUG_OUT({ + fprintf(stderr, "\n ntresp="); + ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen); + }); + + free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ + +#endif + + DEBUG_OUT({ + fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", + LONGQUARTET(ntlm->flags), ntlm->flags); + ntlm_print_flags(stderr, ntlm->flags); + fprintf(stderr, "\n****\n"); + }); + + /* Make sure that the domain, user and host strings fit in the + buffer before we copy them there. */ + if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) { + failf(data, "user + domain + host name too big"); + return CURLE_OUT_OF_MEMORY; + } + + DEBUGASSERT(size == domoff); + if(unicode) + unicodecpy(&ntlmbuf[size], domain, domlen / 2); + else + memcpy(&ntlmbuf[size], domain, domlen); + + size += domlen; + + DEBUGASSERT(size == useroff); + if(unicode) + unicodecpy(&ntlmbuf[size], user, userlen / 2); + else + memcpy(&ntlmbuf[size], user, userlen); + + size += userlen; + + DEBUGASSERT(size == hostoff); + if(unicode) + unicodecpy(&ntlmbuf[size], host, hostlen / 2); + else + memcpy(&ntlmbuf[size], host, hostlen); + + size += hostlen; + + /* Convert domain, user, and host to ASCII but leave the rest as-is */ + result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff], + size - domoff); + if(result) + return CURLE_CONV_FAILED; + + /* Return with binary blob encoded into base64 */ + result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen); + + Curl_sasl_ntlm_cleanup(ntlm); + + return result; +} + +#endif /* USE_NTLM && !USE_WINDOWS_SSPI */ diff --git a/libcurl/src/lib/curl_ntlm_msgs.h b/libcurl/src/lib/curl_ntlm_msgs.h new file mode 100644 index 0000000..2a71431 --- /dev/null +++ b/libcurl/src/lib/curl_ntlm_msgs.h @@ -0,0 +1,143 @@ +#ifndef HEADER_CURL_NTLM_MSGS_H +#define HEADER_CURL_NTLM_MSGS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NTLM + +/* NTLM buffer fixed size, large enough for long user + host + domain */ +#define NTLM_BUFSIZE 1024 + +/* Stuff only required for curl_ntlm_msgs.c */ +#ifdef BUILDING_CURL_NTLM_MSGS_C + +/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */ + +#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) +/* Indicates that Unicode strings are supported for use in security buffer + data. */ + +#define NTLMFLAG_NEGOTIATE_OEM (1<<1) +/* Indicates that OEM strings are supported for use in security buffer data. */ + +#define NTLMFLAG_REQUEST_TARGET (1<<2) +/* Requests that the server's authentication realm be included in the Type 2 + message. */ + +/* unknown (1<<3) */ +#define NTLMFLAG_NEGOTIATE_SIGN (1<<4) +/* Specifies that authenticated communication between the client and server + should carry a digital signature (message integrity). */ + +#define NTLMFLAG_NEGOTIATE_SEAL (1<<5) +/* Specifies that authenticated communication between the client and server + should be encrypted (message confidentiality). */ + +#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6) +/* Indicates that datagram authentication is being used. */ + +#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7) +/* Indicates that the LAN Manager session key should be used for signing and + sealing authenticated communications. */ + +#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) +/* Indicates that NTLM authentication is being used. */ + +/* unknown (1<<10) */ + +#define NTLMFLAG_NEGOTIATE_ANONYMOUS (1<<11) +/* Sent by the client in the Type 3 message to indicate that an anonymous + context has been established. This also affects the response fields. */ + +#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12) +/* Sent by the client in the Type 1 message to indicate that a desired + authentication realm is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13) +/* Sent by the client in the Type 1 message to indicate that the client + workstation's name is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14) +/* Sent by the server to indicate that the server and client are on the same + machine. Implies that the client may use a pre-established local security + context rather than responding to the challenge. */ + +#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15) +/* Indicates that authenticated communication between the client and server + should be signed with a "dummy" signature. */ + +#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a domain. */ + +#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a server. */ + +#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a share. Presumably, this is for share-level + authentication. Usage is unclear. */ + +#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19) +/* Indicates that the NTLM2 signing and sealing scheme should be used for + protecting authenticated communications. */ + +#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23) +/* Sent by the server in the Type 2 message to indicate that it is including a + Target Information block in the message. */ + +/* unknown (1<24) */ +/* unknown (1<25) */ +/* unknown (1<26) */ +/* unknown (1<27) */ +/* unknown (1<28) */ + +#define NTLMFLAG_NEGOTIATE_128 (1<<29) +/* Indicates that 128-bit encryption is supported. */ + +#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30) +/* Indicates that the client will provide an encrypted master key in + the "Session Key" field of the Type 3 message. */ + +#define NTLMFLAG_NEGOTIATE_56 (1<<31) +/* Indicates that 56-bit encryption is supported. */ + +#endif /* BUILDING_CURL_NTLM_MSGS_C */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_CURL_NTLM_MSGS_H */ diff --git a/libcurl/src/lib/curl_ntlm_wb.c b/libcurl/src/lib/curl_ntlm_wb.c new file mode 100644 index 0000000..b209c53 --- /dev/null +++ b/libcurl/src/lib/curl_ntlm_wb.c @@ -0,0 +1,431 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + +/* + * NTLM details: + * + * http://davenport.sourceforge.net/ntlm.html + * http://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "curl_ntlm_msgs.h" +#include "curl_ntlm_wb.h" +#include "url.h" +#include "strerror.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if DEBUG_ME +# define DEBUG_OUT(x) x +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +/* Portable 'sclose_nolog' used only in child process instead of 'sclose' + to avoid fooling the socket leak detector */ +#if defined(HAVE_CLOSESOCKET) +# define sclose_nolog(x) closesocket((x)) +#elif defined(HAVE_CLOSESOCKET_CAMEL) +# define sclose_nolog(x) CloseSocket((x)) +#else +# define sclose_nolog(x) close((x)) +#endif + +CURL_STATIC void Curl_ntlm_wb_cleanup(struct connectdata *conn) +{ + if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) { + sclose(conn->ntlm_auth_hlpr_socket); + conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; + } + + if(conn->ntlm_auth_hlpr_pid) { + int i; + for(i = 0; i < 4; i++) { + pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG); + if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD) + break; + switch(i) { + case 0: + kill(conn->ntlm_auth_hlpr_pid, SIGTERM); + break; + case 1: + /* Give the process another moment to shut down cleanly before + bringing down the axe */ + Curl_wait_ms(1); + break; + case 2: + kill(conn->ntlm_auth_hlpr_pid, SIGKILL); + break; + case 3: + break; + } + } + conn->ntlm_auth_hlpr_pid = 0; + } + + free(conn->challenge_header); + conn->challenge_header = NULL; + free(conn->response_header); + conn->response_header = NULL; +} + +static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) +{ + curl_socket_t sockfds[2]; + pid_t child_pid; + const char *username; + char *slash, *domain = NULL; + const char *ntlm_auth = NULL; + char *ntlm_auth_alloc = NULL; +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + struct passwd pw, *pw_res; + char pwbuf[1024]; +#endif + int error; + + /* Return if communication with ntlm_auth already set up */ + if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || + conn->ntlm_auth_hlpr_pid) + return CURLE_OK; + + username = userp; + /* 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, "\\/"); + if(slash) { + if((domain = strdup(username)) == NULL) + return CURLE_OUT_OF_MEMORY; + slash = domain + (slash - username); + *slash = '\0'; + username = username + (slash - domain) + 1; + } + + /* For testing purposes, when DEBUGBUILD is defined and environment + variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform + NTLM challenge/response which only accepts commands and output + strings pre-written in test case definitions */ +#ifdef DEBUGBUILD + ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE"); + if(ntlm_auth_alloc) + ntlm_auth = ntlm_auth_alloc; + else +#endif + ntlm_auth = NTLM_WB_FILE; + + if(access(ntlm_auth, X_OK) != 0) { + error = ERRNO; + failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s", + ntlm_auth, error, Curl_strerror(conn, error)); + goto done; + } + + if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { + error = ERRNO; + failf(conn->data, "Could not open socket pair. errno %d: %s", + error, Curl_strerror(conn, error)); + goto done; + } + + child_pid = fork(); + if(child_pid == -1) { + error = ERRNO; + sclose(sockfds[0]); + sclose(sockfds[1]); + failf(conn->data, "Could not fork. errno %d: %s", + error, Curl_strerror(conn, error)); + goto done; + } + else if(!child_pid) { + /* + * child process + */ + + /* Don't use sclose in the child since it fools the socket leak detector */ + sclose_nolog(sockfds[0]); + if(dup2(sockfds[1], STDIN_FILENO) == -1) { + error = ERRNO; + failf(conn->data, "Could not redirect child stdin. errno %d: %s", + error, Curl_strerror(conn, error)); + exit(1); + } + + if(dup2(sockfds[1], STDOUT_FILENO) == -1) { + error = ERRNO; + failf(conn->data, "Could not redirect child stdout. errno %d: %s", + error, Curl_strerror(conn, error)); + exit(1); + } + + if(domain) + execl(ntlm_auth, ntlm_auth, + "--helper-protocol", "ntlmssp-client-1", + "--use-cached-creds", + "--username", username, + "--domain", domain, + NULL); + else + execl(ntlm_auth, ntlm_auth, + "--helper-protocol", "ntlmssp-client-1", + "--use-cached-creds", + "--username", username, + NULL); + + error = ERRNO; + sclose_nolog(sockfds[1]); + failf(conn->data, "Could not execl(). errno %d: %s", + error, Curl_strerror(conn, error)); + exit(1); + } + + sclose(sockfds[1]); + conn->ntlm_auth_hlpr_socket = sockfds[0]; + conn->ntlm_auth_hlpr_pid = child_pid; + free(domain); + free(ntlm_auth_alloc); + return CURLE_OK; + +done: + free(domain); + free(ntlm_auth_alloc); + return CURLE_REMOTE_ACCESS_DENIED; +} + +static CURLcode ntlm_wb_response(struct connectdata *conn, + const char *input, curlntlm state) +{ + char *buf = malloc(NTLM_BUFSIZE); + size_t len_in = strlen(input), len_out = 0; + + if(!buf) + return CURLE_OUT_OF_MEMORY; + + while(len_in > 0) { + ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in); + if(written == -1) { + /* Interrupted by a signal, retry it */ + if(errno == EINTR) + continue; + /* write failed if other errors happen */ + goto done; + } + input += written; + len_in -= written; + } + /* Read one line */ + while(1) { + ssize_t size; + char *newbuf; + + size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE); + if(size == -1) { + if(errno == EINTR) + continue; + goto done; + } + else if(size == 0) + goto done; + + len_out += size; + if(buf[len_out - 1] == '\n') { + buf[len_out - 1] = '\0'; + break; + } + newbuf = realloc(buf, len_out + NTLM_BUFSIZE); + if(!newbuf) { + free(buf); + return CURLE_OUT_OF_MEMORY; + } + buf = newbuf; + } + + /* Samba/winbind installed but not configured */ + if(state == NTLMSTATE_TYPE1 && + len_out == 3 && + buf[0] == 'P' && buf[1] == 'W') + return CURLE_REMOTE_ACCESS_DENIED; + /* invalid response */ + if(len_out < 4) + goto done; + if(state == NTLMSTATE_TYPE1 && + (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' ')) + goto done; + if(state == NTLMSTATE_TYPE2 && + (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') && + (buf[0]!='A' || buf[1]!='F' || buf[2]!=' ')) + goto done; + + conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3); + free(buf); + return CURLE_OK; +done: + free(buf); + return CURLE_REMOTE_ACCESS_DENIED; +} + +/* + * This is for creating ntlm header output by delegating challenge/response + * to Samba's winbind daemon helper ntlm_auth. + */ +CURL_STATIC CURLcode Curl_output_ntlm_wb(struct connectdata *conn, + bool proxy) +{ + /* point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + /* point to the name and password for this */ + const char *userp; + /* point to the correct struct with this */ + struct ntlmdata *ntlm; + struct auth *authp; + + CURLcode res = CURLE_OK; + char *input; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + + if(proxy) { + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->proxyuser; + ntlm = &conn->proxyntlm; + authp = &conn->data->state.authproxy; + } + else { + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + ntlm = &conn->ntlm; + authp = &conn->data->state.authhost; + } + authp->done = FALSE; + + /* not set means empty */ + if(!userp) + userp=""; + + switch(ntlm->state) { + case NTLMSTATE_TYPE1: + default: + /* Use Samba's 'winbind' daemon to support NTLM authentication, + * by delegating the NTLM challenge/response protocal to a helper + * in ntlm_auth. + * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html + * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html + * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html + * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this + * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute + * filename of ntlm_auth helper. + * If NTLM authentication using winbind fails, go back to original + * request handling process. + */ + /* Create communication with ntlm_auth */ + res = ntlm_wb_init(conn, userp); + if(res) + return res; + res = ntlm_wb_response(conn, "YR\n", ntlm->state); + if(res) + return res; + + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + proxy ? "Proxy-" : "", + conn->response_header); + DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); + free(conn->response_header); + conn->response_header = NULL; + break; + case NTLMSTATE_TYPE2: + input = aprintf("TT %s\n", conn->challenge_header); + if(!input) + return CURLE_OUT_OF_MEMORY; + res = ntlm_wb_response(conn, input, ntlm->state); + free(input); + input = NULL; + if(res) + return res; + + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + proxy ? "Proxy-" : "", + conn->response_header); + DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); + ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ + authp->done = TRUE; + Curl_ntlm_wb_cleanup(conn); + break; + case NTLMSTATE_TYPE3: + /* connection is already authenticated, + * don't send a header in future requests */ + free(*allocuserpwd); + *allocuserpwd=NULL; + authp->done = TRUE; + break; + } + + return CURLE_OK; +} + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ diff --git a/libcurl/src/lib/curl_ntlm_wb.h b/libcurl/src/lib/curl_ntlm_wb.h new file mode 100644 index 0000000..f4dd4e9 --- /dev/null +++ b/libcurl/src/lib/curl_ntlm_wb.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_NTLM_WB_H +#define HEADER_CURL_NTLM_WB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + +/* this is for creating ntlm header output by delegating challenge/response + to Samba's winbind daemon helper ntlm_auth */ +CURL_STATIC CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy); + +CURL_STATIC void Curl_ntlm_wb_cleanup(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ + +#endif /* HEADER_CURL_NTLM_WB_H */ diff --git a/libcurl/src/lib/curl_printf.h b/libcurl/src/lib/curl_printf.h new file mode 100644 index 0000000..086923f --- /dev/null +++ b/libcurl/src/lib/curl_printf.h @@ -0,0 +1,56 @@ +#ifndef HEADER_CURL_PRINTF_H +#define HEADER_CURL_PRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * This header should be included by ALL code in libcurl that uses any + * *rintf() functions. + */ + +#include + +# undef printf +# undef fprintf +# undef snprintf +# undef vprintf +# undef vfprintf +# undef vsnprintf +# undef aprintf +# undef vaprintf +# define printf curl_mprintf +# define fprintf curl_mfprintf +# define snprintf curl_msnprintf +# define vprintf curl_mvprintf +# define vfprintf curl_mvfprintf +# define vsnprintf curl_mvsnprintf +# define aprintf curl_maprintf +# define vaprintf curl_mvaprintf + +/* We define away the sprintf functions unconditonally since we don't want + internal code to be using them, intentionally or by mistake!*/ +# undef sprintf +# undef vsprintf +# define sprintf sprintf_was_used +# define vsprintf vsprintf_was_used + +#endif /* HEADER_CURL_PRINTF_H */ diff --git a/libcurl/src/lib/curl_rtmp.c b/libcurl/src/lib/curl_rtmp.c new file mode 100644 index 0000000..2938972 --- /dev/null +++ b/libcurl/src/lib/curl_rtmp.c @@ -0,0 +1,306 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2010, Howard Chu, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_LIBRTMP + +#include "urldata.h" +#include "nonblock.h" /* for curlx_nonblock */ +#include "progress.h" /* for Curl_pgrsSetUploadSize */ +#include "transfer.h" +#include "warnless.h" +#include +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifdef _WIN32 +#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) +#define SET_RCVTIMEO(tv,s) int tv = s*1000 +#else +#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} +#endif + +#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */ + +static CURLcode rtmp_setup_connection(struct connectdata *conn); +static CURLcode rtmp_do(struct connectdata *conn, bool *done); +static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature); +static CURLcode rtmp_connect(struct connectdata *conn, bool *done); +static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead); + +static Curl_recv rtmp_recv; +static Curl_send rtmp_send; + +/* + * RTMP protocol handler.h, based on http://rtmpdump.mplayerhq.hu + */ + +const struct Curl_handler Curl_handler_rtmp = { + "RTMP", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMP, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpt = { + "RTMPT", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPT, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpe = { + "RTMPE", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMPE, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpte = { + "RTMPTE", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPTE, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmps = { + "RTMPS", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPS, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpts = { + "RTMPTS", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPTS, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +static CURLcode rtmp_setup_connection(struct connectdata *conn) +{ + RTMP *r = RTMP_Alloc(); + if(!r) + return CURLE_OUT_OF_MEMORY; + + RTMP_Init(r); + RTMP_SetBufferMS(r, DEF_BUFTIME); + if(!RTMP_SetupURL(r, conn->data->change.url)) { + RTMP_Free(r); + return CURLE_URL_MALFORMAT; + } + conn->proto.generic = r; + return CURLE_OK; +} + +static CURLcode rtmp_connect(struct connectdata *conn, bool *done) +{ + RTMP *r = conn->proto.generic; + SET_RCVTIMEO(tv, 10); + + r->m_sb.sb_socket = conn->sock[FIRSTSOCKET]; + + /* We have to know if it's a write before we send the + * connect request packet + */ + if(conn->data->set.upload) + r->Link.protocol |= RTMP_FEATURE_WRITE; + + /* For plain streams, use the buffer toggle trick to keep data flowing */ + if(!(r->Link.lFlags & RTMP_LF_LIVE) && + !(r->Link.protocol & RTMP_FEATURE_HTTP)) + r->Link.lFlags |= RTMP_LF_BUFX; + + (void)curlx_nonblock(r->m_sb.sb_socket, FALSE); + setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, + (char *)&tv, sizeof(tv)); + + if(!RTMP_Connect1(r, NULL)) + return CURLE_FAILED_INIT; + + /* Clients must send a periodic BytesReceived report to the server */ + r->m_bSendCounter = true; + + *done = TRUE; + conn->recv[FIRSTSOCKET] = rtmp_recv; + conn->send[FIRSTSOCKET] = rtmp_send; + return CURLE_OK; +} + +static CURLcode rtmp_do(struct connectdata *conn, bool *done) +{ + RTMP *r = conn->proto.generic; + + if(!RTMP_ConnectStream(r, 0)) + return CURLE_FAILED_INIT; + + if(conn->data->set.upload) { + Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize); + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + } + else + Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + *done = TRUE; + return CURLE_OK; +} + +static CURLcode rtmp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void)conn; /* unused */ + (void)status; /* unused */ + (void)premature; /* unused */ + + return CURLE_OK; +} + +static CURLcode rtmp_disconnect(struct connectdata *conn, + bool dead_connection) +{ + RTMP *r = conn->proto.generic; + (void)dead_connection; + if(r) { + conn->proto.generic = NULL; + RTMP_Close(r); + RTMP_Free(r); + } + return CURLE_OK; +} + +static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, + size_t len, CURLcode *err) +{ + RTMP *r = conn->proto.generic; + ssize_t nread; + + (void)sockindex; /* unused */ + + nread = RTMP_Read(r, buf, curlx_uztosi(len)); + if(nread < 0) { + if(r->m_read.status == RTMP_READ_COMPLETE || + r->m_read.status == RTMP_READ_EOF) { + conn->data->req.size = conn->data->req.bytecount; + nread = 0; + } + else + *err = CURLE_RECV_ERROR; + } + return nread; +} + +static ssize_t rtmp_send(struct connectdata *conn, int sockindex, + const void *buf, size_t len, CURLcode *err) +{ + RTMP *r = conn->proto.generic; + ssize_t num; + + (void)sockindex; /* unused */ + + num = RTMP_Write(r, (char *)buf, curlx_uztosi(len)); + if(num < 0) + *err = CURLE_SEND_ERROR; + + return num; +} +#endif /* USE_LIBRTMP */ diff --git a/libcurl/src/lib/curl_rtmp.h b/libcurl/src/lib/curl_rtmp.h new file mode 100644 index 0000000..4a9e9e6 --- /dev/null +++ b/libcurl/src/lib/curl_rtmp.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_RTMP_H +#define HEADER_CURL_RTMP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Howard Chu, + * + * 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. + * + ***************************************************************************/ +#ifdef USE_LIBRTMP +extern const struct Curl_handler Curl_handler_rtmp; +extern const struct Curl_handler Curl_handler_rtmpt; +extern const struct Curl_handler Curl_handler_rtmpe; +extern const struct Curl_handler Curl_handler_rtmpte; +extern const struct Curl_handler Curl_handler_rtmps; +extern const struct Curl_handler Curl_handler_rtmpts; +#endif + +#endif /* HEADER_CURL_RTMP_H */ diff --git a/libcurl/src/lib/curl_sasl.c b/libcurl/src/lib/curl_sasl.c new file mode 100644 index 0000000..86a4af0 --- /dev/null +++ b/libcurl/src/lib/curl_sasl.c @@ -0,0 +1,1667 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2195 CRAM-MD5 authentication + * RFC2617 Basic and Digest Access Authentication + * RFC2831 DIGEST-MD5 authentication + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC6749 OAuth 2.0 Authorization Framework + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" + +#include "curl_base64.h" +#include "curl_md5.h" +#include "vtls/vtls.h" +#include "curl_hmac.h" +#include "curl_sasl.h" +#include "warnless.h" +#include "strtok.h" +#include "strequal.h" +#include "rawstr.h" +#include "sendf.h" +#include "non-ascii.h" /* included for Curl_convert_... prototypes */ +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Supported mechanisms */ +const struct { + const char *name; /* Name */ + size_t len; /* Name length */ + unsigned int bit; /* Flag bit */ +} mechtable[] = { + { "LOGIN", 5, SASL_MECH_LOGIN }, + { "PLAIN", 5, SASL_MECH_PLAIN }, + { "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 }, + { "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 }, + { "GSSAPI", 6, SASL_MECH_GSSAPI }, + { "EXTERNAL", 8, SASL_MECH_EXTERNAL }, + { "NTLM", 4, SASL_MECH_NTLM }, + { "XOAUTH2", 7, SASL_MECH_XOAUTH2 }, + { ZERO_NULL, 0, 0 } +}; + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI) +#define DIGEST_QOP_VALUE_AUTH (1 << 0) +#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1) +#define DIGEST_QOP_VALUE_AUTH_CONF (1 << 2) + +#define DIGEST_QOP_VALUE_STRING_AUTH "auth" +#define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int" +#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf" + +#define DIGEST_MAX_VALUE_LENGTH 256 +#define DIGEST_MAX_CONTENT_LENGTH 1024 + +/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines. + It converts digest text to ASCII so the MD5 will be correct for + what ultimately goes over the network. +*/ +#define CURL_OUTPUT_DIGEST_CONV(a, b) \ + result = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \ + if(result) { \ + free(b); \ + return result; \ + } + +/* + * Returns 0 on success and then the buffers are filled in fine. + * + * Non-zero means failure to parse. + */ +static int sasl_digest_get_pair(const char *str, char *value, char *content, + const char **endptr) +{ + int c; + bool starts_with_quote = FALSE; + bool escape = FALSE; + + for(c = DIGEST_MAX_VALUE_LENGTH - 1; (*str && (*str != '=') && c--); ) + *value++ = *str++; + *value = 0; + + if('=' != *str++) + /* eek, no match */ + return 1; + + if('\"' == *str) { + /* this starts with a quote so it must end with one as well! */ + str++; + starts_with_quote = TRUE; + } + + for(c = DIGEST_MAX_CONTENT_LENGTH - 1; *str && c--; str++) { + switch(*str) { + case '\\': + if(!escape) { + /* possibly the start of an escaped quote */ + escape = TRUE; + *content++ = '\\'; /* even though this is an escape character, we still + store it as-is in the target buffer */ + continue; + } + break; + case ',': + if(!starts_with_quote) { + /* this signals the end of the content if we didn't get a starting + quote and then we do "sloppy" parsing */ + c = 0; /* the end */ + continue; + } + break; + case '\r': + case '\n': + /* end of string */ + c = 0; + continue; + case '\"': + if(!escape && starts_with_quote) { + /* end of string */ + c = 0; + continue; + } + break; + } + escape = FALSE; + *content++ = *str; + } + *content = 0; + + *endptr = str; + + return 0; /* all is fine! */ +} + +/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/ +static void sasl_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */ + unsigned char *dest) /* 33 bytes */ +{ + int i; + for(i = 0; i < 16; i++) + snprintf((char *)&dest[i*2], 3, "%02x", source[i]); +} + +/* Perform quoted-string escaping as described in RFC2616 and its errata */ +static char *sasl_digest_string_quoted(const char *source) +{ + char *dest, *d; + const char *s = source; + size_t n = 1; /* null terminator */ + + /* Calculate size needed */ + while(*s) { + ++n; + if(*s == '"' || *s == '\\') { + ++n; + } + ++s; + } + + dest = malloc(n); + if(dest) { + s = source; + d = dest; + while(*s) { + if(*s == '"' || *s == '\\') { + *d++ = '\\'; + } + *d++ = *s++; + } + *d = 0; + } + + return dest; +} + +/* Retrieves the value for a corresponding key from the challenge string + * returns TRUE if the key could be found, FALSE if it does not exists + */ +static bool sasl_digest_get_key_value(const char *chlg, + const char *key, + char *value, + size_t max_val_len, + char end_char) +{ + char *find_pos; + size_t i; + + find_pos = strstr(chlg, key); + if(!find_pos) + return FALSE; + + find_pos += strlen(key); + + for(i = 0; *find_pos && *find_pos != end_char && i < max_val_len - 1; ++i) + value[i] = *find_pos++; + value[i] = '\0'; + + return TRUE; +} + +static CURLcode sasl_digest_get_qop_values(const char *options, int *value) +{ + char *tmp; + char *token; + char *tok_buf; + + /* Initialise the output */ + *value = 0; + + /* Tokenise the list of qop values. Use a temporary clone of the buffer since + strtok_r() ruins it. */ + tmp = strdup(options); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + token = strtok_r(tmp, ",", &tok_buf); + while(token != NULL) { + if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH)) + *value |= DIGEST_QOP_VALUE_AUTH; + else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) + *value |= DIGEST_QOP_VALUE_AUTH_INT; + else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF)) + *value |= DIGEST_QOP_VALUE_AUTH_CONF; + + token = strtok_r(NULL, ",", &tok_buf); + } + + free(tmp); + + return CURLE_OK; +} +#endif /* !CURL_DISABLE_CRYPTO_AUTH && !USE_WINDOWS_SSPI */ + +#if !defined(USE_WINDOWS_SSPI) +/* + * Curl_sasl_build_spn() + * + * This is used to build a SPN string in the format service/host. + * + * Parameters: + * + * service [in] - The service type such as www, smtp, pop or imap. + * host [in] - The host name or realm. + * + * Returns a pointer to the newly allocated SPN. + */ +CURL_STATIC char *Curl_sasl_build_spn(const char *service, const char *host) +{ + /* Generate and return our SPN */ + return aprintf("%s/%s", service, host); +} +#endif + +/* + * sasl_create_plain_message() + * + * This is used to generate an already encoded PLAIN message ready + * for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name. + * passdwp [in] - The user's password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +static CURLcode sasl_create_plain_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen) +{ + CURLcode result; + char *plainauth; + size_t ulen; + size_t plen; + + ulen = strlen(userp); + plen = strlen(passwdp); + + plainauth = malloc(2 * ulen + plen + 2); + if(!plainauth) { + *outlen = 0; + *outptr = NULL; + return CURLE_OUT_OF_MEMORY; + } + + /* Calculate the reply */ + memcpy(plainauth, userp, ulen); + plainauth[ulen] = '\0'; + memcpy(plainauth + ulen + 1, userp, ulen); + plainauth[2 * ulen + 1] = '\0'; + memcpy(plainauth + 2 * ulen + 2, passwdp, plen); + + /* Base64 encode the reply */ + result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr, + outlen); + free(plainauth); + return result; +} + +/* + * sasl_create_login_message() + * + * This is used to generate an already encoded LOGIN message containing the + * user name or password ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * valuep [in] - The user name or user's password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +static CURLcode sasl_create_login_message(struct SessionHandle *data, + const char *valuep, char **outptr, + size_t *outlen) +{ + size_t vlen = strlen(valuep); + + if(!vlen) { + /* Calculate an empty reply */ + *outptr = strdup("="); + if(*outptr) { + *outlen = (size_t) 1; + return CURLE_OK; + } + + *outlen = 0; + return CURLE_OUT_OF_MEMORY; + } + + /* Base64 encode the value */ + return Curl_base64_encode(data, valuep, vlen, outptr, outlen); +} + +/* + * sasl_create_external_message() + * + * This is used to generate an already encoded EXTERNAL message containing + * the user name ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * user [in] - The user name. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +static CURLcode sasl_create_external_message(struct SessionHandle *data, + const char *user, char **outptr, + size_t *outlen) +{ + /* This is the same formatting as the login message. */ + return sasl_create_login_message(data, user, outptr, outlen); +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH + /* + * sasl_decode_cram_md5_message() + * + * This is used to decode an already encoded CRAM-MD5 challenge message. + * + * Parameters: + * + * chlg64 [in] - The base64 encoded challenge message. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +static CURLcode sasl_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlg64len = strlen(chlg64); + + *outptr = NULL; + *outlen = 0; + + /* Decode the challenge if necessary */ + if(chlg64len && *chlg64 != '=') + result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen); + + return result; + } + + /* + * sasl_create_cram_md5_message() + * + * This is used to generate an already encoded CRAM-MD5 response message ready + * for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg [in] - The challenge. + * userp [in] - The user name. + * passdwp [in] - The user's password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +static CURLcode sasl_create_cram_md5_message(struct SessionHandle *data, + const char *chlg, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + HMAC_context *ctxt; + unsigned char digest[MD5_DIGEST_LEN]; + char *response; + + if(chlg) + chlglen = strlen(chlg); + + /* Compute the digest using the password as the key */ + ctxt = Curl_HMAC_init(Curl_HMAC_MD5, + (const unsigned char *) passwdp, + curlx_uztoui(strlen(passwdp))); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + /* Update the digest with the given challenge */ + if(chlglen > 0) + Curl_HMAC_update(ctxt, (const unsigned char *) chlg, + curlx_uztoui(chlglen)); + + /* Finalise the digest */ + Curl_HMAC_final(ctxt, digest); + + /* Generate the response */ + response = aprintf( + "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + userp, digest[0], digest[1], digest[2], digest[3], digest[4], + digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], + digest[11], digest[12], digest[13], digest[14], digest[15]); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the response */ + result = Curl_base64_encode(data, response, 0, outptr, outlen); + + free(response); + + return result; +} + +#ifndef USE_WINDOWS_SSPI +/* + * sasl_decode_digest_md5_message() + * + * This is used internally to decode an already encoded DIGEST-MD5 challenge + * message into the seperate attributes. + * + * Parameters: + * + * chlg64 [in] - The base64 encoded challenge message. + * nonce [in/out] - The buffer where the nonce will be stored. + * nlen [in] - The length of the nonce buffer. + * realm [in/out] - The buffer where the realm will be stored. + * rlen [in] - The length of the realm buffer. + * alg [in/out] - The buffer where the algorithm will be stored. + * alen [in] - The length of the algorithm buffer. + * qop [in/out] - The buffer where the qop-options will be stored. + * qlen [in] - The length of the qop buffer. + * + * Returns CURLE_OK on success. + */ +static CURLcode sasl_decode_digest_md5_message(const char *chlg64, + char *nonce, size_t nlen, + char *realm, size_t rlen, + char *alg, size_t alen, + char *qop, size_t qlen) +{ + CURLcode result = CURLE_OK; + unsigned char *chlg = NULL; + size_t chlglen = 0; + size_t chlg64len = strlen(chlg64); + + /* Decode the base-64 encoded challenge message */ + if(chlg64len && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) + return CURLE_BAD_CONTENT_ENCODING; + + /* Retrieve nonce string from the challenge */ + if(!sasl_digest_get_key_value((char *)chlg, "nonce=\"", nonce, nlen, '\"')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Retrieve realm string from the challenge */ + if(!sasl_digest_get_key_value((char *)chlg, "realm=\"", realm, rlen, '\"')) { + /* Challenge does not have a realm, set empty string [RFC2831] page 6 */ + strcpy(realm, ""); + } + + /* Retrieve algorithm string from the challenge */ + if(!sasl_digest_get_key_value((char *)chlg, "algorithm=", alg, alen, ',')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Retrieve qop-options string from the challenge */ + if(!sasl_digest_get_key_value((char *)chlg, "qop=\"", qop, qlen, '\"')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + free(chlg); + + return CURLE_OK; +} + +/* + * Curl_sasl_create_digest_md5_message() + * + * This is used to generate an already encoded DIGEST-MD5 response message + * ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - The base64 encoded challenge message. + * userp [in] - The user name. + * passdwp [in] - The user's password. + * service [in] - The service type such as www, smtp, pop or imap. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t i; + MD5_context *ctxt; + char *response = NULL; + unsigned char digest[MD5_DIGEST_LEN]; + char HA1_hex[2 * MD5_DIGEST_LEN + 1]; + char HA2_hex[2 * MD5_DIGEST_LEN + 1]; + char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; + char nonce[64]; + char realm[128]; + char algorithm[64]; + char qop_options[64]; + int qop_values; + char cnonce[33]; + unsigned int entropy[4]; + char nonceCount[] = "00000001"; + char method[] = "AUTHENTICATE"; + char qop[] = DIGEST_QOP_VALUE_STRING_AUTH; + char *spn = NULL; + + /* Decode the challange message */ + result = sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce), + realm, sizeof(realm), + algorithm, sizeof(algorithm), + qop_options, sizeof(qop_options)); + if(result) + return result; + + /* We only support md5 sessions */ + if(strcmp(algorithm, "md5-sess") != 0) + return CURLE_BAD_CONTENT_ENCODING; + + /* Get the qop-values from the qop-options */ + result = sasl_digest_get_qop_values(qop_options, &qop_values); + if(result) + return result; + + /* We only support auth quality-of-protection */ + if(!(qop_values & DIGEST_QOP_VALUE_AUTH)) + return CURLE_BAD_CONTENT_ENCODING; + + /* Generate 16 bytes of random data */ + entropy[0] = Curl_rand(data); + entropy[1] = Curl_rand(data); + entropy[2] = Curl_rand(data); + entropy[3] = Curl_rand(data); + + /* Convert the random data into a 32 byte hex string */ + snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x", + entropy[0], entropy[1], entropy[2], entropy[3]); + + /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) userp, + curlx_uztoui(strlen(userp))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) realm, + curlx_uztoui(strlen(realm))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) passwdp, + curlx_uztoui(strlen(passwdp))); + Curl_MD5_final(ctxt, digest); + + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) nonce, + curlx_uztoui(strlen(nonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) cnonce, + curlx_uztoui(strlen(cnonce))); + Curl_MD5_final(ctxt, digest); + + /* Convert calculated 16 octet hex into 32 bytes string */ + for(i = 0; i < MD5_DIGEST_LEN; i++) + snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]); + + /* Generate our SPN */ + spn = Curl_sasl_build_spn(service, realm); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Calculate H(A2) */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) { + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + Curl_MD5_update(ctxt, (const unsigned char *) method, + curlx_uztoui(strlen(method))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) spn, + curlx_uztoui(strlen(spn))); + Curl_MD5_final(ctxt, digest); + + for(i = 0; i < MD5_DIGEST_LEN; i++) + snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]); + + /* Now calculate the response hash */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) { + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) nonce, + curlx_uztoui(strlen(nonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + + Curl_MD5_update(ctxt, (const unsigned char *) nonceCount, + curlx_uztoui(strlen(nonceCount))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) cnonce, + curlx_uztoui(strlen(cnonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) qop, + curlx_uztoui(strlen(qop))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + + Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN); + Curl_MD5_final(ctxt, digest); + + for(i = 0; i < MD5_DIGEST_LEN; i++) + snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); + + /* Generate the response */ + response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\"," + "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s," + "qop=%s", + userp, realm, nonce, + cnonce, nonceCount, spn, resp_hash_hex, qop); + free(spn); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the response */ + result = Curl_base64_encode(data, response, 0, outptr, outlen); + + free(response); + + return result; +} + +/* + * Curl_sasl_decode_digest_http_message() + * + * This is used to decode a HTTP DIGEST challenge message into the seperate + * attributes. + * + * Parameters: + * + * chlg [in] - The challenge message. + * digest [in/out] - The digest data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_sasl_decode_digest_http_message(const char *chlg, + struct digestdata *digest) +{ + bool before = FALSE; /* got a nonce before */ + bool foundAuth = FALSE; + bool foundAuthInt = FALSE; + char *token = NULL; + char *tmp = NULL; + + /* If we already have received a nonce, keep that in mind */ + if(digest->nonce) + before = TRUE; + + /* Clean up any former leftovers and initialise to defaults */ + Curl_sasl_digest_cleanup(digest); + + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Extract a value=content pair */ + if(!sasl_digest_get_pair(chlg, value, content, &chlg)) { + if(Curl_raw_equal(value, "nonce")) { + digest->nonce = strdup(content); + if(!digest->nonce) + return CURLE_OUT_OF_MEMORY; + } + else if(Curl_raw_equal(value, "stale")) { + if(Curl_raw_equal(content, "true")) { + digest->stale = TRUE; + digest->nc = 1; /* we make a new nonce now */ + } + } + else if(Curl_raw_equal(value, "realm")) { + digest->realm = strdup(content); + if(!digest->realm) + return CURLE_OUT_OF_MEMORY; + } + else if(Curl_raw_equal(value, "opaque")) { + digest->opaque = strdup(content); + if(!digest->opaque) + return CURLE_OUT_OF_MEMORY; + } + else if(Curl_raw_equal(value, "qop")) { + char *tok_buf; + /* Tokenize the list and choose auth if possible, use a temporary + clone of the buffer since strtok_r() ruins it */ + tmp = strdup(content); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + token = strtok_r(tmp, ",", &tok_buf); + while(token != NULL) { + if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH)) { + foundAuth = TRUE; + } + else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) { + foundAuthInt = TRUE; + } + token = strtok_r(NULL, ",", &tok_buf); + } + + free(tmp); + + /* Select only auth or auth-int. Otherwise, ignore */ + if(foundAuth) { + digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH); + if(!digest->qop) + return CURLE_OUT_OF_MEMORY; + } + else if(foundAuthInt) { + digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH_INT); + if(!digest->qop) + return CURLE_OUT_OF_MEMORY; + } + } + else if(Curl_raw_equal(value, "algorithm")) { + digest->algorithm = strdup(content); + if(!digest->algorithm) + return CURLE_OUT_OF_MEMORY; + + if(Curl_raw_equal(content, "MD5-sess")) + digest->algo = CURLDIGESTALGO_MD5SESS; + else if(Curl_raw_equal(content, "MD5")) + digest->algo = CURLDIGESTALGO_MD5; + else + return CURLE_BAD_CONTENT_ENCODING; + } + else { + /* unknown specifier, ignore it! */ + } + } + else + break; /* we're done here */ + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Allow the list to be comma-separated */ + if(',' == *chlg) + chlg++; + } + + /* We had a nonce since before, and we got another one now without + 'stale=true'. This means we provided bad credentials in the previous + request */ + if(before && !digest->stale) + return CURLE_BAD_CONTENT_ENCODING; + + /* We got this header without a nonce, that's a bad Digest line! */ + if(!digest->nonce) + return CURLE_BAD_CONTENT_ENCODING; + + return CURLE_OK; +} + +/* + * Curl_sasl_create_digest_http_message() + * + * This is used to generate a HTTP DIGEST response message ready for sending + * to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name. + * passdwp [in] - The user's password. + * request [in] - The HTTP request. + * uripath [in] - The path of the HTTP uri. + * digest [in/out] - The digest data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uripath, + struct digestdata *digest, + char **outptr, size_t *outlen) +{ + CURLcode result; + unsigned char md5buf[16]; /* 16 bytes/128 bits */ + unsigned char request_digest[33]; + unsigned char *md5this; + unsigned char ha1[33];/* 32 digits and 1 zero byte */ + unsigned char ha2[33];/* 32 digits and 1 zero byte */ + char cnoncebuf[33]; + char *cnonce = NULL; + size_t cnonce_sz = 0; + char *userp_quoted; + char *response = NULL; + char *tmp = NULL; + + if(!digest->nc) + digest->nc = 1; + + if(!digest->cnonce) { + snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x", + Curl_rand(data), Curl_rand(data), + Curl_rand(data), Curl_rand(data)); + + result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), + &cnonce, &cnonce_sz); + if(result) + return result; + + digest->cnonce = cnonce; + } + + /* + if the algorithm is "MD5" or unspecified (which then defaults to MD5): + + A1 = unq(username-value) ":" unq(realm-value) ":" passwd + + if the algorithm is "MD5-sess" then: + + A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd ) + ":" unq(nonce-value) ":" unq(cnonce-value) + */ + + md5this = (unsigned char *) + aprintf("%s:%s:%s", userp, digest->realm, passwdp); + if(!md5this) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ + Curl_md5it(md5buf, md5this); + free(md5this); + sasl_digest_md5_to_ascii(md5buf, ha1); + + if(digest->algo == CURLDIGESTALGO_MD5SESS) { + /* nonce and cnonce are OUTSIDE the hash */ + tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */ + Curl_md5it(md5buf, (unsigned char *)tmp); + free(tmp); + sasl_digest_md5_to_ascii(md5buf, ha1); + } + + /* + If the "qop" directive's value is "auth" or is unspecified, then A2 is: + + A2 = Method ":" digest-uri-value + + If the "qop" value is "auth-int", then A2 is: + + A2 = Method ":" digest-uri-value ":" H(entity-body) + + (The "Method" value is the HTTP request method as specified in section + 5.1.1 of RFC 2616) + */ + + md5this = (unsigned char *)aprintf("%s:%s", request, uripath); + + if(digest->qop && Curl_raw_equal(digest->qop, "auth-int")) { + /* We don't support auth-int for PUT or POST at the moment. + TODO: replace md5 of empty string with entity-body for PUT/POST */ + unsigned char *md5this2 = (unsigned char *) + aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e"); + free(md5this); + md5this = md5this2; + } + + if(!md5this) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ + Curl_md5it(md5buf, md5this); + free(md5this); + sasl_digest_md5_to_ascii(md5buf, ha2); + + if(digest->qop) { + md5this = (unsigned char *)aprintf("%s:%s:%08x:%s:%s:%s", + ha1, + digest->nonce, + digest->nc, + digest->cnonce, + digest->qop, + ha2); + } + else { + md5this = (unsigned char *)aprintf("%s:%s:%s", + ha1, + digest->nonce, + ha2); + } + + if(!md5this) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ + Curl_md5it(md5buf, md5this); + free(md5this); + sasl_digest_md5_to_ascii(md5buf, request_digest); + + /* for test case 64 (snooped from a Mozilla 1.3a request) + + Authorization: Digest username="testuser", realm="testrealm", \ + nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca" + + Digest parameters are all quoted strings. Username which is provided by + the user will need double quotes and backslashes within it escaped. For + the other fields, this shouldn't be an issue. realm, nonce, and opaque + are copied as is from the server, escapes and all. cnonce is generated + with web-safe characters. uri is already percent encoded. nc is 8 hex + characters. algorithm and qop with standard values only contain web-safe + chracters. + */ + userp_quoted = sasl_digest_string_quoted(userp); + if(!userp_quoted) + return CURLE_OUT_OF_MEMORY; + + if(digest->qop) { + response = aprintf("username=\"%s\", " + "realm=\"%s\", " + "nonce=\"%s\", " + "uri=\"%s\", " + "cnonce=\"%s\", " + "nc=%08x, " + "qop=%s, " + "response=\"%s\"", + userp_quoted, + digest->realm, + digest->nonce, + uripath, + digest->cnonce, + digest->nc, + digest->qop, + request_digest); + + if(Curl_raw_equal(digest->qop, "auth")) + digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0 + padded which tells to the server how many times you are + using the same nonce in the qop=auth mode */ + } + else { + response = aprintf("username=\"%s\", " + "realm=\"%s\", " + "nonce=\"%s\", " + "uri=\"%s\", " + "response=\"%s\"", + userp_quoted, + digest->realm, + digest->nonce, + uripath, + request_digest); + } + free(userp_quoted); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Add the optional fields */ + if(digest->opaque) { + /* Append the opaque */ + tmp = aprintf("%s, opaque=\"%s\"", response, digest->opaque); + free(response); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + response = tmp; + } + + if(digest->algorithm) { + /* Append the algorithm */ + tmp = aprintf("%s, algorithm=\"%s\"", response, digest->algorithm); + free(response); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + response = tmp; + } + + /* Return the output */ + *outptr = response; + *outlen = strlen(response); + + return CURLE_OK; +} + +/* + * Curl_sasl_digest_cleanup() + * + * This is used to clean up the digest specific data. + * + * Parameters: + * + * digest [in/out] - The digest data struct being cleaned up. + * + */ +CURL_STATIC void Curl_sasl_digest_cleanup(struct digestdata *digest) +{ + Curl_safefree(digest->nonce); + Curl_safefree(digest->cnonce); + Curl_safefree(digest->realm); + Curl_safefree(digest->opaque); + Curl_safefree(digest->qop); + Curl_safefree(digest->algorithm); + + digest->nc = 0; + digest->algo = CURLDIGESTALGO_MD5; /* default algorithm */ + digest->stale = FALSE; /* default means normal, not stale */ +} +#endif /* !USE_WINDOWS_SSPI */ + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ + +#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI) +/* + * Curl_sasl_ntlm_cleanup() + * + * This is used to clean up the ntlm specific data. + * + * Parameters: + * + * ntlm [in/out] - The ntlm data struct being cleaned up. + * + */ +CURL_STATIC void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm) +{ + /* Free the target info */ + Curl_safefree(ntlm->target_info); + + /* Reset any variables */ + ntlm->target_info_len = 0; + } +#endif /* USE_NTLM && !USE_WINDOWS_SSPI*/ + +/* + * sasl_create_xoauth2_message() + * + * This is used to generate an already encoded OAuth 2.0 message ready for + * sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * user [in] - The user name. + * bearer [in] - The bearer token. + * 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. + */ +static CURLcode sasl_create_xoauth2_message(struct SessionHandle *data, + const char *user, + const char *bearer, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + char *xoauth = NULL; + + /* Generate the message */ + xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer); + if(!xoauth) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the reply */ + result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen); + + free(xoauth); + + return result; +} + +/* + * Curl_sasl_cleanup() + * + * This is used to cleanup any libraries or curl modules used by the sasl + * functions. + * + * Parameters: + * + * conn [in] - The connection data. + * authused [in] - The authentication mechanism used. + */ +CURL_STATIC void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) +{ +#if defined(USE_KERBEROS5) + /* Cleanup the gssapi structure */ + if(authused == SASL_MECH_GSSAPI) { + Curl_sasl_gssapi_cleanup(&conn->krb5); + } +#endif + +#if defined(USE_NTLM) + /* Cleanup the ntlm structure */ + if(authused == SASL_MECH_NTLM) { + Curl_ntlm_sspi_cleanup(&conn->ntlm); + } +#endif + +#if !defined(USE_KERBEROS5) && !defined(USE_NTLM) + /* Reserved for future use */ + (void)conn; + (void)authused; +#endif +} + +/* + * Curl_sasl_decode_mech() + * + * Convert a SASL mechanism name into a token. + * + * Parameters: + * + * ptr [in] - The mechanism string. + * maxlen [in] - Maximum mechanism string length. + * len [out] - If not NULL, effective name length. + * + * Returns the SASL mechanism token or 0 if no match. + */ +CURL_STATIC unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len) +{ + unsigned int i; + char c; + + for(i = 0; mechtable[i].name; i++) { + if(maxlen >= mechtable[i].len && + !memcmp(ptr, mechtable[i].name, mechtable[i].len)) { + if(len) + *len = mechtable[i].len; + + if(maxlen == mechtable[i].len) + return mechtable[i].bit; + + c = ptr[mechtable[i].len]; + if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_') + return mechtable[i].bit; + } + } + + return 0; +} + +/* + * Curl_sasl_parse_url_auth_option() + * + * Parse the URL login options. + */ +CURL_STATIC CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, + const char *value, size_t len) +{ + CURLcode result = CURLE_OK; + unsigned int mechbit; + size_t mechlen; + + if(!len) + return CURLE_URL_MALFORMAT; + + if(sasl->resetprefs) { + sasl->resetprefs = FALSE; + sasl->prefmech = SASL_AUTH_NONE; + } + + if(strnequal(value, "*", len)) + sasl->prefmech = SASL_AUTH_DEFAULT; + else if((mechbit = Curl_sasl_decode_mech(value, len, &mechlen)) && + mechlen == len) + sasl->prefmech |= mechbit; + else + result = CURLE_URL_MALFORMAT; + + return result; +} + +/* + * Curl_sasl_init() + * + * Initializes the SASL structure. + */ +CURL_STATIC void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params) +{ + sasl->params = params; /* Set protocol dependent parameters */ + sasl->state = SASL_STOP; /* Not yet running */ + sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */ + sasl->prefmech = SASL_AUTH_DEFAULT; /* Prefer all mechanisms */ + sasl->authused = SASL_AUTH_NONE; /* No the authentication mechanism used */ + sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */ + sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */ + sasl->force_ir = FALSE; /* Respect external option */ +} + +/* + * state() + * + * This is the ONLY way to change SASL state! + */ +static void state(struct SASL *sasl, struct connectdata *conn, + saslstate newstate) +{ +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[]={ + "STOP", + "PLAIN", + "LOGIN", + "LOGIN_PASSWD", + "EXTERNAL", + "CRAMMD5", + "DIGESTMD5", + "DIGESTMD5_RESP", + "NTLM", + "NTLM_TYPE2MSG", + "GSSAPI", + "GSSAPI_TOKEN", + "GSSAPI_NO_DATA", + "XOAUTH2", + "CANCEL", + "FINAL", + /* LAST */ + }; + + if(sasl->state != newstate) + infof(conn->data, "SASL %p state change from %s to %s\n", + (void *)sasl, names[sasl->state], names[newstate]); +#else + (void) conn; +#endif + + sasl->state = newstate; +} + +/* + * Curl_sasl_can_authenticate() + * + * Check if we have enough auth data and capabilities to authenticate. + */ +CURL_STATIC bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn) +{ + /* Have credentials been provided? */ + if(conn->bits.user_passwd) + return TRUE; + + /* EXTERNAL can authenticate without a user name and/or password */ + if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL) + return TRUE; + + return FALSE; +} + +/* + * Curl_sasl_start() + * + * Calculate the required login details for SASL authentication. + */ +CURL_STATIC CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, + bool force_ir, saslprogress *progress) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + unsigned int enabledmechs; + const char *mech = NULL; + char *resp = NULL; + size_t len = 0; + saslstate state1 = SASL_STOP; + saslstate state2 = SASL_FINAL; + + sasl->force_ir = force_ir; /* Latch for future use */ + sasl->authused = 0; /* No mechanism used yet */ + enabledmechs = sasl->authmechs & sasl->prefmech; + *progress = SASL_IDLE; + + /* Calculate the supported authentication mechanism, by decreasing order of + security, as well as the initial response where appropriate */ + if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) { + mech = SASL_MECH_STRING_EXTERNAL; + state1 = SASL_EXTERNAL; + sasl->authused = SASL_MECH_EXTERNAL; + + if(force_ir || data->set.sasl_ir) + result = sasl_create_external_message(data, conn->user, &resp, &len); + } + else if(conn->bits.user_passwd) { +#if defined(USE_KERBEROS5) + if(enabledmechs & SASL_MECH_GSSAPI) { + sasl->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */ + mech = SASL_MECH_STRING_GSSAPI; + state1 = SASL_GSSAPI; + state2 = SASL_GSSAPI_TOKEN; + sasl->authused = SASL_MECH_GSSAPI; + + if(force_ir || data->set.sasl_ir) + result = Curl_sasl_create_gssapi_user_message(data, conn->user, + conn->passwd, + sasl->params->service, + sasl->mutual_auth, + NULL, &conn->krb5, + &resp, &len); + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(enabledmechs & SASL_MECH_DIGEST_MD5) { + mech = SASL_MECH_STRING_DIGEST_MD5; + state1 = SASL_DIGESTMD5; + sasl->authused = SASL_MECH_DIGEST_MD5; + } + else if(enabledmechs & SASL_MECH_CRAM_MD5) { + mech = SASL_MECH_STRING_CRAM_MD5; + state1 = SASL_CRAMMD5; + sasl->authused = SASL_MECH_CRAM_MD5; + } + else +#endif +#ifdef USE_NTLM + if(enabledmechs & SASL_MECH_NTLM) { + mech = SASL_MECH_STRING_NTLM; + state1 = SASL_NTLM; + state2 = SASL_NTLM_TYPE2MSG; + sasl->authused = SASL_MECH_NTLM; + + if(force_ir || data->set.sasl_ir) + result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, + &conn->ntlm, &resp, &len); + } + else +#endif + if((enabledmechs & SASL_MECH_XOAUTH2) || conn->xoauth2_bearer) { + mech = SASL_MECH_STRING_XOAUTH2; + state1 = SASL_XOAUTH2; + sasl->authused = SASL_MECH_XOAUTH2; + + if(force_ir || data->set.sasl_ir) + result = sasl_create_xoauth2_message(data, conn->user, + conn->xoauth2_bearer, + &resp, &len); + } + else if(enabledmechs & SASL_MECH_LOGIN) { + mech = SASL_MECH_STRING_LOGIN; + state1 = SASL_LOGIN; + state2 = SASL_LOGIN_PASSWD; + sasl->authused = SASL_MECH_LOGIN; + + if(force_ir || data->set.sasl_ir) + result = sasl_create_login_message(data, conn->user, &resp, &len); + } + else if(enabledmechs & SASL_MECH_PLAIN) { + mech = SASL_MECH_STRING_PLAIN; + state1 = SASL_PLAIN; + sasl->authused = SASL_MECH_PLAIN; + + if(force_ir || data->set.sasl_ir) + result = sasl_create_plain_message(data, conn->user, conn->passwd, + &resp, &len); + } + } + + if(!result) { + if(resp && sasl->params->maxirlen && + strlen(mech) + len > sasl->params->maxirlen) { + free(resp); + resp = NULL; + } + + if(mech) { + result = sasl->params->sendauth(conn, mech, resp); + if(!result) { + *progress = SASL_INPROGRESS; + state(sasl, conn, resp? state2: state1); + } + } + } + + free(resp); + + return result; +} + +/* + * Curl_sasl_continue() + * + * Continue the authentication. + */ +CURL_STATIC CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, + int code, saslprogress *progress) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + saslstate newstate = SASL_FINAL; + char *resp = NULL; +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + char *serverdata; + char *chlg = NULL; + size_t chlglen = 0; +#endif + size_t len = 0; + + *progress = SASL_INPROGRESS; + + if(sasl->state == SASL_FINAL) { + if(code != sasl->params->finalcode) + result = CURLE_LOGIN_DENIED; + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return result; + } + + if(sasl->state != SASL_CANCEL && code != sasl->params->contcode) { + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return CURLE_LOGIN_DENIED; + } + + switch(sasl->state) { + case SASL_STOP: + *progress = SASL_DONE; + return result; + case SASL_PLAIN: + result = sasl_create_plain_message(data, conn->user, conn->passwd, &resp, + &len); + break; + case SASL_LOGIN: + result = sasl_create_login_message(data, conn->user, &resp, &len); + newstate = SASL_LOGIN_PASSWD; + break; + case SASL_LOGIN_PASSWD: + result = sasl_create_login_message(data, conn->passwd, &resp, &len); + break; + case SASL_EXTERNAL: + result = sasl_create_external_message(data, conn->user, &resp, &len); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case SASL_CRAMMD5: + sasl->params->getmessage(data->state.buffer, &serverdata); + result = sasl_decode_cram_md5_message(serverdata, &chlg, &chlglen); + if(!result) + result = sasl_create_cram_md5_message(data, chlg, conn->user, + conn->passwd, &resp, &len); + free(chlg); + break; + case SASL_DIGESTMD5: + sasl->params->getmessage(data->state.buffer, &serverdata); + result = Curl_sasl_create_digest_md5_message(data, serverdata, + conn->user, conn->passwd, + sasl->params->service, + &resp, &len); + newstate = SASL_DIGESTMD5_RESP; + break; + case SASL_DIGESTMD5_RESP: + if(!(resp = strdup(""))) + result = CURLE_OUT_OF_MEMORY; + break; +#endif + +#ifdef USE_NTLM + case SASL_NTLM: + /* Create the type-1 message */ + result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, + &conn->ntlm, &resp, &len); + newstate = SASL_NTLM_TYPE2MSG; + break; + case SASL_NTLM_TYPE2MSG: + /* Decode the type-2 message */ + sasl->params->getmessage(data->state.buffer, &serverdata); + result = Curl_sasl_decode_ntlm_type2_message(data, serverdata, + &conn->ntlm); + if(!result) + result = Curl_sasl_create_ntlm_type3_message(data, conn->user, + conn->passwd, &conn->ntlm, + &resp, &len); + break; +#endif + +#if defined(USE_KERBEROS5) + case SASL_GSSAPI: + result = Curl_sasl_create_gssapi_user_message(data, conn->user, + conn->passwd, + sasl->params->service, + sasl->mutual_auth, NULL, + &conn->krb5, + &resp, &len); + newstate = SASL_GSSAPI_TOKEN; + break; + case SASL_GSSAPI_TOKEN: + sasl->params->getmessage(data->state.buffer, &serverdata); + if(sasl->mutual_auth) { + /* Decode the user token challenge and create the optional response + message */ + result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL, + sasl->mutual_auth, + serverdata, &conn->krb5, + &resp, &len); + newstate = SASL_GSSAPI_NO_DATA; + } + else + /* Decode the security challenge and create the response message */ + result = Curl_sasl_create_gssapi_security_message(data, serverdata, + &conn->krb5, + &resp, &len); + break; + case SASL_GSSAPI_NO_DATA: + sasl->params->getmessage(data->state.buffer, &serverdata); + /* Decode the security challenge and create the response message */ + result = Curl_sasl_create_gssapi_security_message(data, serverdata, + &conn->krb5, + &resp, &len); + break; +#endif + + case SASL_XOAUTH2: + /* Create the authorisation message */ + result = sasl_create_xoauth2_message(data, conn->user, + conn->xoauth2_bearer, &resp, &len); + break; + case SASL_CANCEL: + /* Remove the offending mechanism from the supported list */ + sasl->authmechs ^= sasl->authused; + + /* Start an alternative SASL authentication */ + result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress); + newstate = sasl->state; /* Use state from Curl_sasl_start() */ + break; + default: + failf(data, "Unsupported SASL authentication mechanism"); + result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ + break; + } + + switch(result) { + case CURLE_BAD_CONTENT_ENCODING: + /* Cancel dialog */ + result = sasl->params->sendcont(conn, "*"); + newstate = SASL_CANCEL; + break; + case CURLE_OK: + if(resp) + result = sasl->params->sendcont(conn, resp); + break; + default: + newstate = SASL_STOP; /* Stop on error */ + *progress = SASL_DONE; + break; + } + + free(resp); + + state(sasl, conn, newstate); + + return result; +} diff --git a/libcurl/src/lib/curl_sasl.h b/libcurl/src/lib/curl_sasl.h new file mode 100644 index 0000000..ce0abbc --- /dev/null +++ b/libcurl/src/lib/curl_sasl.h @@ -0,0 +1,245 @@ +#ifndef HEADER_CURL_SASL_H +#define HEADER_CURL_SASL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +struct SessionHandle; +struct connectdata; + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +struct digestdata; +#endif + +#if defined(USE_NTLM) +struct ntlmdata; +#endif + +#if defined(USE_KERBEROS5) +struct kerberos5data; +#endif + +/* Authentication mechanism flags */ +#define SASL_MECH_LOGIN (1 << 0) +#define SASL_MECH_PLAIN (1 << 1) +#define SASL_MECH_CRAM_MD5 (1 << 2) +#define SASL_MECH_DIGEST_MD5 (1 << 3) +#define SASL_MECH_GSSAPI (1 << 4) +#define SASL_MECH_EXTERNAL (1 << 5) +#define SASL_MECH_NTLM (1 << 6) +#define SASL_MECH_XOAUTH2 (1 << 7) + +/* Authentication mechanism values */ +#define SASL_AUTH_NONE 0 +#define SASL_AUTH_ANY ~0U +#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & \ + ~(SASL_MECH_EXTERNAL | SASL_MECH_XOAUTH2)) + +/* Authentication mechanism strings */ +#define SASL_MECH_STRING_LOGIN "LOGIN" +#define SASL_MECH_STRING_PLAIN "PLAIN" +#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5" +#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5" +#define SASL_MECH_STRING_GSSAPI "GSSAPI" +#define SASL_MECH_STRING_EXTERNAL "EXTERNAL" +#define SASL_MECH_STRING_NTLM "NTLM" +#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2" + +enum { + CURLDIGESTALGO_MD5, + CURLDIGESTALGO_MD5SESS +}; + +/* SASL machine states */ +typedef enum { + SASL_STOP, + SASL_PLAIN, + SASL_LOGIN, + SASL_LOGIN_PASSWD, + SASL_EXTERNAL, + SASL_CRAMMD5, + SASL_DIGESTMD5, + SASL_DIGESTMD5_RESP, + SASL_NTLM, + SASL_NTLM_TYPE2MSG, + SASL_GSSAPI, + SASL_GSSAPI_TOKEN, + SASL_GSSAPI_NO_DATA, + SASL_XOAUTH2, + SASL_CANCEL, + SASL_FINAL +} saslstate; + +/* Progress indicator */ +typedef enum { + SASL_IDLE, + SASL_INPROGRESS, + SASL_DONE +} saslprogress; + +/* Protocol dependent SASL parameters */ +struct SASLproto { + const char *service; /* The service name */ + int contcode; /* Code to receive when continuation is expected */ + int finalcode; /* Code to receive upon authentication success */ + size_t maxirlen; /* Maximum initial response length */ + CURLcode (*sendauth)(struct connectdata *conn, + const char *mech, const char *ir); + /* Send authentication command */ + CURLcode (*sendcont)(struct connectdata *conn, const char *contauth); + /* Send authentication continuation */ + void (*getmessage)(char *buffer, char **outptr); + /* Get SASL response message */ +}; + +/* Per-connection parameters */ +struct SASL { + const struct SASLproto *params; /* Protocol dependent parameters */ + saslstate state; /* Current machine state */ + unsigned int authmechs; /* Accepted authentication mechanisms */ + unsigned int prefmech; /* Preferred authentication mechanism */ + unsigned int authused; /* Auth mechanism used for the connection */ + bool resetprefs; /* For URL auth option parsing. */ + bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ + bool force_ir; /* Protocol always supports initial response */ +}; + +/* This is used to test whether the line starts with the given mechanism */ +#define sasl_mech_equal(line, wordlen, mech) \ + (wordlen == (sizeof(mech) - 1) / sizeof(char) && \ + !memcmp(line, mech, wordlen)) + +/* This is used to build a SPN string */ +#if !defined(USE_WINDOWS_SSPI) +CURL_STATIC char *Curl_sasl_build_spn(const char *service, const char *instance); +#else +CURL_STATIC TCHAR *Curl_sasl_build_spn(const char *service, const char *instance); +#endif + +#if defined(HAVE_GSSAPI) +CURL_STATIC char *Curl_sasl_build_gssapi_spn(const char *service, const char *host); +#endif + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +/* This is used to generate a base64 encoded DIGEST-MD5 response message */ +CURL_STATIC CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen); + +/* This is used to decode a HTTP DIGEST challenge message */ +CURL_STATIC CURLcode Curl_sasl_decode_digest_http_message(const char *chlg, + struct digestdata *digest); + +/* This is used to generate a HTTP DIGEST response message */ +CURL_STATIC CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uri, + struct digestdata *digest, + char **outptr, size_t *outlen); + +/* This is used to clean up the digest specific data */ +CURL_STATIC void Curl_sasl_digest_cleanup(struct digestdata *digest); +#endif + +#ifdef USE_NTLM +/* This is used to generate a base64 encoded NTLM type-1 message */ +CURL_STATIC CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, + size_t *outlen); + +/* This is used to decode a base64 encoded NTLM type-2 message */ +CURL_STATIC CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data, + const char *type2msg, + struct ntlmdata *ntlm); + +/* This is used to generate a base64 encoded NTLM type-3 message */ +CURL_STATIC CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen); + +/* This is used to clean up the ntlm specific data */ +void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm); + +#endif /* USE_NTLM */ + +#if defined(USE_KERBEROS5) +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token + message */ +CURL_STATIC 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 */ +CURL_STATIC CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data, + const char *input, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen); + +/* This is used to clean up the gssapi specific data */ +CURL_STATIC void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5); +#endif /* USE_KERBEROS5 */ + +/* This is used to cleanup any libraries or curl modules used by the sasl + functions */ +CURL_STATIC void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); + +/* Convert a mechanism name to a token */ +CURL_STATIC unsigned int Curl_sasl_decode_mech(const char *ptr, + size_t maxlen, size_t *len); + +/* Parse the URL login options */ +CURL_STATIC CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, + const char *value, size_t len); + +/* Initializes an SASL structure */ +CURL_STATIC void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params); + +/* Check if we have enough auth data and capabilities to authenticate */ +CURL_STATIC bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn); + +/* Calculate the required login details for SASL authentication */ +CURL_STATIC CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, + bool force_ir, saslprogress *progress); + +/* Continue an SASL authentication */ +CURL_STATIC CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, + int code, saslprogress *progress); + +#endif /* HEADER_CURL_SASL_H */ diff --git a/libcurl/src/lib/curl_sasl_gssapi.c b/libcurl/src/lib/curl_sasl_gssapi.c new file mode 100644 index 0000000..75bf6a7 --- /dev/null +++ b/libcurl/src/lib/curl_sasl_gssapi.c @@ -0,0 +1,392 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2015, Steve Holme, . + * Copyright (C) 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && defined(USE_KERBEROS5) + +#include + +#include "curl_sasl.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_gssapi.h" +#include "sendf.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* +* Curl_sasl_build_gssapi_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. +* host [in] - The host name or realm. +* +* Returns a pointer to the newly allocated SPN. +*/ +char *Curl_sasl_build_gssapi_spn(const char *service, const char *host) +{ + /* Generate and return our SPN */ + return aprintf("%s@%s", service, host); +} + +/* + * 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. + */ +CURL_STATIC 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; + OM_uint32 gss_status; + OM_uint32 gss_major_status; + OM_uint32 gss_minor_status; + gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + + (void) userp; + (void) passwdp; + + if(krb5->context == GSS_C_NO_CONTEXT) { + /* Generate our SPN */ + char *spn = Curl_sasl_build_gssapi_spn(service, + data->easy_conn->host.name); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Populate the SPN structure */ + spn_token.value = spn; + spn_token.length = strlen(spn); + + /* Import the SPN */ + gss_major_status = gss_import_name(&gss_minor_status, &spn_token, + GSS_C_NT_HOSTBASED_SERVICE, &krb5->spn); + if(GSS_ERROR(gss_major_status)) { + Curl_gss_log_error(data, gss_minor_status, "gss_import_name() failed: "); + + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + free(spn); + } + 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) { + infof(data, "GSSAPI handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + input_token.value = chlg; + input_token.length = chlglen; + } + + gss_major_status = Curl_gss_init_sec_context(data, + &gss_minor_status, + &krb5->context, + krb5->spn, + &Curl_krb5_mech_oid, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + &output_token, + mutual_auth, + NULL); + + free(input_token.value); + + if(GSS_ERROR(gss_major_status)) { + if(output_token.value) + gss_release_buffer(&gss_status, &output_token); + + Curl_gss_log_error(data, gss_minor_status, + "gss_init_sec_context() failed: "); + + return CURLE_RECV_ERROR; + } + + if(output_token.value && output_token.length) { + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token.value, + output_token.length, outptr, outlen); + + gss_release_buffer(&gss_status, &output_token); + } + + 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. + */ +CURL_STATIC 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 chlglen = 0; + size_t messagelen = 0; + unsigned char *chlg = NULL; + unsigned char *message = NULL; + OM_uint32 gss_status; + OM_uint32 gss_major_status; + OM_uint32 gss_minor_status; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + unsigned int indata = 0; + unsigned int outdata = 0; + gss_qop_t qop = GSS_C_QOP_DEFAULT; + unsigned int sec_layer = 0; + unsigned int max_size = 0; + gss_name_t username = GSS_C_NO_NAME; + gss_buffer_desc username_token; + + /* Decode the base-64 encoded input message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Get the fully qualified username back from the context */ + gss_major_status = gss_inquire_context(&gss_minor_status, krb5->context, + &username, NULL, NULL, NULL, NULL, + NULL, NULL); + if(GSS_ERROR(gss_major_status)) { + Curl_gss_log_error(data, gss_minor_status, + "gss_inquire_context() failed: "); + + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Convert the username from internal format to a displayable token */ + gss_major_status = gss_display_name(&gss_minor_status, username, + &username_token, NULL); + if(GSS_ERROR(gss_major_status)) { + Curl_gss_log_error(data, gss_minor_status, "gss_display_name() failed: "); + + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the challenge "input" security buffer */ + input_token.value = chlg; + input_token.length = chlglen; + + /* Decrypt the inbound challenge and obtain the qop */ + gss_major_status = gss_unwrap(&gss_minor_status, krb5->context, &input_token, + &output_token, NULL, &qop); + if(GSS_ERROR(gss_major_status)) { + Curl_gss_log_error(data, gss_minor_status, "gss_unwrap() failed: "); + + gss_release_buffer(&gss_status, &username_token); + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ + if(output_token.length != 4) { + infof(data, "GSSAPI handshake failure (invalid security data)\n"); + + gss_release_buffer(&gss_status, &username_token); + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Copy the data out and free the challenge as it is not required anymore */ + memcpy(&indata, output_token.value, 4); + gss_release_buffer(&gss_status, &output_token); + free(chlg); + + /* Extract the security layer */ + sec_layer = indata & 0x000000FF; + if(!(sec_layer & GSSAUTH_P_NONE)) { + infof(data, "GSSAPI handshake failure (invalid security layer)\n"); + + gss_release_buffer(&gss_status, &username_token); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Extract the maximum message size the server can receive */ + max_size = ntohl(indata & 0xFFFFFF00); + if(max_size > 0) { + /* The server has told us it supports a maximum receive buffer, however, as + we don't require one unless we are encrypting data, we tell the server + our receive buffer is zero. */ + max_size = 0; + } + + /* Allocate our message */ + messagelen = sizeof(outdata) + username_token.length + 1; + message = malloc(messagelen); + if(!message) { + gss_release_buffer(&gss_status, &username_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the message with the security layer, client supported receive + message size and authorization identity including the 0x00 based + terminator. Note: Dispite RFC4752 Section 3.1 stating "The authorization + identity is not terminated with the zero-valued (%x00) octet." it seems + necessary to include it. */ + outdata = htonl(max_size) | sec_layer; + memcpy(message, &outdata, sizeof(outdata)); + memcpy(message + sizeof(outdata), username_token.value, + username_token.length); + message[messagelen - 1] = '\0'; + + /* Free the username token as it is not required anymore */ + gss_release_buffer(&gss_status, &username_token); + + /* Setup the "authentication data" security buffer */ + input_token.value = message; + input_token.length = messagelen; + + /* Encrypt the data */ + gss_major_status = gss_wrap(&gss_minor_status, krb5->context, 0, + GSS_C_QOP_DEFAULT, &input_token, NULL, + &output_token); + if(GSS_ERROR(gss_major_status)) { + Curl_gss_log_error(data, gss_minor_status, "gss_wrap() failed: "); + + free(message); + + return CURLE_OUT_OF_MEMORY; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token.value, + output_token.length, outptr, outlen); + + /* Free the output buffer */ + gss_release_buffer(&gss_status, &output_token); + + /* Free the message buffer */ + free(message); + + return result; +} + +/* + * Curl_sasl_gssapi_cleanup() + * + * This is used to clean up the gssapi specific data. + * + * Parameters: + * + * krb5 [in/out] - The kerberos 5 data struct being cleaned up. + * + */ +CURL_STATIC void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5) +{ + OM_uint32 minor_status; + + /* Free our security context */ + if(krb5->context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&minor_status, &krb5->context, GSS_C_NO_BUFFER); + krb5->context = GSS_C_NO_CONTEXT; + } + + /* Free the SPN */ + if(krb5->spn != GSS_C_NO_NAME) { + gss_release_name(&minor_status, &krb5->spn); + krb5->spn = GSS_C_NO_NAME; + } +} + +#endif /* HAVE_GSSAPI && USE_KERBEROS5 */ diff --git a/libcurl/src/lib/curl_sasl_sspi.c b/libcurl/src/lib/curl_sasl_sspi.c new file mode 100644 index 0000000..71007ea --- /dev/null +++ b/libcurl/src/lib/curl_sasl_sspi.c @@ -0,0 +1,1207 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2014, Steve Holme, . + * + * 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. + * + * RFC2617 Basic and Digest Access Authentication + * RFC2831 DIGEST-MD5 authentication + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) + +#include + +#include "curl_sasl.h" +#include "urldata.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" +#include "strdup.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * 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. + * host [in] - The host name or realm. + * + * Returns a pointer to the newly allocated SPN. + */ +CURL_STATIC 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) { + free(utf8_spn); + + return NULL; + } + + /* Release the UTF8 variant when operating with Unicode */ + Curl_unicodefree(utf8_spn); + + /* Return our newly allocated SPN */ + return tchar_spn; +} + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +/* + * Curl_sasl_create_digest_md5_message() + * + * This is used to generate an already encoded DIGEST-MD5 response message + * ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - The base64 encoded challenge message. + * userp [in] - The user name in the format User or Domain\User. + * passdwp [in] - The user's password. + * service [in] - The service type such as www, smtp, pop or imap. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + TCHAR *spn = NULL; + size_t chlglen = 0; + size_t token_max = 0; + unsigned char *input_token = NULL; + unsigned char *output_token = NULL; + CredHandle credentials; + CtxtHandle context; + PSecPkgInfo SecurityPackage; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + SecBuffer chlg_buf; + SecBuffer resp_buf; + SecBufferDesc chlg_desc; + SecBufferDesc resp_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + /* Decode the base-64 encoded challenge message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &input_token, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!input_token) { + infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Query the security package for DigestSSP */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), + &SecurityPackage); + if(status != SEC_E_OK) { + free(input_token); + + return CURLE_NOT_BUILT_IN; + } + + token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our response buffer */ + output_token = malloc(token_max); + if(!output_token) { + free(input_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Generate our SPN */ + spn = Curl_sasl_build_spn(service, data->easy_conn->host.name); + if(!spn) { + free(output_token); + free(input_token); + + return CURLE_OUT_OF_MEMORY; + } + + if(userp && *userp) { + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &identity); + if(result) { + free(spn); + free(output_token); + free(input_token); + + return result; + } + + /* Allow proper cleanup of the identity structure */ + p_identity = &identity; + } + else + /* Use the current Windows user */ + p_identity = NULL; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_DIGEST), + SECPKG_CRED_OUTBOUND, NULL, + p_identity, NULL, NULL, + &credentials, &expiry); + + if(status != SEC_E_OK) { + Curl_sspi_free_identity(p_identity); + free(spn); + free(output_token); + free(input_token); + + return CURLE_LOGIN_DENIED; + } + + /* Setup the challenge "input" security buffer */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 1; + chlg_desc.pBuffers = &chlg_buf; + chlg_buf.BufferType = SECBUFFER_TOKEN; + chlg_buf.pvBuffer = input_token; + chlg_buf.cbBuffer = curlx_uztoul(chlglen); + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = output_token; + resp_buf.cbBuffer = curlx_uztoul(token_max); + + /* Generate our response message */ + status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, spn, + 0, 0, 0, &chlg_desc, 0, + &context, &resp_desc, &attrs, + &expiry); + + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + s_pSecFn->FreeCredentialsHandle(&credentials); + Curl_sspi_free_identity(p_identity); + free(spn); + free(output_token); + free(input_token); + + return CURLE_RECV_ERROR; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer, + outptr, outlen); + + /* Free our handles */ + s_pSecFn->DeleteSecurityContext(&context); + s_pSecFn->FreeCredentialsHandle(&credentials); + + /* Free the identity structure */ + Curl_sspi_free_identity(p_identity); + + /* Free the SPN */ + free(spn); + + /* Free the response buffer */ + free(output_token); + + /* Free the decoded challenge message */ + free(input_token); + + return result; +} + +/* + * Curl_sasl_decode_digest_http_message() + * + * This is used to decode a HTTP DIGEST challenge message into the seperate + * attributes. + * + * Parameters: + * + * chlg [in] - The challenge message. + * digest [in/out] - The digest data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_sasl_decode_digest_http_message(const char *chlg, + struct digestdata *digest) +{ + size_t chlglen = strlen(chlg); + + /* We had an input token before and we got another one now. This means we + provided bad credentials in the previous request. */ + if(digest->input_token) + return CURLE_BAD_CONTENT_ENCODING; + + /* Simply store the challenge for use later */ + digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen); + if(!digest->input_token) + return CURLE_OUT_OF_MEMORY; + + digest->input_token_len = chlglen; + + return CURLE_OK; +} + +/* + * Curl_sasl_create_digest_http_message() + * + * This is used to generate a HTTP DIGEST response message ready for sending + * to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passdwp [in] - The user's password. + * request [in] - The HTTP request. + * uripath [in] - The path of the HTTP uri. + * digest [in/out] - The digest data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uripath, + struct digestdata *digest, + char **outptr, size_t *outlen) +{ + size_t token_max; + CredHandle credentials; + CtxtHandle context; + char *resp; + BYTE *output_token; + PSecPkgInfo SecurityPackage; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + SecBuffer chlg_buf[3]; + SecBuffer resp_buf; + SecBufferDesc chlg_desc; + SecBufferDesc resp_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + (void) data; + + /* Query the security package for DigestSSP */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), + &SecurityPackage); + if(status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate the output buffer according to the max token size as indicated + by the security package */ + output_token = malloc(token_max); + if(!output_token) + return CURLE_OUT_OF_MEMORY; + + if(userp && *userp) { + /* Populate our identity structure */ + if(Curl_create_sspi_identity(userp, passwdp, &identity)) + return CURLE_OUT_OF_MEMORY; + + /* Allow proper cleanup of the identity structure */ + p_identity = &identity; + } + else + /* Use the current Windows user */ + p_identity = NULL; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_DIGEST), + SECPKG_CRED_OUTBOUND, NULL, + p_identity, NULL, NULL, + &credentials, &expiry); + if(status != SEC_E_OK) { + free(output_token); + + return CURLE_LOGIN_DENIED; + } + + /* Setup the challenge "input" security buffer if present */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 3; + chlg_desc.pBuffers = chlg_buf; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = digest->input_token; + chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len); + chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[1].pvBuffer = (void *)request; + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[2].pvBuffer = NULL; + chlg_buf[2].cbBuffer = 0; + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = output_token; + resp_buf.cbBuffer = curlx_uztoul(token_max); + + /* Generate our reponse message */ + status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, + (TCHAR *) uripath, + ISC_REQ_USE_HTTP_STYLE, 0, 0, + &chlg_desc, 0, &context, + &resp_desc, &attrs, &expiry); + + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + s_pSecFn->FreeCredentialsHandle(&credentials); + + free(output_token); + + return CURLE_OUT_OF_MEMORY; + } + + resp = malloc(resp_buf.cbBuffer + 1); + if(!resp) { + s_pSecFn->DeleteSecurityContext(&context); + s_pSecFn->FreeCredentialsHandle(&credentials); + + free(output_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Copy the generated reponse */ + memcpy(resp, resp_buf.pvBuffer, resp_buf.cbBuffer); + resp[resp_buf.cbBuffer] = 0x00; + + /* Return the response */ + *outptr = resp; + *outlen = resp_buf.cbBuffer; + + /* Free our handles */ + s_pSecFn->DeleteSecurityContext(&context); + s_pSecFn->FreeCredentialsHandle(&credentials); + + /* Free the identity structure */ + Curl_sspi_free_identity(p_identity); + + /* Free the response buffer */ + free(output_token); + + return CURLE_OK; +} + +/* + * Curl_sasl_digest_cleanup() + * + * This is used to clean up the digest specific data. + * + * Parameters: + * + * digest [in/out] - The digest data struct being cleaned up. + * + */ +void Curl_sasl_digest_cleanup(struct digestdata *digest) +{ + /* Free the input token */ + Curl_safefree(digest->input_token); + + /* Reset any variables */ + digest->input_token_len = 0; +} +#endif /* !CURL_DISABLE_CRYPTO_AUTH */ + +#if defined USE_NTLM +/* +* Curl_sasl_create_ntlm_type1_message() +* +* This is used to generate an already encoded NTLM type-1 message ready for +* sending to the recipient. +* +* Parameters: +* +* userp [in] - The user name in the format User or Domain\User. +* passdwp [in] - The user's password. +* ntlm [in/out] - The ntlm data struct being used and modified. +* outptr [in/out] - The address where a pointer to newly allocated memory +* holding the result will be stored upon completion. +* outlen [out] - The length of the output message. +* +* Returns CURLE_OK on success. +*/ +CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + PSecPkgInfo SecurityPackage; + SecBuffer type_1_buf; + SecBufferDesc type_1_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + /* Clean up any former leftovers and initialise to defaults */ + Curl_sasl_ntlm_cleanup(ntlm); + + /* Query the security package for NTLM */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM), + &SecurityPackage); + if(status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + ntlm->token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our output buffer */ + ntlm->output_token = malloc(ntlm->token_max); + if(!ntlm->output_token) + return CURLE_OUT_OF_MEMORY; + + if(userp && *userp) { + CURLcode result; + + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &ntlm->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ + ntlm->p_identity = &ntlm->identity; + } + else + /* Use the current Windows user */ + ntlm->p_identity = NULL; + + /* Allocate our credentials handle */ + ntlm->credentials = malloc(sizeof(CredHandle)); + if(!ntlm->credentials) + return CURLE_OUT_OF_MEMORY; + + memset(ntlm->credentials, 0, sizeof(CredHandle)); + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_NTLM), + SECPKG_CRED_OUTBOUND, NULL, + ntlm->p_identity, NULL, NULL, + ntlm->credentials, &expiry); + if(status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + + /* Allocate our new context handle */ + ntlm->context = malloc(sizeof(CtxtHandle)); + if(!ntlm->context) + return CURLE_OUT_OF_MEMORY; + + memset(ntlm->context, 0, sizeof(CtxtHandle)); + + /* Setup the type-1 "output" security buffer */ + type_1_desc.ulVersion = SECBUFFER_VERSION; + type_1_desc.cBuffers = 1; + type_1_desc.pBuffers = &type_1_buf; + type_1_buf.BufferType = SECBUFFER_TOKEN; + type_1_buf.pvBuffer = ntlm->output_token; + type_1_buf.cbBuffer = curlx_uztoul(ntlm->token_max); + + /* Generate our type-1 message */ + status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL, + (TCHAR *) TEXT(""), + 0, 0, SECURITY_NETWORK_DREP, + NULL, 0, + ntlm->context, &type_1_desc, + &attrs, &expiry); + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(ntlm->context, &type_1_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) + return CURLE_RECV_ERROR; + + /* Base64 encode the response */ + return Curl_base64_encode(NULL, (char *) ntlm->output_token, + type_1_buf.cbBuffer, outptr, outlen); +} + +/* +* Curl_sasl_decode_ntlm_type2_message() +* +* This is used to decode an already encoded NTLM type-2 message. +* +* Parameters: +* +* data [in] - The session handle. +* type2msg [in] - The base64 encoded type-2 message. +* ntlm [in/out] - The ntlm data struct being used and modified. +* +* Returns CURLE_OK on success. +*/ +CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data, + const char *type2msg, + struct ntlmdata *ntlm) +{ + CURLcode result = CURLE_OK; + unsigned char *type2 = NULL; + size_t type2_len = 0; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + /* Decode the base-64 encoded type-2 message */ + if(strlen(type2msg) && *type2msg != '=') { + result = Curl_base64_decode(type2msg, &type2, &type2_len); + if(result) + return result; + } + + /* Ensure we have a valid type-2 message */ + if(!type2) { + infof(data, "NTLM handshake failure (empty type-2 message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Simply store the challenge for use later */ + ntlm->input_token = type2; + ntlm->input_token_len = type2_len; + + return result; +} + +/* +* Curl_sasl_create_ntlm_type3_message() +* +* This is used to generate an already encoded NTLM type-3 message ready for +* sending to the recipient. +* +* Parameters: +* +* data [in] - The session handle. +* userp [in] - The user name in the format User or Domain\User. +* passdwp [in] - The user's password. +* ntlm [in/out] - The ntlm data struct being used and modified. +* outptr [in/out] - The address where a pointer to newly allocated memory +* holding the result will be stored upon completion. +* outlen [out] - The length of the output message. +* +* Returns CURLE_OK on success. +*/ +CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + SecBuffer type_2_buf; + SecBuffer type_3_buf; + SecBufferDesc type_2_desc; + SecBufferDesc type_3_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + (void) passwdp; + (void) userp; + + /* Setup the type-2 "input" security buffer */ + type_2_desc.ulVersion = SECBUFFER_VERSION; + type_2_desc.cBuffers = 1; + type_2_desc.pBuffers = &type_2_buf; + type_2_buf.BufferType = SECBUFFER_TOKEN; + type_2_buf.pvBuffer = ntlm->input_token; + type_2_buf.cbBuffer = curlx_uztoul(ntlm->input_token_len); + + /* Setup the type-3 "output" security buffer */ + type_3_desc.ulVersion = SECBUFFER_VERSION; + type_3_desc.cBuffers = 1; + type_3_desc.pBuffers = &type_3_buf; + type_3_buf.BufferType = SECBUFFER_TOKEN; + type_3_buf.pvBuffer = ntlm->output_token; + type_3_buf.cbBuffer = curlx_uztoul(ntlm->token_max); + + /* Generate our type-3 message */ + status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, + ntlm->context, + (TCHAR *) TEXT(""), + 0, 0, SECURITY_NETWORK_DREP, + &type_2_desc, + 0, ntlm->context, + &type_3_desc, + &attrs, &expiry); + if(status != SEC_E_OK) { + infof(data, "NTLM handshake failure (type-3 message): Status=%x\n", + status); + + return CURLE_RECV_ERROR; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) ntlm->output_token, + type_3_buf.cbBuffer, outptr, outlen); + + Curl_sasl_ntlm_cleanup(ntlm); + + return result; +} + +/* + * Curl_sasl_ntlm_cleanup() + * + * This is used to clean up the ntlm specific data. + * + * Parameters: + * + * ntlm [in/out] - The ntlm data struct being cleaned up. + * + */ +void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm) +{ + /* Free our security context */ + if(ntlm->context) { + s_pSecFn->DeleteSecurityContext(ntlm->context); + free(ntlm->context); + ntlm->context = NULL; + } + + /* Free our credentials handle */ + if(ntlm->credentials) { + s_pSecFn->FreeCredentialsHandle(ntlm->credentials); + free(ntlm->credentials); + ntlm->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(ntlm->p_identity); + ntlm->p_identity = NULL; + + /* Free the input and output tokens */ + Curl_safefree(ntlm->input_token); + Curl_safefree(ntlm->output_token); + + /* Reset any variables */ + ntlm->token_max = 0; +} +#endif /* USE_NTLM */ + +#if defined(USE_KERBEROS5) +/* + * 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 in the format User or Domain\User. + * 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] - 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. + */ +CURL_STATIC 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 expiry; /* For Windows 9x compatibility of SSPI calls */ + + if(!krb5->credentials) { + /* Query the security package for Kerberos */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_KERBEROS), + &SecurityPackage); + if(status != SEC_E_OK) { + return CURLE_NOT_BUILT_IN; + } + + krb5->token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our response buffer */ + krb5->output_token = malloc(krb5->token_max); + if(!krb5->output_token) + return CURLE_OUT_OF_MEMORY; + + /* 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; + } + else + /* Use the current Windows user */ + krb5->p_identity = NULL; + + /* Allocate our credentials handle */ + krb5->credentials = malloc(sizeof(CredHandle)); + if(!krb5->credentials) + return CURLE_OUT_OF_MEMORY; + + memset(krb5->credentials, 0, sizeof(CredHandle)); + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) + TEXT(SP_NAME_KERBEROS), + SECPKG_CRED_OUTBOUND, NULL, + krb5->p_identity, NULL, NULL, + krb5->credentials, &expiry); + if(status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + + /* Allocate our new context handle */ + krb5->context = malloc(sizeof(CtxtHandle)); + if(!krb5->context) + return CURLE_OUT_OF_MEMORY; + + memset(krb5->context, 0, sizeof(CtxtHandle)); + } + 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) { + infof(data, "GSSAPI handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 1; + chlg_desc.pBuffers = &chlg_buf; + chlg_buf.BufferType = SECBUFFER_TOKEN; + chlg_buf.pvBuffer = chlg; + chlg_buf.cbBuffer = curlx_uztoul(chlglen); + } + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = krb5->output_token; + resp_buf.cbBuffer = curlx_uztoul(krb5->token_max); + + /* Generate our challenge-response message */ + status = s_pSecFn->InitializeSecurityContext(krb5->credentials, + chlg ? krb5->context : NULL, + krb5->spn, + (mutual_auth ? + ISC_REQ_MUTUAL_AUTH : 0), + 0, SECURITY_NATIVE_DREP, + chlg ? &chlg_desc : NULL, 0, + &context, + &resp_desc, &attrs, + &expiry); + + if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + free(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 */ + free(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] - 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. + */ +CURL_STATIC 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; + char *user_name; + + /* Decode the base-64 encoded input message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Get our response size information */ + status = s_pSecFn->QueryContextAttributes(krb5->context, + SECPKG_ATTR_SIZES, + &sizes); + if(status != SEC_E_OK) { + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Get the fully qualified username back from the context */ + status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials, + SECPKG_CRED_ATTR_NAMES, + &names); + if(status != SEC_E_OK) { + free(chlg); + + return CURLE_RECV_ERROR; + } + + /* Setup the "input" security buffer */ + input_desc.ulVersion = SECBUFFER_VERSION; + input_desc.cBuffers = 2; + input_desc.pBuffers = input_buf; + input_buf[0].BufferType = SECBUFFER_STREAM; + input_buf[0].pvBuffer = chlg; + input_buf[0].cbBuffer = curlx_uztoul(chlglen); + input_buf[1].BufferType = SECBUFFER_DATA; + input_buf[1].pvBuffer = NULL; + input_buf[1].cbBuffer = 0; + + /* Decrypt the inbound challenge and obtain the qop */ + status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop); + if(status != SEC_E_OK) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ + if(input_buf[1].cbBuffer != 4) { + infof(data, "GSSAPI handshake failure (invalid security data)\n"); + + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Copy the data out and free the challenge as it is not required anymore */ + memcpy(&indata, input_buf[1].pvBuffer, 4); + s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer); + free(chlg); + + /* Extract the security layer */ + sec_layer = indata & 0x000000FF; + if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) { + infof(data, "GSSAPI handshake failure (invalid security layer)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Extract the maximum message size the server can receive */ + max_size = ntohl(indata & 0xFFFFFF00); + if(max_size > 0) { + /* The server has told us it supports a maximum receive buffer, however, as + we don't require one unless we are encrypting data, we tell the server + our receive buffer is zero. */ + max_size = 0; + } + + /* Allocate the trailer */ + trailer = malloc(sizes.cbSecurityTrailer); + if(!trailer) + return CURLE_OUT_OF_MEMORY; + + /* Convert the user name to UTF8 when operating with Unicode */ + user_name = Curl_convert_tchar_to_UTF8(names.sUserName); + if(!user_name) { + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Allocate our message */ + messagelen = sizeof(outdata) + strlen(user_name) + 1; + message = malloc(messagelen); + if(!message) { + free(trailer); + Curl_unicodefree(user_name); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the message with the security layer, client supported receive + message size and authorization identity including the 0x00 based + terminator. Note: Dispite RFC4752 Section 3.1 stating "The authorization + identity is not terminated with the zero-valued (%x00) octet." it seems + necessary to include it. */ + outdata = htonl(max_size) | sec_layer; + memcpy(message, &outdata, sizeof(outdata)); + strcpy((char *) message + sizeof(outdata), user_name); + Curl_unicodefree(user_name); + + /* Allocate the padding */ + padding = malloc(sizes.cbBlockSize); + if(!padding) { + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the "authentication data" security buffer */ + wrap_desc.ulVersion = SECBUFFER_VERSION; + wrap_desc.cBuffers = 3; + wrap_desc.pBuffers = wrap_buf; + wrap_buf[0].BufferType = SECBUFFER_TOKEN; + wrap_buf[0].pvBuffer = trailer; + wrap_buf[0].cbBuffer = sizes.cbSecurityTrailer; + wrap_buf[1].BufferType = SECBUFFER_DATA; + wrap_buf[1].pvBuffer = message; + wrap_buf[1].cbBuffer = curlx_uztoul(messagelen); + wrap_buf[2].BufferType = SECBUFFER_PADDING; + wrap_buf[2].pvBuffer = padding; + wrap_buf[2].cbBuffer = sizes.cbBlockSize; + + /* Encrypt the data */ + status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT, + &wrap_desc, 0); + if(status != SEC_E_OK) { + free(padding); + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Allocate the encryption (wrap) buffer */ + appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer + + wrap_buf[2].cbBuffer; + appdata = malloc(appdatalen); + if(!appdata) { + free(padding); + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the encryption buffer */ + memcpy(appdata, wrap_buf[0].pvBuffer, wrap_buf[0].cbBuffer); + offset += wrap_buf[0].cbBuffer; + memcpy(appdata + offset, wrap_buf[1].pvBuffer, wrap_buf[1].cbBuffer); + offset += wrap_buf[1].cbBuffer; + memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer); + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *)appdata, appdatalen, outptr, + outlen); + + /* Free all of our local buffers */ + free(appdata); + free(padding); + free(message); + free(trailer); + + return result; +} + +/* + * Curl_sasl_gssapi_cleanup() + * + * This is used to clean up the gssapi specific data. + * + * Parameters: + * + * krb5 [in/out] - The kerberos 5 data struct being cleaned up. + * + */ +CURL_STATIC void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5) +{ + /* Free our security context */ + if(krb5->context) { + s_pSecFn->DeleteSecurityContext(krb5->context); + free(krb5->context); + krb5->context = NULL; + } + + /* Free our credentials handle */ + if(krb5->credentials) { + s_pSecFn->FreeCredentialsHandle(krb5->credentials); + free(krb5->credentials); + krb5->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(krb5->p_identity); + krb5->p_identity = NULL; + + /* Free the SPN and output token */ + Curl_safefree(krb5->spn); + Curl_safefree(krb5->output_token); + + /* Reset any variables */ + krb5->token_max = 0; +} +#endif /* USE_KERBEROS5 */ + +#endif /* USE_WINDOWS_SSPI */ diff --git a/libcurl/src/lib/curl_sec.h b/libcurl/src/lib/curl_sec.h new file mode 100644 index 0000000..9cb6d0a --- /dev/null +++ b/libcurl/src/lib/curl_sec.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_SECURITY_H +#define HEADER_CURL_SECURITY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +struct Curl_sec_client_mech { + const char *name; + size_t size; + int (*init)(void *); + int (*auth)(void *, struct connectdata *); + void (*end)(void *); + int (*check_prot)(void *, int); + int (*overhead)(void *, int, int); + int (*encode)(void *, const void*, int, int, void**); + int (*decode)(void *, void*, int, int, struct connectdata *); +}; + +#define AUTH_OK 0 +#define AUTH_CONTINUE 1 +#define AUTH_ERROR 2 + +#ifdef HAVE_GSSAPI +CURL_STATIC int Curl_sec_read_msg (struct connectdata *conn, char *, + enum protection_level); +CURL_STATIC void Curl_sec_end (struct connectdata *); +CURL_STATIC CURLcode Curl_sec_login (struct connectdata *); +CURL_STATIC int Curl_sec_request_prot (struct connectdata *conn, const char *level); + +extern struct Curl_sec_client_mech Curl_krb5_client_mech; +#endif + +#endif /* HEADER_CURL_SECURITY_H */ diff --git a/libcurl/src/lib/curl_setup.h b/libcurl/src/lib/curl_setup.h new file mode 100644 index 0000000..7709e0e --- /dev/null +++ b/libcurl/src/lib/curl_setup.h @@ -0,0 +1,713 @@ +#ifndef HEADER_CURL_SETUP_H +#define HEADER_CURL_SETUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \ + !defined(__SYMBIAN32__) +#define WIN32 +#endif + +/* + * Include configuration script results or hand-crafted + * configuration file for platforms which lack config tool. + */ + +#ifdef HAVE_CONFIG_H + +#include "curl_config.h" + +#else /* HAVE_CONFIG_H */ + +#ifdef _WIN32_WCE +# include "config-win32ce.h" +#elif defined(CURL_WINRT) +# include "config-winrt.h" +#elif defined(WIN32) +# include "config-win32.h" +#elif defined(macintosh) && defined(__MRC__) +# include "config-mac.h" +#elif defined(__APPLE__) +# include "TargetConditionals.h" +# if TARGET_IPHONE_SIMULATOR +# include "config-ios-sim.h" +# elif TARGET_OS_IPHONE +# include "config-ios.h" +# elif TARGET_OS_MAC +# include "config-osx.h" +# endif +#elif defined(__ANDROID__) && (defined(__arm__) || defined(_M_ARM)) +# include "config-android-arm.h" +#elif defined(__ANDROID__) && (defined(__i386__) || defined(_M_IX86)) +# include "config-android-x86.h" +#elif defined(__EMSCRIPTEN__) +# include "config-emscripten.h" +#elif defined(__riscos__) +# include "config-riscos.h" +#elif defined(__AMIGA__) +# include "config-amigaos.h" +#elif defined(__SYMBIAN32__) +# include "config-symbian.h" +#elif defined(__OS400__) +# include "config-os400.h" +#elif defined(TPF) +# include "config-tpf.h" +#elif defined(__VXWORKS__) +# include "config-vxworks.h" +#else +#error Add missing configuration. +#endif + +#endif /* HAVE_CONFIG_H */ + +/* ================================================================ */ +/* Definition of preprocessor macros/symbols which modify compiler */ +/* behavior or generated code characteristics must be done here, */ +/* as appropriate, before any system header file is included. It is */ +/* also possible to have them defined in the config file included */ +/* before this point. As a result of all this we frown inclusion of */ +/* system header files in our config files, avoid this at any cost. */ +/* ================================================================ */ + +/* + * AIX 4.3 and newer needs _THREAD_SAFE defined to build + * proper reentrant code. Others may also need it. + */ + +#ifdef NEED_THREAD_SAFE +# ifndef _THREAD_SAFE +# define _THREAD_SAFE +# endif +#endif + +/* + * Tru64 needs _REENTRANT set for a few function prototypes and + * things to appear in the system header files. Unixware needs it + * to build proper reentrant code. Others may also need it. + */ + +#ifdef NEED_REENTRANT +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +/* Solaris needs this to get a POSIX-conformant getpwuid_r */ +#if defined(sun) || defined(__sun) +# ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +# endif +#endif + +/* ================================================================ */ +/* If you need to include a system header file for your platform, */ +/* please, do it beyond the point further indicated in this file. */ +/* ================================================================ */ + +/* + * libcurl's external interface definitions are also used internally, + * and might also include required system header files to define them. + */ + +#include + +/* + * Compile time sanity checks must also be done when building the library. + */ + +#include + +/* + * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro + */ + +#ifdef SIZEOF_CURL_OFF_T +# error "SIZEOF_CURL_OFF_T shall not be defined!" + Error Compilation_aborted_SIZEOF_CURL_OFF_T_shall_not_be_defined +#endif + +/* + * Disable other protocols when http is the only one desired. + */ + +#ifdef HTTP_ONLY +# ifndef CURL_DISABLE_TFTP +# define CURL_DISABLE_TFTP +# endif +# ifndef CURL_DISABLE_FTP +# define CURL_DISABLE_FTP +# endif +# ifndef CURL_DISABLE_LDAP +# define CURL_DISABLE_LDAP +# endif +# ifndef CURL_DISABLE_TELNET +# define CURL_DISABLE_TELNET +# endif +# ifndef CURL_DISABLE_DICT +# define CURL_DISABLE_DICT +# endif +# ifndef CURL_DISABLE_FILE +# define CURL_DISABLE_FILE +# endif +# ifndef CURL_DISABLE_RTSP +# define CURL_DISABLE_RTSP +# endif +# ifndef CURL_DISABLE_POP3 +# define CURL_DISABLE_POP3 +# endif +# ifndef CURL_DISABLE_IMAP +# define CURL_DISABLE_IMAP +# endif +# ifndef CURL_DISABLE_SMTP +# define CURL_DISABLE_SMTP +# endif +# ifndef CURL_DISABLE_RTSP +# define CURL_DISABLE_RTSP +# endif +# ifndef CURL_DISABLE_RTMP +# define CURL_DISABLE_RTMP +# endif +# ifndef CURL_DISABLE_GOPHER +# define CURL_DISABLE_GOPHER +# endif +# ifndef CURL_DISABLE_SMB +# define CURL_DISABLE_SMB +# endif +#endif + +/* + * When http is disabled rtsp is not supported. + */ + +#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP) +# define CURL_DISABLE_RTSP +#endif + +/* ================================================================ */ +/* No system header file shall be included in this file before this */ +/* point. The only allowed ones are those included from curlbuild.h */ +/* ================================================================ */ + +/* + * OS/400 setup file includes some system headers. + */ + +#ifdef __OS400__ +# include "setup-os400.h" +#endif + +/* + * VMS setup file includes some system headers. + */ + +#ifdef __VMS +# include "setup-vms.h" +#endif + +/* + * Include header files for windows builds before redefining anything. + * Use this preprocessor block only to include or exclude windows.h, + * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs + * to any other further and independent block. Under Cygwin things work + * just as under linux (e.g. ) and the winsock headers should + * never be included when __CYGWIN__ is defined. configure script takes + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H, + * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined. + */ + +#ifdef HAVE_WINDOWS_H +# if defined(UNICODE) && !defined(_UNICODE) +# define _UNICODE +# endif +# if defined(_UNICODE) && !defined(UNICODE) +# define UNICODE +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# ifdef HAVE_WINSOCK2_H +# include +# ifdef HAVE_WS2TCPIP_H +# include +# endif +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +# include +# ifdef UNICODE + typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str); +# endif +#endif + +/* + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else + * define USE_WINSOCK to 1 if we have and use WINSOCK API, else + * undefine USE_WINSOCK. + */ + +#undef USE_WINSOCK + +#ifdef HAVE_WINSOCK2_H +# define USE_WINSOCK 2 +#else +# ifdef HAVE_WINSOCK_H +# define USE_WINSOCK 1 +# endif +#endif + +#ifdef USE_LWIPSOCK +# include +# include +# include +#endif + +#ifdef HAVE_EXTRA_STRICMP_H +# include +#endif + +#ifdef HAVE_EXTRA_STRDUP_H +# include +#endif + +#ifdef TPF +# include /* for bzero, strcasecmp, and strncasecmp */ +# include /* for strcpy and strlen */ +# include /* for rand and srand */ +# include /* for select and ioctl*/ +# include /* for in_addr_t definition */ +# include /* for tpf_process_signals */ + /* change which select is used for libcurl */ +# define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e) +#endif + +#ifdef __VXWORKS__ +# include /* for generic BSD socket functions */ +# include /* for basic I/O interface functions */ +#endif + +#ifdef __AMIGA__ +# ifndef __ixemul__ +# include +# include +# include +# include +# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0) +# endif +#endif + +#include +#ifdef HAVE_ASSERT_H +#include +#endif + +#ifdef __TANDEM /* for nsr-tandem-nsk systems */ +#include +#endif + +#ifndef STDC_HEADERS /* no standard C headers! */ +#include +#endif + +#ifdef __POCC__ +# include +# include +# define sys_nerr EILSEQ +#endif + +/* + * Salford-C kludge section (mostly borrowed from wxWidgets). + */ +#ifdef __SALFORDC__ + #pragma suppress 353 /* Possible nested comments */ + #pragma suppress 593 /* Define not used */ + #pragma suppress 61 /* enum has no name */ + #pragma suppress 106 /* unnamed, unused parameter */ + #include +#endif + +/* + * Large file (>2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_LARGE_FILES +# include +# include +# include +# undef lseek +# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence) +# undef fstat +# define fstat(fdes,stp) _fstati64(fdes, stp) +# undef stat +# define stat(fname,stp) _stati64(fname, stp) +# define struct_stat struct _stati64 +# define LSEEK_ERROR (__int64)-1 +#endif + +/* + * Small file (<2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_SMALL_FILES +# include +# include +# include +# ifndef _WIN32_WCE +# undef lseek +# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence) +# define fstat(fdes,stp) _fstat(fdes, stp) +# define stat(fname,stp) _stat(fname, stp) +# define struct_stat struct _stat +# endif +# define LSEEK_ERROR (long)-1 +#endif + +#ifndef struct_stat +# define struct_stat struct stat +#endif + +#ifndef LSEEK_ERROR +# define LSEEK_ERROR (off_t)-1 +#endif + +/* + * Default sizeof(off_t) in case it hasn't been defined in config file. + */ + +#ifndef SIZEOF_OFF_T +# if defined(__VMS) && !defined(__VAX) +# if defined(_LARGEFILE) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__OS400__) && defined(__ILEC400__) +# if defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__MVS__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__370__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# endif +# ifndef SIZEOF_OFF_T +# define SIZEOF_OFF_T 4 +# endif +#endif + +/* + * Arg 2 type for gethostname in case it hasn't been defined in config file. + */ + +#ifndef GETHOSTNAME_TYPE_ARG2 +# ifdef USE_WINSOCK +# define GETHOSTNAME_TYPE_ARG2 int +# else +# define GETHOSTNAME_TYPE_ARG2 size_t +# endif +#endif + +/* Below we define some functions. They should + + 4. set the SIGALRM signal timeout + 5. set dir/file naming defines + */ + +#ifdef WIN32 + +# define DIR_CHAR "\\" +# define DOT_CHAR "_" + +#else /* WIN32 */ + +# ifdef MSDOS /* Watt-32 */ + +# include +# define select(n,r,w,x,t) select_s(n,r,w,x,t) +# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z)) +# include +# ifdef word +# undef word +# endif +# ifdef byte +# undef byte +# endif + +# endif /* MSDOS */ + +# ifdef __minix + /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */ + extern char * strtok_r(char *s, const char *delim, char **last); + extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp); +# endif + +# define DIR_CHAR "/" +# ifndef DOT_CHAR +# define DOT_CHAR "." +# endif + +# ifdef MSDOS +# undef DOT_CHAR +# define DOT_CHAR "_" +# endif + +# ifndef fileno /* sunos 4 have this as a macro! */ + int fileno( FILE *stream); +# endif + +#endif /* WIN32 */ + +/* + * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN + * defined in ws2tcpip.h as well as to provide IPv6 support. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WS2TCPIP_H) || \ + ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN)) +# undef HAVE_GETADDRINFO_THREADSAFE +# undef HAVE_FREEADDRINFO +# undef HAVE_GETADDRINFO +# undef HAVE_GETNAMEINFO +# undef ENABLE_IPV6 +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* resolver specialty compile-time defines */ +/* CURLRES_* defines to use in the host*.c sources */ +/* ---------------------------------------------------------------- */ + +/* + * lcc-win32 doesn't have _beginthreadex(), lacks threads support. + */ + +#if defined(__LCC__) && defined(WIN32) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * MSVC threads support requires a multi-threaded runtime library. + * _beginthreadex() is not available in single-threaded ones. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * Mutually exclusive CURLRES_* definitions. + */ + +#ifdef USE_ARES +# define CURLRES_ASYNCH +# define CURLRES_ARES +/* now undef the stock libc functions just to avoid them being used */ +# undef HAVE_GETADDRINFO +# undef HAVE_GETHOSTBYNAME +#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +# define CURLRES_ASYNCH +# define CURLRES_THREADED +#else +# define CURLRES_SYNCH +#endif + +#ifdef ENABLE_IPV6 +# define CURLRES_IPV6 +#else +# define CURLRES_IPV4 +#endif + +/* ---------------------------------------------------------------- */ + +/* + * When using WINSOCK, TELNET protocol requires WINSOCK2 API. + */ + +#if defined(USE_WINSOCK) && (USE_WINSOCK != 2) +# define CURL_DISABLE_TELNET 1 +#endif + +/* + * msvc 6.0 does not have struct sockaddr_storage and + * does not define IPPROTO_ESP in winsock2.h. But both + * are available if PSDK is properly installed. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP)) +# undef HAVE_STRUCT_SOCKADDR_STORAGE +# endif +#endif + +/* + * Intentionally fail to build when using msvc 6.0 without PSDK installed. + * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK + * in lib/config-win32.h although absolutely discouraged and unsupported. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_)) +# if !defined(ALLOW_MSVC6_WITHOUT_PSDK) +# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \ + "Windows Server 2003 PSDK" +# else +# define CURL_DISABLE_LDAP 1 +# endif +# endif +#endif + +#ifdef NETWARE +int netware_init(void); +#ifndef __NOVELL_LIBC__ +#include +#include +#endif +#endif + +#if defined(HAVE_LIBIDN) && defined(HAVE_TLD_H) +/* The lib was present and the tld.h header (which is missing in libidn 0.3.X + but we only work with libidn 0.4.1 or later) */ +#define USE_LIBIDN +#endif + +#ifndef SIZEOF_TIME_T +/* assume default size of time_t to be 32 bit */ +#define SIZEOF_TIME_T 4 +#endif + +#define LIBIDN_REQUIRED_VERSION "0.4.1" + +#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \ + defined(USE_POLARSSL) || defined(USE_AXTLS) || \ + defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ + defined(USE_DARWINSSL) || defined(USE_GSKIT) +#define USE_SSL /* SSL support has been enabled */ +#endif + +/* Single point where USE_SPNEGO definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_SPNEGO +#endif + +/* Single point where USE_KERBEROS5 definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_KERBEROS5 +#endif + +/* Single point where USE_NTLM definition might be defined */ +#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) +#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \ + defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) + +#ifdef HAVE_BORINGSSL /* BoringSSL is not NTLM capable */ +#undef USE_NTLM +#else +#define USE_NTLM +#endif +#endif +#endif + +/* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */ +#if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE) +#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE") +#endif + +/* + * Provide a mechanism to silence picky compilers, such as gcc 4.6+. + * Parameters should of course normally not be unused, but for example when + * we have multiple implementations of the same interface it may happen. + */ + +#if defined(__GNUC__) && ((__GNUC__ >= 3) || \ + ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7))) +# define UNUSED_PARAM __attribute__((__unused__)) +# define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define UNUSED_PARAM /*NOTHING*/ +# define WARN_UNUSED_RESULT +#endif + +/* + * Include macros and defines that should only be processed once. + */ + +#ifndef HEADER_CURL_SETUP_ONCE_H +#include "curl_setup_once.h" +#endif + +/* + * Definition of our NOP statement Object-like macro + */ + +#ifndef Curl_nop_stmt +# define Curl_nop_stmt do { } WHILE_FALSE +#endif + +/* + * Ensure that Winsock and lwIP TCP/IP stacks are not mixed. + */ + +#if defined(__LWIP_OPT_H__) +# if defined(SOCKET) || \ + defined(USE_WINSOCK) || \ + defined(HAVE_WINSOCK_H) || \ + defined(HAVE_WINSOCK2_H) || \ + defined(HAVE_WS2TCPIP_H) +# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!" +# endif +#endif + +/* + * Portable symbolic names for Winsock shutdown() mode flags. + */ + +#ifdef USE_WINSOCK +# define SHUT_RD 0x00 +# define SHUT_WR 0x01 +# define SHUT_RDWR 0x02 +#endif + +/* Define S_ISREG if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + +/* Define S_ISDIR if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +#endif /* HEADER_CURL_SETUP_H */ diff --git a/libcurl/src/lib/curl_setup_once.h b/libcurl/src/lib/curl_setup_once.h new file mode 100644 index 0000000..69d6d47 --- /dev/null +++ b/libcurl/src/lib/curl_setup_once.h @@ -0,0 +1,551 @@ +#ifndef HEADER_CURL_SETUP_ONCE_H +#define HEADER_CURL_SETUP_ONCE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* + * Inclusion of common header files. + */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_ERRNO_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef NEED_MALLOC_H +#include +#endif + +#ifdef NEED_MEMORY_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#else +#ifdef HAVE_TIME_H +#include +#endif +#endif + +#ifdef WIN32 +#include +#include +#endif + +#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T) +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef __hpux +# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL) +# ifdef _APP32_64BIT_OFF_T +# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T +# undef _APP32_64BIT_OFF_T +# else +# undef OLD_APP32_64BIT_OFF_T +# endif +# endif +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef __hpux +# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL) +# ifdef OLD_APP32_64BIT_OFF_T +# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T +# undef OLD_APP32_64BIT_OFF_T +# endif +# endif +#endif + + +/* + * Definition of timeval struct for platforms that don't have it. + */ + +#ifndef HAVE_STRUCT_TIMEVAL +struct timeval { + long tv_sec; + long tv_usec; +}; +#endif + + +/* + * If we have the MSG_NOSIGNAL define, make sure we use + * it as the fourth argument of function send() + */ + +#ifdef HAVE_MSG_NOSIGNAL +#define SEND_4TH_ARG MSG_NOSIGNAL +#else +#define SEND_4TH_ARG 0 +#endif + + +#if defined(__minix) +/* Minix doesn't support recv on TCP sockets */ +#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z)) + +#elif defined(HAVE_RECV) +/* + * The definitions for the return type and arguments types + * of functions recv() and send() belong and come from the + * configuration file. Do not define them in any other place. + * + * HAVE_RECV is defined if you have a function named recv() + * which is used to read incoming data from sockets. If your + * function has another name then don't define HAVE_RECV. + * + * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2, + * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also + * be defined. + * + * HAVE_SEND is defined if you have a function named send() + * which is used to write outgoing data on a connected socket. + * If yours has another name then don't define HAVE_SEND. + * + * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2, + * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and + * SEND_TYPE_RETV must also be defined. + */ + +#if !defined(RECV_TYPE_ARG1) || \ + !defined(RECV_TYPE_ARG2) || \ + !defined(RECV_TYPE_ARG3) || \ + !defined(RECV_TYPE_ARG4) || \ + !defined(RECV_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_recv + /* */ +#else +#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z), \ + (RECV_TYPE_ARG4)(0)) +#endif +#else /* HAVE_RECV */ +#ifndef sread + /* */ + Error Missing_definition_of_macro_sread + /* */ +#endif +#endif /* HAVE_RECV */ + + +#if defined(__minix) +/* Minix doesn't support send on TCP sockets */ +#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \ + (SEND_TYPE_ARG2)(y), \ + (SEND_TYPE_ARG3)(z)) + +#elif defined(HAVE_SEND) +#if !defined(SEND_TYPE_ARG1) || \ + !defined(SEND_QUAL_ARG2) || \ + !defined(SEND_TYPE_ARG2) || \ + !defined(SEND_TYPE_ARG3) || \ + !defined(SEND_TYPE_ARG4) || \ + !defined(SEND_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_send + /* */ +#else +#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ + (SEND_TYPE_ARG2)(y), \ + (SEND_TYPE_ARG3)(z), \ + (SEND_TYPE_ARG4)(SEND_4TH_ARG)) +#endif +#else /* HAVE_SEND */ +#ifndef swrite + /* */ + Error Missing_definition_of_macro_swrite + /* */ +#endif +#endif /* HAVE_SEND */ + + +#if 0 +#if defined(HAVE_RECVFROM) +/* + * Currently recvfrom is only used on udp sockets. + */ +#if !defined(RECVFROM_TYPE_ARG1) || \ + !defined(RECVFROM_TYPE_ARG2) || \ + !defined(RECVFROM_TYPE_ARG3) || \ + !defined(RECVFROM_TYPE_ARG4) || \ + !defined(RECVFROM_TYPE_ARG5) || \ + !defined(RECVFROM_TYPE_ARG6) || \ + !defined(RECVFROM_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_recvfrom + /* */ +#else +#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \ + (RECVFROM_TYPE_ARG2 *)(b), \ + (RECVFROM_TYPE_ARG3) (bl), \ + (RECVFROM_TYPE_ARG4) (0), \ + (RECVFROM_TYPE_ARG5 *)(f), \ + (RECVFROM_TYPE_ARG6 *)(fl)) +#endif +#else /* HAVE_RECVFROM */ +#ifndef sreadfrom + /* */ + Error Missing_definition_of_macro_sreadfrom + /* */ +#endif +#endif /* HAVE_RECVFROM */ + + +#ifdef RECVFROM_TYPE_ARG6_IS_VOID +# define RECVFROM_ARG6_T int +#else +# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6 +#endif +#endif /* if 0 */ + + +/* + * Function-like macro definition used to close a socket. + */ + +#if defined(HAVE_CLOSESOCKET) +# define sclose(x) closesocket((x)) +#elif defined(HAVE_CLOSESOCKET_CAMEL) +# define sclose(x) CloseSocket((x)) +#elif defined(HAVE_CLOSE_S) +# define sclose(x) close_s((x)) +#elif defined(USE_LWIPSOCK) +# define sclose(x) lwip_close((x)) +#else +# define sclose(x) close((x)) +#endif + +/* + * Stack-independent version of fcntl() on sockets: + */ +#if defined(USE_LWIPSOCK) +# define sfcntl lwip_fcntl +#else +# define sfcntl fcntl +#endif + +/* + * Uppercase macro versions of ANSI/ISO is*() functions/macros which + * avoid negative number inputs with argument byte codes > 127. + */ + +#define ISSPACE(x) (isspace((int) ((unsigned char)x))) +#define ISDIGIT(x) (isdigit((int) ((unsigned char)x))) +#define ISALNUM(x) (isalnum((int) ((unsigned char)x))) +#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) +#define ISGRAPH(x) (isgraph((int) ((unsigned char)x))) +#define ISALPHA(x) (isalpha((int) ((unsigned char)x))) +#define ISPRINT(x) (isprint((int) ((unsigned char)x))) +#define ISUPPER(x) (isupper((int) ((unsigned char)x))) +#define ISLOWER(x) (islower((int) ((unsigned char)x))) +#define ISASCII(x) (isascii((int) ((unsigned char)x))) + +#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \ + (((unsigned char)x) == '\t')) + +#define TOLOWER(x) (tolower((int) ((unsigned char)x))) + + +/* + * 'bool' stuff compatible with HP-UX headers. + */ + +#if defined(__hpux) && !defined(HAVE_BOOL_T) + typedef int bool; +# define false 0 +# define true 1 +# define HAVE_BOOL_T +#endif + + +/* + * 'bool' exists on platforms with , i.e. C99 platforms. + * On non-C99 platforms there's no bool, so define an enum for that. + * On C99 platforms 'false' and 'true' also exist. Enum uses a + * global namespace though, so use bool_false and bool_true. + */ + +#ifndef HAVE_BOOL_T + typedef enum { + bool_false = 0, + bool_true = 1 + } bool; + +/* + * Use a define to let 'true' and 'false' use those enums. There + * are currently no use of true and false in libcurl proper, but + * there are some in the examples. This will cater for any later + * code happening to use true and false. + */ +# define false bool_false +# define true bool_true +# define HAVE_BOOL_T +#endif + + +/* + * Redefine TRUE and FALSE too, to catch current use. With this + * change, 'bool found = 1' will give a warning on MIPSPro, but + * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro, + * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too. + */ + +#ifndef TRUE +#define TRUE true +#endif +#ifndef FALSE +#define FALSE false +#endif + + +/* + * Macro WHILE_FALSE may be used to build single-iteration do-while loops, + * avoiding compiler warnings. Mostly intended for other macro definitions. + */ + +#define WHILE_FALSE while(0) + +#if defined(_MSC_VER) && !defined(__POCC__) +# undef WHILE_FALSE +# if (_MSC_VER < 1500) +# define WHILE_FALSE while(1, 0) +# else +# define WHILE_FALSE \ +__pragma(warning(push)) \ +__pragma(warning(disable:4127)) \ +while(0) \ +__pragma(warning(pop)) +# endif +#endif + + +/* + * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type. + */ + +#ifndef HAVE_SIG_ATOMIC_T +typedef int sig_atomic_t; +#define HAVE_SIG_ATOMIC_T +#endif + + +/* + * Convenience SIG_ATOMIC_T definition + */ + +#ifdef HAVE_SIG_ATOMIC_T_VOLATILE +#define SIG_ATOMIC_T static sig_atomic_t +#else +#define SIG_ATOMIC_T static volatile sig_atomic_t +#endif + + +/* + * Default return type for signal handlers. + */ + +#ifndef RETSIGTYPE +#define RETSIGTYPE void +#endif + + +/* + * Macro used to include code only in debug builds. + */ + +#ifdef DEBUGBUILD +#define DEBUGF(x) x +#else +#define DEBUGF(x) do { } WHILE_FALSE +#endif + + +/* + * Macro used to include assertion code only in debug builds. + */ + +#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H) +#define DEBUGASSERT(x) assert(x) +#else +#define DEBUGASSERT(x) do { } WHILE_FALSE +#endif + + +/* + * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno + * (or equivalent) on this platform to hide platform details to code using it. + */ + +#ifdef USE_WINSOCK +#define SOCKERRNO ((int)WSAGetLastError()) +#define SET_SOCKERRNO(x) (WSASetLastError((int)(x))) +#else +#define SOCKERRNO (errno) +#define SET_SOCKERRNO(x) (errno = (x)) +#endif + + +/* + * Macro ERRNO / SET_ERRNO() returns / sets the NOT *socket-related* errno + * (or equivalent) on this platform to hide platform details to code using it. + */ + +#if defined(WIN32) && !defined(USE_LWIPSOCK) +#define ERRNO ((int)GetLastError()) +#define SET_ERRNO(x) (SetLastError((DWORD)(x))) +#else +#define ERRNO (errno) +#define SET_ERRNO(x) (errno = (x)) +#endif + + +/* + * Portable error number symbolic names defined to Winsock error codes. + */ + +#ifdef USE_WINSOCK +#undef EBADF /* override definition in errno.h */ +#define EBADF WSAEBADF +#undef EINTR /* override definition in errno.h */ +#define EINTR WSAEINTR +#undef EINVAL /* override definition in errno.h */ +#define EINVAL WSAEINVAL +#undef EWOULDBLOCK /* override definition in errno.h */ +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef EINPROGRESS /* override definition in errno.h */ +#define EINPROGRESS WSAEINPROGRESS +#undef EALREADY /* override definition in errno.h */ +#define EALREADY WSAEALREADY +#undef ENOTSOCK /* override definition in errno.h */ +#define ENOTSOCK WSAENOTSOCK +#undef EDESTADDRREQ /* override definition in errno.h */ +#define EDESTADDRREQ WSAEDESTADDRREQ +#undef EMSGSIZE /* override definition in errno.h */ +#define EMSGSIZE WSAEMSGSIZE +#undef EPROTOTYPE /* override definition in errno.h */ +#define EPROTOTYPE WSAEPROTOTYPE +#undef ENOPROTOOPT /* override definition in errno.h */ +#define ENOPROTOOPT WSAENOPROTOOPT +#undef EPROTONOSUPPORT /* override definition in errno.h */ +#define EPROTONOSUPPORT WSAEPROTONOSUPPORT +#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +#undef EOPNOTSUPP /* override definition in errno.h */ +#define EOPNOTSUPP WSAEOPNOTSUPP +#define EPFNOSUPPORT WSAEPFNOSUPPORT +#undef EAFNOSUPPORT /* override definition in errno.h */ +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#undef EADDRINUSE /* override definition in errno.h */ +#define EADDRINUSE WSAEADDRINUSE +#undef EADDRNOTAVAIL /* override definition in errno.h */ +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL +#undef ENETDOWN /* override definition in errno.h */ +#define ENETDOWN WSAENETDOWN +#undef ENETUNREACH /* override definition in errno.h */ +#define ENETUNREACH WSAENETUNREACH +#undef ENETRESET /* override definition in errno.h */ +#define ENETRESET WSAENETRESET +#undef ECONNABORTED /* override definition in errno.h */ +#define ECONNABORTED WSAECONNABORTED +#undef ECONNRESET /* override definition in errno.h */ +#define ECONNRESET WSAECONNRESET +#undef ENOBUFS /* override definition in errno.h */ +#define ENOBUFS WSAENOBUFS +#undef EISCONN /* override definition in errno.h */ +#define EISCONN WSAEISCONN +#undef ENOTCONN /* override definition in errno.h */ +#define ENOTCONN WSAENOTCONN +#define ESHUTDOWN WSAESHUTDOWN +#define ETOOMANYREFS WSAETOOMANYREFS +#undef ETIMEDOUT /* override definition in errno.h */ +#define ETIMEDOUT WSAETIMEDOUT +#undef ECONNREFUSED /* override definition in errno.h */ +#define ECONNREFUSED WSAECONNREFUSED +#undef ELOOP /* override definition in errno.h */ +#define ELOOP WSAELOOP +#ifndef ENAMETOOLONG /* possible previous definition in errno.h */ +#define ENAMETOOLONG WSAENAMETOOLONG +#endif +#define EHOSTDOWN WSAEHOSTDOWN +#undef EHOSTUNREACH /* override definition in errno.h */ +#define EHOSTUNREACH WSAEHOSTUNREACH +#ifndef ENOTEMPTY /* possible previous definition in errno.h */ +#define ENOTEMPTY WSAENOTEMPTY +#endif +#define EPROCLIM WSAEPROCLIM +#define EUSERS WSAEUSERS +#define EDQUOT WSAEDQUOT +#define ESTALE WSAESTALE +#define EREMOTE WSAEREMOTE +#endif + +/* + * Macro argv_item_t hides platform details to code using it. + */ + +#ifdef __VMS +#define argv_item_t __char_ptr32 +#else +#define argv_item_t char * +#endif + + +/* + * We use this ZERO_NULL to avoid picky compiler warnings, + * when assigning a NULL pointer to a function pointer var. + */ + +#define ZERO_NULL 0 + + +#endif /* HEADER_CURL_SETUP_ONCE_H */ + diff --git a/libcurl/src/lib/curl_sspi.c b/libcurl/src/lib/curl_sspi.c new file mode 100644 index 0000000..6a58437 --- /dev/null +++ b/libcurl/src/lib/curl_sspi.c @@ -0,0 +1,252 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WINDOWS_SSPI + +#include +#include "curl_sspi.h" +#include "curl_multibyte.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* We use our own typedef here since some headers might lack these */ +typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID); + +/* See definition of SECURITY_ENTRYPOINT in sspi.h */ +#ifdef UNICODE +# ifdef _WIN32_WCE +# define SECURITYENTRYPOINT L"InitSecurityInterfaceW" +# else +# define SECURITYENTRYPOINT "InitSecurityInterfaceW" +# endif +#else +# define SECURITYENTRYPOINT "InitSecurityInterfaceA" +#endif + +/* Handle of security.dll or secur32.dll, depending on Windows version */ +HMODULE s_hSecDll = NULL; + +/* Pointer to SSPI dispatch table */ +PSecurityFunctionTable s_pSecFn = NULL; + +/* + * Curl_sspi_global_init() + * + * This is used to load the Security Service Provider Interface (SSPI) + * dynamic link library portably across all Windows versions, without + * the need to directly link libcurl, nor the application using it, at + * build time. + * + * Once this function has been executed, Windows SSPI functions can be + * called through the Security Service Provider Interface dispatch table. + */ +CURL_STATIC CURLcode Curl_sspi_global_init(void) +{ + bool securityDll = FALSE; + INITSECURITYINTERFACE_FN pInitSecurityInterface; + + /* If security interface is not yet initialized try to do this */ + if(!s_hSecDll) { + /* Security Service Provider Interface (SSPI) functions are located in + * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP + * have both these DLLs (security.dll forwards calls to secur32.dll) */ + DWORD majorVersion = 4; + DWORD platformId = VER_PLATFORM_WIN32_NT; + +#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \ + (_WIN32_WINNT < _WIN32_WINNT_WIN2K) + OSVERSIONINFO osver; + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + + /* Find out Windows version */ + if(!GetVersionEx(&osver)) + return CURLE_FAILED_INIT; + + /* Verify the major version number == 4 and platform id == WIN_NT */ + if(osver.dwMajorVersion == majorVersion && + osver.dwPlatformId == platformId) + securityDll = TRUE; +#else + ULONGLONG majorVersionMask; + ULONGLONG platformIdMask; + OSVERSIONINFOEX osver; + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + osver.dwMajorVersion = majorVersion; + osver.dwPlatformId = platformId; + majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); + platformIdMask = VerSetConditionMask(0, VER_PLATFORMID, VER_EQUAL); + + /* Verify the major version number == 4 and platform id == WIN_NT */ + if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask) && + VerifyVersionInfo(&osver, VER_PLATFORMID, platformIdMask)) + securityDll = TRUE; +#endif + + /* Load SSPI dll into the address space of the calling process */ + if(securityDll) + s_hSecDll = LoadLibrary(TEXT("security.dll")); + else + s_hSecDll = LoadLibrary(TEXT("secur32.dll")); + if(!s_hSecDll) + return CURLE_FAILED_INIT; + + /* Get address of the InitSecurityInterfaceA function from the SSPI dll */ + pInitSecurityInterface = (INITSECURITYINTERFACE_FN) + GetProcAddress(s_hSecDll, SECURITYENTRYPOINT); + if(!pInitSecurityInterface) + return CURLE_FAILED_INIT; + + /* Get pointer to Security Service Provider Interface dispatch table */ + s_pSecFn = pInitSecurityInterface(); + if(!s_pSecFn) + return CURLE_FAILED_INIT; + } + + return CURLE_OK; +} + +/* + * Curl_sspi_global_cleanup() + * + * This deinitializes the Security Service Provider Interface from libcurl. + */ + +CURL_STATIC void Curl_sspi_global_cleanup(void) +{ + if(s_hSecDll) { + FreeLibrary(s_hSecDll); + s_hSecDll = NULL; + s_pSecFn = NULL; + } +} + +/* + * Curl_create_sspi_identity() + * + * This is used to populate a SSPI identity structure based on the supplied + * username and password. + * + * Parameters: + * + * userp [in] - The user name in the format User or Domain\User. + * passdwp [in] - The user's password. + * identity [in/out] - The identity structure. + * + * Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity) +{ + xcharp_u useranddomain; + xcharp_u user, dup_user; + xcharp_u domain, dup_domain; + xcharp_u passwd, dup_passwd; + size_t domlen = 0; + + domain.const_tchar_ptr = TEXT(""); + + /* Initialize the identity */ + memset(identity, 0, sizeof(*identity)); + + useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp); + if(!useranddomain.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + + user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\')); + if(!user.const_tchar_ptr) + user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/')); + + if(user.tchar_ptr) { + domain.tchar_ptr = useranddomain.tchar_ptr; + domlen = user.tchar_ptr - useranddomain.tchar_ptr; + user.tchar_ptr++; + } + else { + user.tchar_ptr = useranddomain.tchar_ptr; + domain.const_tchar_ptr = TEXT(""); + domlen = 0; + } + + /* Setup the identity's user and length */ + dup_user.tchar_ptr = _tcsdup(user.tchar_ptr); + if(!dup_user.tchar_ptr) { + Curl_unicodefree(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + identity->User = dup_user.tbyte_ptr; + identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr)); + dup_user.tchar_ptr = NULL; + + /* Setup the identity's domain and length */ + dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1)); + if(!dup_domain.tchar_ptr) { + Curl_unicodefree(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen); + *(dup_domain.tchar_ptr + domlen) = TEXT('\0'); + identity->Domain = dup_domain.tbyte_ptr; + identity->DomainLength = curlx_uztoul(domlen); + dup_domain.tchar_ptr = NULL; + + Curl_unicodefree(useranddomain.tchar_ptr); + + /* Setup ntlm identity's password and length */ + passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp); + if(!passwd.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr); + if(!dup_passwd.tchar_ptr) { + Curl_unicodefree(passwd.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + identity->Password = dup_passwd.tbyte_ptr; + identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr)); + dup_passwd.tchar_ptr = NULL; + + Curl_unicodefree(passwd.tchar_ptr); + + /* Setup the identity's flags */ + identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY; + + return CURLE_OK; +} + +CURL_STATIC void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity) +{ + if(identity) { + Curl_safefree(identity->User); + Curl_safefree(identity->Password); + Curl_safefree(identity->Domain); + } +} + +#endif /* USE_WINDOWS_SSPI */ diff --git a/libcurl/src/lib/curl_sspi.h b/libcurl/src/lib/curl_sspi.h new file mode 100644 index 0000000..b4cd05f --- /dev/null +++ b/libcurl/src/lib/curl_sspi.h @@ -0,0 +1,342 @@ +#ifndef HEADER_CURL_SSPI_H +#define HEADER_CURL_SSPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WINDOWS_SSPI + +#include + +/* + * When including the following three headers, it is mandatory to define either + * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code. + */ + +#undef SECURITY_WIN32 +#undef SECURITY_KERNEL +#define SECURITY_WIN32 1 +#include +#include +#include + +CURL_STATIC CURLcode Curl_sspi_global_init(void); +CURL_STATIC void Curl_sspi_global_cleanup(void); + +/* This is used to generate an SSPI identity structure */ +CURL_STATIC CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity); + +/* This is used to free an SSPI identity structure */ +CURL_STATIC void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity); + +/* Forward-declaration of global variables defined in curl_sspi.c */ +extern HMODULE s_hSecDll; +extern PSecurityFunctionTable s_pSecFn; + +/* Provide some definitions missing in old headers */ +#define SP_NAME_DIGEST "WDigest" +#define SP_NAME_NTLM "NTLM" +#define SP_NAME_NEGOTIATE "Negotiate" +#define SP_NAME_KERBEROS "Kerberos" + +#ifndef ISC_REQ_USE_HTTP_STYLE +#define ISC_REQ_USE_HTTP_STYLE 0x01000000 +#endif + +#ifndef ISC_RET_REPLAY_DETECT +#define ISC_RET_REPLAY_DETECT 0x00000004 +#endif + +#ifndef ISC_RET_SEQUENCE_DETECT +#define ISC_RET_SEQUENCE_DETECT 0x00000008 +#endif + +#ifndef ISC_RET_CONFIDENTIALITY +#define ISC_RET_CONFIDENTIALITY 0x00000010 +#endif + +#ifndef ISC_RET_ALLOCATED_MEMORY +#define ISC_RET_ALLOCATED_MEMORY 0x00000100 +#endif + +#ifndef ISC_RET_STREAM +#define ISC_RET_STREAM 0x00008000 +#endif + +#ifndef SEC_E_INSUFFICIENT_MEMORY +# define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L) +#endif +#ifndef SEC_E_INVALID_HANDLE +# define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L) +#endif +#ifndef SEC_E_UNSUPPORTED_FUNCTION +# define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L) +#endif +#ifndef SEC_E_TARGET_UNKNOWN +# define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L) +#endif +#ifndef SEC_E_INTERNAL_ERROR +# define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L) +#endif +#ifndef SEC_E_SECPKG_NOT_FOUND +# define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L) +#endif +#ifndef SEC_E_NOT_OWNER +# define SEC_E_NOT_OWNER ((HRESULT)0x80090306L) +#endif +#ifndef SEC_E_CANNOT_INSTALL +# define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L) +#endif +#ifndef SEC_E_INVALID_TOKEN +# define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L) +#endif +#ifndef SEC_E_CANNOT_PACK +# define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L) +#endif +#ifndef SEC_E_QOP_NOT_SUPPORTED +# define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL) +#endif +#ifndef SEC_E_NO_IMPERSONATION +# define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL) +#endif +#ifndef SEC_E_LOGON_DENIED +# define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL) +#endif +#ifndef SEC_E_UNKNOWN_CREDENTIALS +# define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL) +#endif +#ifndef SEC_E_NO_CREDENTIALS +# define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL) +#endif +#ifndef SEC_E_MESSAGE_ALTERED +# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL) +#endif +#ifndef SEC_E_OUT_OF_SEQUENCE +# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L) +#endif +#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY +# define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L) +#endif +#ifndef SEC_E_BAD_PKGID +# define SEC_E_BAD_PKGID ((HRESULT)0x80090316L) +#endif +#ifndef SEC_E_CONTEXT_EXPIRED +# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L) +#endif +#ifndef SEC_E_INCOMPLETE_MESSAGE +# define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L) +#endif +#ifndef SEC_E_INCOMPLETE_CREDENTIALS +# define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L) +#endif +#ifndef SEC_E_BUFFER_TOO_SMALL +# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L) +#endif +#ifndef SEC_E_WRONG_PRINCIPAL +# define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L) +#endif +#ifndef SEC_E_TIME_SKEW +# define SEC_E_TIME_SKEW ((HRESULT)0x80090324L) +#endif +#ifndef SEC_E_UNTRUSTED_ROOT +# define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L) +#endif +#ifndef SEC_E_ILLEGAL_MESSAGE +# define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L) +#endif +#ifndef SEC_E_CERT_UNKNOWN +# define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L) +#endif +#ifndef SEC_E_CERT_EXPIRED +# define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L) +#endif +#ifndef SEC_E_ENCRYPT_FAILURE +# define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L) +#endif +#ifndef SEC_E_DECRYPT_FAILURE +# define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L) +#endif +#ifndef SEC_E_ALGORITHM_MISMATCH +# define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L) +#endif +#ifndef SEC_E_SECURITY_QOS_FAILED +# define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L) +#endif +#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED +# define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L) +#endif +#ifndef SEC_E_NO_TGT_REPLY +# define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L) +#endif +#ifndef SEC_E_NO_IP_ADDRESSES +# define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L) +#endif +#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE +# define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L) +#endif +#ifndef SEC_E_CRYPTO_SYSTEM_INVALID +# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L) +#endif +#ifndef SEC_E_MAX_REFERRALS_EXCEEDED +# define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L) +#endif +#ifndef SEC_E_MUST_BE_KDC +# define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L) +#endif +#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED +# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL) +#endif +#ifndef SEC_E_TOO_MANY_PRINCIPALS +# define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL) +#endif +#ifndef SEC_E_NO_PA_DATA +# define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL) +#endif +#ifndef SEC_E_PKINIT_NAME_MISMATCH +# define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL) +#endif +#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED +# define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL) +#endif +#ifndef SEC_E_SHUTDOWN_IN_PROGRESS +# define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL) +#endif +#ifndef SEC_E_KDC_INVALID_REQUEST +# define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L) +#endif +#ifndef SEC_E_KDC_UNABLE_TO_REFER +# define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L) +#endif +#ifndef SEC_E_KDC_UNKNOWN_ETYPE +# define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L) +#endif +#ifndef SEC_E_UNSUPPORTED_PREAUTH +# define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L) +#endif +#ifndef SEC_E_DELEGATION_REQUIRED +# define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L) +#endif +#ifndef SEC_E_BAD_BINDINGS +# define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L) +#endif +#ifndef SEC_E_MULTIPLE_ACCOUNTS +# define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L) +#endif +#ifndef SEC_E_NO_KERB_KEY +# define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L) +#endif +#ifndef SEC_E_CERT_WRONG_USAGE +# define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L) +#endif +#ifndef SEC_E_DOWNGRADE_DETECTED +# define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L) +#endif +#ifndef SEC_E_SMARTCARD_CERT_REVOKED +# define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L) +#endif +#ifndef SEC_E_ISSUING_CA_UNTRUSTED +# define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L) +#endif +#ifndef SEC_E_REVOCATION_OFFLINE_C +# define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L) +#endif +#ifndef SEC_E_PKINIT_CLIENT_FAILURE +# define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L) +#endif +#ifndef SEC_E_SMARTCARD_CERT_EXPIRED +# define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L) +#endif +#ifndef SEC_E_NO_S4U_PROT_SUPPORT +# define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L) +#endif +#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE +# define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L) +#endif +#ifndef SEC_E_REVOCATION_OFFLINE_KDC +# define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L) +#endif +#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC +# define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L) +#endif +#ifndef SEC_E_KDC_CERT_EXPIRED +# define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL) +#endif +#ifndef SEC_E_KDC_CERT_REVOKED +# define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL) +#endif +#ifndef SEC_E_INVALID_PARAMETER +# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL) +#endif +#ifndef SEC_E_DELEGATION_POLICY +# define SEC_E_DELEGATION_POLICY ((HRESULT)0x8009035EL) +#endif +#ifndef SEC_E_POLICY_NLTM_ONLY +# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL) +#endif + +#ifndef SEC_I_CONTINUE_NEEDED +# define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L) +#endif +#ifndef SEC_I_COMPLETE_NEEDED +# define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L) +#endif +#ifndef SEC_I_COMPLETE_AND_CONTINUE +# define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L) +#endif +#ifndef SEC_I_LOCAL_LOGON +# define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L) +#endif +#ifndef SEC_I_CONTEXT_EXPIRED +# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L) +#endif +#ifndef SEC_I_INCOMPLETE_CREDENTIALS +# define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L) +#endif +#ifndef SEC_I_RENEGOTIATE +# define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L) +#endif +#ifndef SEC_I_NO_LSA_CONTEXT +# define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L) +#endif +#ifndef SEC_I_SIGNATURE_NEEDED +# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL) +#endif + +#ifdef UNICODE +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE +#else +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI +#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 /* HEADER_CURL_SSPI_H */ diff --git a/libcurl/src/lib/curl_threads.c b/libcurl/src/lib/curl_threads.c new file mode 100644 index 0000000..42556bd --- /dev/null +++ b/libcurl/src/lib/curl_threads.c @@ -0,0 +1,136 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_THREADS_POSIX) +# ifdef HAVE_PTHREAD_H +# include +# endif +#elif defined(USE_THREADS_WIN32) +# ifdef HAVE_PROCESS_H +# include +# endif +#endif + +#include "curl_threads.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#if defined(USE_THREADS_POSIX) + +struct curl_actual_call { + unsigned int (*func)(void *); + void *arg; +}; + +static void *curl_thread_create_thunk(void *arg) +{ + struct curl_actual_call * ac = arg; + unsigned int (*func)(void *) = ac->func; + void *real_arg = ac->arg; + + free(ac); + + (*func)(real_arg); + + return 0; +} + +CURL_STATIC curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg) +{ + curl_thread_t t = malloc(sizeof(pthread_t)); + struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call)); + if(!(ac && t)) + goto err; + + ac->func = func; + ac->arg = arg; + + if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0) + goto err; + + return t; + +err: + free(t); + free(ac); + return curl_thread_t_null; +} + +CURL_STATIC void Curl_thread_destroy(curl_thread_t hnd) +{ + if(hnd != curl_thread_t_null) { + pthread_detach(*hnd); + free(hnd); + } +} + +CURL_STATIC int Curl_thread_join(curl_thread_t *hnd) +{ + int ret = (pthread_join(**hnd, NULL) == 0); + + free(*hnd); + *hnd = curl_thread_t_null; + + return ret; +} + +#elif defined(USE_THREADS_WIN32) + +CURL_STATIC curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), + void *arg) +{ +#ifdef _WIN32_WCE + return CreateThread(NULL, 0, func, arg, 0, NULL); +#else + curl_thread_t t; + t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL); + if((t == 0) || (t == (curl_thread_t)-1L)) + return curl_thread_t_null; + return t; +#endif +} + +CURL_STATIC void Curl_thread_destroy(curl_thread_t hnd) +{ + CloseHandle(hnd); +} + +CURL_STATIC int Curl_thread_join(curl_thread_t *hnd) +{ +#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ + (_WIN32_WINNT < _WIN32_WINNT_VISTA) + int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); +#else + int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); +#endif + + Curl_thread_destroy(*hnd); + + *hnd = curl_thread_t_null; + + return ret; +} + +#endif /* USE_THREADS_* */ diff --git a/libcurl/src/lib/curl_threads.h b/libcurl/src/lib/curl_threads.h new file mode 100644 index 0000000..20bbcdb --- /dev/null +++ b/libcurl/src/lib/curl_threads.h @@ -0,0 +1,62 @@ +#ifndef HEADER_CURL_THREADS_H +#define HEADER_CURL_THREADS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_THREADS_POSIX) +# define CURL_STDCALL +# define curl_mutex_t pthread_mutex_t +# define curl_thread_t pthread_t * +# define curl_thread_t_null (pthread_t *)0 +# define Curl_mutex_init(m) pthread_mutex_init(m, NULL) +# define Curl_mutex_acquire(m) pthread_mutex_lock(m) +# define Curl_mutex_release(m) pthread_mutex_unlock(m) +# define Curl_mutex_destroy(m) pthread_mutex_destroy(m) +#elif defined(USE_THREADS_WIN32) +# define CURL_STDCALL __stdcall +# define curl_mutex_t CRITICAL_SECTION +# define curl_thread_t HANDLE +# define curl_thread_t_null (HANDLE)0 +# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ + (_WIN32_WINNT < _WIN32_WINNT_VISTA) +# define Curl_mutex_init(m) InitializeCriticalSection(m) +# else +# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1) +# endif +# define Curl_mutex_acquire(m) EnterCriticalSection(m) +# define Curl_mutex_release(m) LeaveCriticalSection(m) +# define Curl_mutex_destroy(m) DeleteCriticalSection(m) +#endif + +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + +CURL_STATIC curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), + void *arg); + +CURL_STATIC void Curl_thread_destroy(curl_thread_t hnd); + +CURL_STATIC int Curl_thread_join(curl_thread_t *hnd); + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* HEADER_CURL_THREADS_H */ diff --git a/libcurl/src/lib/curlx.h b/libcurl/src/lib/curlx.h new file mode 100644 index 0000000..979e7d7 --- /dev/null +++ b/libcurl/src/lib/curlx.h @@ -0,0 +1,118 @@ +#ifndef HEADER_CURL_CURLX_H +#define HEADER_CURL_CURLX_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Defines protos and includes all header files that provide the curlx_* + * functions. The curlx_* functions are not part of the libcurl API, but are + * stand-alone functions whose sources can be built and linked by apps if need + * be. + */ + +#include +/* this is still a public header file that provides the curl_mprintf() + functions while they still are offered publicly. They will be made library- + private one day */ + +#include "strequal.h" +/* "strequal.h" provides the strequal protos */ + +#include "strtoofft.h" +/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a + curl_off_t number from a given string. +*/ + +#include "timeval.h" +/* + "timeval.h" sets up a 'struct timeval' even for platforms that otherwise + don't have one and has protos for these functions: + + curlx_tvnow() + curlx_tvdiff() + curlx_tvdiff_secs() +*/ + +#include "nonblock.h" +/* "nonblock.h" provides curlx_nonblock() */ + +#include "warnless.h" +/* "warnless.h" provides functions: + + curlx_ultous() + curlx_ultouc() + curlx_uztosi() +*/ + +/* Now setup curlx_ * names for the functions that are to become curlx_ and + be removed from a future libcurl official API: + curlx_getenv + curlx_mprintf (and its variations) + curlx_strequal + curlx_strnequal + +*/ + +#define curlx_getenv curl_getenv +#define curlx_strequal curl_strequal +#define curlx_strnequal curl_strnequal +#define curlx_raw_equal Curl_raw_equal +#define curlx_mvsnprintf curl_mvsnprintf +#define curlx_msnprintf curl_msnprintf +#define curlx_maprintf curl_maprintf +#define curlx_mvaprintf curl_mvaprintf +#define curlx_msprintf curl_msprintf +#define curlx_mprintf curl_mprintf +#define curlx_mfprintf curl_mfprintf +#define curlx_mvsprintf curl_mvsprintf +#define curlx_mvprintf curl_mvprintf +#define curlx_mvfprintf curl_mvfprintf + +#ifdef ENABLE_CURLX_PRINTF +/* If this define is set, we define all "standard" printf() functions to use + the curlx_* version instead. It makes the source code transparent and + easier to understand/patch. Undefine them first. */ +# undef printf +# undef fprintf +# undef sprintf +# undef snprintf +# undef vprintf +# undef vfprintf +# undef vsprintf +# undef vsnprintf +# undef aprintf +# undef vaprintf + +# define printf curlx_mprintf +# define fprintf curlx_mfprintf +# define sprintf curlx_msprintf +# define snprintf curlx_msnprintf +# define vprintf curlx_mvprintf +# define vfprintf curlx_mvfprintf +# define vsprintf curlx_mvsprintf +# define vsnprintf curlx_mvsnprintf +# define aprintf curlx_maprintf +# define vaprintf curlx_mvaprintf +#endif /* ENABLE_CURLX_PRINTF */ + +#endif /* HEADER_CURL_CURLX_H */ + diff --git a/libcurl/src/lib/dict.c b/libcurl/src/lib/dict.c new file mode 100644 index 0000000..06d7699 --- /dev/null +++ b/libcurl/src/lib/dict.c @@ -0,0 +1,279 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_DICT + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" + +#include "progress.h" +#include "strequal.h" +#include "dict.h" +#include "rawstr.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static CURLcode dict_do(struct connectdata *conn, bool *done); + +/* + * DICT protocol handler. + */ + +const struct Curl_handler Curl_handler_dict = { + "DICT", /* scheme */ + ZERO_NULL, /* setup_connection */ + dict_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_DICT, /* defport */ + CURLPROTO_DICT, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + +static char *unescape_word(struct SessionHandle *data, const char *inputbuff) +{ + char *newp; + char *dictp; + char *ptr; + int len; + char ch; + int olen=0; + + newp = curl_easy_unescape(data, inputbuff, 0, &len); + if(!newp) + return NULL; + + dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */ + if(dictp) { + /* According to RFC2229 section 2.2, these letters need to be escaped with + \[letter] */ + for(ptr = newp; + (ch = *ptr) != 0; + ptr++) { + if((ch <= 32) || (ch == 127) || + (ch == '\'') || (ch == '\"') || (ch == '\\')) { + dictp[olen++] = '\\'; + } + dictp[olen++] = ch; + } + dictp[olen]=0; + } + free(newp); + return dictp; +} + +static CURLcode dict_do(struct connectdata *conn, bool *done) +{ + char *word; + char *eword; + char *ppath; + char *database = NULL; + char *strategy = NULL; + char *nthdef = NULL; /* This is not part of the protocol, but required + by RFC 2229 */ + CURLcode result=CURLE_OK; + struct SessionHandle *data=conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + + char *path = data->state.path; + curl_off_t *bytecount = &data->req.bytecount; + + *done = TRUE; /* unconditionally */ + + if(conn->bits.user_passwd) { + /* AUTH is missing */ + } + + if(Curl_raw_nequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) || + Curl_raw_nequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) || + Curl_raw_nequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) { + + word = strchr(path, ':'); + if(word) { + word++; + database = strchr(word, ':'); + if(database) { + *database++ = (char)0; + strategy = strchr(database, ':'); + if(strategy) { + *strategy++ = (char)0; + nthdef = strchr(strategy, ':'); + if(nthdef) { + *nthdef = (char)0; + } + } + } + } + + if((word == NULL) || (*word == (char)0)) { + infof(data, "lookup word is missing\n"); + word=(char *)"default"; + } + if((database == NULL) || (*database == (char)0)) { + database = (char *)"!"; + } + if((strategy == NULL) || (*strategy == (char)0)) { + strategy = (char *)"."; + } + + eword = unescape_word(data, word); + if(!eword) + return CURLE_OUT_OF_MEMORY; + + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "MATCH " + "%s " /* database */ + "%s " /* strategy */ + "%s\r\n" /* word */ + "QUIT\r\n", + + database, + strategy, + eword + ); + + free(eword); + + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, + -1, NULL); /* no upload */ + } + else if(Curl_raw_nequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) || + Curl_raw_nequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) || + Curl_raw_nequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) { + + word = strchr(path, ':'); + if(word) { + word++; + database = strchr(word, ':'); + if(database) { + *database++ = (char)0; + nthdef = strchr(database, ':'); + if(nthdef) { + *nthdef = (char)0; + } + } + } + + if((word == NULL) || (*word == (char)0)) { + infof(data, "lookup word is missing\n"); + word=(char *)"default"; + } + if((database == NULL) || (*database == (char)0)) { + database = (char *)"!"; + } + + eword = unescape_word(data, word); + if(!eword) + return CURLE_OUT_OF_MEMORY; + + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "DEFINE " + "%s " /* database */ + "%s\r\n" /* word */ + "QUIT\r\n", + database, + eword); + + free(eword); + + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, + -1, NULL); /* no upload */ + } + else { + + ppath = strchr(path, '/'); + if(ppath) { + int i; + + ppath++; + for(i = 0; ppath[i]; i++) { + if(ppath[i] == ':') + ppath[i] = ' '; + } + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "%s\r\n" + "QUIT\r\n", ppath); + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + + Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL); + } + } + + return CURLE_OK; +} +#endif /*CURL_DISABLE_DICT*/ diff --git a/libcurl/src/lib/dict.h b/libcurl/src/lib/dict.h new file mode 100644 index 0000000..44fd9d4 --- /dev/null +++ b/libcurl/src/lib/dict.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_DICT_H +#define HEADER_CURL_DICT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_DICT +extern const struct Curl_handler Curl_handler_dict; +#endif + +#endif /* HEADER_CURL_DICT_H */ diff --git a/libcurl/src/lib/dotdot.c b/libcurl/src/lib/dotdot.c new file mode 100644 index 0000000..418408e --- /dev/null +++ b/libcurl/src/lib/dotdot.c @@ -0,0 +1,170 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "dotdot.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * "Remove Dot Segments" + * http://tools.ietf.org/html/rfc3986#section-5.2.4 + */ + +/* + * Curl_dedotdotify() + * + * This function gets a zero-terminated path with dot and dotdot sequences + * passed in and strips them off according to the rules in RFC 3986 section + * 5.2.4. + * + * The function handles a query part ('?' + stuff) appended but it expects + * that fragments ('#' + stuff) have already been cut off. + * + * RETURNS + * + * an allocated dedotdotified output string + */ +CURL_STATIC char *Curl_dedotdotify(const char *input) +{ + size_t inlen = strlen(input); + char *clone; + size_t clen = inlen; /* the length of the cloned input */ + char *out = malloc(inlen+1); + char *outptr; + char *orgclone; + char *queryp; + if(!out) + return NULL; /* out of memory */ + + /* get a cloned copy of the input */ + clone = strdup(input); + if(!clone) { + free(out); + return NULL; + } + orgclone = clone; + outptr = out; + + /* + * To handle query-parts properly, we must find it and remove it during the + * dotdot-operation and then append it again at the end to the output + * string. + */ + queryp = strchr(clone, '?'); + if(queryp) + *queryp = 0; + + do { + + /* A. If the input buffer begins with a prefix of "../" or "./", then + remove that prefix from the input buffer; otherwise, */ + + if(!strncmp("./", clone, 2)) { + clone+=2; + clen-=2; + } + else if(!strncmp("../", clone, 3)) { + clone+=3; + clen-=3; + } + + /* B. if the input buffer begins with a prefix of "/./" or "/.", where + "." is a complete path segment, then replace that prefix with "/" in + the input buffer; otherwise, */ + else if(!strncmp("/./", clone, 3)) { + clone+=2; + clen-=2; + } + else if(!strcmp("/.", clone)) { + clone[1]='/'; + clone++; + clen-=1; + } + + /* C. if the input buffer begins with a prefix of "/../" or "/..", where + ".." is a complete path segment, then replace that prefix with "/" in + the input buffer and remove the last segment and its preceding "/" (if + any) from the output buffer; otherwise, */ + + else if(!strncmp("/../", clone, 4)) { + clone+=3; + clen-=3; + /* remove the last segment from the output buffer */ + while(outptr > out) { + outptr--; + if(*outptr == '/') + break; + } + *outptr = 0; /* zero-terminate where it stops */ + } + else if(!strcmp("/..", clone)) { + clone[2]='/'; + clone+=2; + clen-=2; + /* remove the last segment from the output buffer */ + while(outptr > out) { + outptr--; + if(*outptr == '/') + break; + } + *outptr = 0; /* zero-terminate where it stops */ + } + + /* D. if the input buffer consists only of "." or "..", then remove + that from the input buffer; otherwise, */ + + else if(!strcmp(".", clone) || !strcmp("..", clone)) { + *clone=0; + } + + else { + /* E. move the first path segment in the input buffer to the end of + the output buffer, including the initial "/" character (if any) and + any subsequent characters up to, but not including, the next "/" + character or the end of the input buffer. */ + + do { + *outptr++ = *clone++; + clen--; + } while(*clone && (*clone != '/')); + *outptr = 0; + } + + } while(*clone); + + if(queryp) { + size_t qlen; + /* There was a query part, append that to the output. The 'clone' string + may now have been altered so we copy from the original input string + from the correct index. */ + size_t oindex = queryp - orgclone; + qlen = strlen(&input[oindex]); + memcpy(outptr, &input[oindex], qlen+1); /* include the ending zero byte */ + } + + free(orgclone); + return out; +} diff --git a/libcurl/src/lib/dotdot.h b/libcurl/src/lib/dotdot.h new file mode 100644 index 0000000..e831732 --- /dev/null +++ b/libcurl/src/lib/dotdot.h @@ -0,0 +1,25 @@ +#ifndef HEADER_CURL_DOTDOT_H +#define HEADER_CURL_DOTDOT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +CURL_STATIC char *Curl_dedotdotify(const char *input); +#endif diff --git a/libcurl/src/lib/easy.c b/libcurl/src/lib/easy.c new file mode 100644 index 0000000..9492d3e --- /dev/null +++ b/libcurl/src/lib/easy.c @@ -0,0 +1,1130 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * See comment in curl_memory.h for the explanation of this sanity check. + */ + +#ifdef CURLX_NO_MEMORY_CALLBACKS +#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined" +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "strequal.h" +#include "urldata.h" +#include +#include "transfer.h" +#include "vtls/vtls.h" +#include "url.h" +#include "getinfo.h" +#include "hostip.h" +#include "share.h" +#include "strdup.h" +#include "progress.h" +#include "easyif.h" +#include "select.h" +#include "sendf.h" /* for failf function prototype */ +#include "curl_ntlm.h" +#include "connect.h" /* for Curl_getconnectinfo */ +#include "slist.h" +#include "amigaos.h" +#include "non-ascii.h" +#include "warnless.h" +#include "conncache.h" +#include "multiif.h" +#include "sigpipe.h" +#include "ssh.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* win32_cleanup() is for win32 socket cleanup functionality, the opposite + of win32_init() */ +static void win32_cleanup(void) +{ +#ifdef USE_WINSOCK + WSACleanup(); +#endif +#ifdef USE_WINDOWS_SSPI + Curl_sspi_global_cleanup(); +#endif +} + +/* win32_init() performs win32 socket initialization to properly setup the + stack to allow networking */ +static CURLcode win32_init(void) +{ +#ifdef USE_WINSOCK + WORD wVersionRequested; + WSADATA wsaData; + int res; + +#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) + Error IPV6_requires_winsock2 +#endif + + wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); + + res = WSAStartup(wVersionRequested, &wsaData); + + if(res != 0) + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + return CURLE_FAILED_INIT; + + /* Confirm that the Windows Sockets DLL supports what we need.*/ + /* Note that if the DLL supports versions greater */ + /* than wVersionRequested, it will still return */ + /* wVersionRequested in wVersion. wHighVersion contains the */ + /* highest supported version. */ + + if(LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) || + HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) { + /* Tell the user that we couldn't find a useable */ + + /* winsock.dll. */ + WSACleanup(); + return CURLE_FAILED_INIT; + } + /* The Windows Sockets DLL is acceptable. Proceed. */ +#elif defined(USE_LWIPSOCK) + lwip_init(); +#endif + +#ifdef USE_WINDOWS_SSPI + { + CURLcode result = Curl_sspi_global_init(); + if(result) + return result; + } +#endif + + return CURLE_OK; +} + +#ifdef USE_LIBIDN +/* + * Initialise use of IDNA library. + * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for + * idna_to_ascii_lz(). + */ +static void idna_init (void) +{ +#ifdef WIN32 + char buf[60]; + UINT cp = GetACP(); + + if(!getenv("CHARSET") && cp > 0) { + snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp); + putenv(buf); + } +#else + /* to do? */ +#endif +} +#endif /* USE_LIBIDN */ + +/* true globals -- for curl_global_init() and curl_global_cleanup() */ +static unsigned int initialized; +static long init_flags; + +///* +// * strdup (and other memory functions) is redefined in complicated +// * ways, but at this point it must be defined as the system-supplied strdup +// * so the callback pointer is initialized correctly. +// */ +//#if defined(_WIN32_WCE) +//#define system_strdup _strdup +//#elif !defined(HAVE_STRDUP) +//#define system_strdup curlx_strdup +//#else +//#define system_strdup strdup +//#endif +// +//#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +//# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ +//#endif +// +//#ifndef __SYMBIAN32__ +///* +// * If a memory-using function (like curl_getenv) is used before +// * curl_global_init() is called, we need to have these pointers set already. +// */ +//curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; +//curl_free_callback Curl_cfree = (curl_free_callback)free; +//curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; +//curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; +//curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; +//#if defined(WIN32) && defined(UNICODE) +//curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +//#endif +//#else +///* +// * Symbian OS doesn't support initialization to code in writeable static data. +// * Initialization will occur in the curl_global_init() call. +// */ +//curl_malloc_callback Curl_cmalloc; +//curl_free_callback Curl_cfree; +//curl_realloc_callback Curl_crealloc; +//curl_strdup_callback Curl_cstrdup; +//curl_calloc_callback Curl_ccalloc; +//#endif +// +//#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +//# pragma warning(default:4232) /* MSVC extension, dllimport identity */ +//#endif + +/** + * curl_global_init() globally initializes cURL given a bitwise set of the + * different features of what to initialize. + */ +CURLcode curl_global_init(long flags) +{ + if(initialized++) + return CURLE_OK; + + /* Setup the default memory functions here (again) */ + Curl_cmalloc = (curl_malloc_callback)malloc; + Curl_cfree = (curl_free_callback)free; + Curl_crealloc = (curl_realloc_callback)realloc; + Curl_cstrdup = (curl_strdup_callback)system_strdup; + Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) + Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif + + if(flags & CURL_GLOBAL_SSL) + if(!Curl_ssl_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n")); + return CURLE_FAILED_INIT; + } + + if(flags & CURL_GLOBAL_WIN32) + if(win32_init()) { + DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); + return CURLE_FAILED_INIT; + } + +#ifdef __AMIGA__ + if(!Curl_amiga_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#ifdef NETWARE + if(netware_init()) { + DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); + } +#endif + +#ifdef USE_LIBIDN + idna_init(); +#endif + + if(Curl_resolver_global_init()) { + DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n")); + return CURLE_FAILED_INIT; + } + +#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT) + if(libssh2_init(0)) { + DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + + if(flags & CURL_GLOBAL_ACK_EINTR) + Curl_ack_eintr = 1; + + init_flags = flags; + + return CURLE_OK; +} + +/* + * curl_global_init_mem() globally initializes cURL and also registers the + * user provided callback routines. + */ +CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, + curl_free_callback f, curl_realloc_callback r, + curl_strdup_callback s, curl_calloc_callback c) +{ + CURLcode result = CURLE_OK; + + /* Invalid input, return immediately */ + if(!m || !f || !r || !s || !c) + return CURLE_FAILED_INIT; + + if(initialized) { + /* Already initialized, don't do it again, but bump the variable anyway to + work like curl_global_init() and require the same amount of cleanup + calls. */ + initialized++; + return CURLE_OK; + } + + /* Call the actual init function first */ + result = curl_global_init(flags); + if(!result) { + Curl_cmalloc = m; + Curl_cfree = f; + Curl_cstrdup = s; + Curl_crealloc = r; + Curl_ccalloc = c; + } + + return result; +} + +/** + * curl_global_cleanup() globally cleanups cURL, uses the value of + * "init_flags" to determine what needs to be cleaned up and what doesn't. + */ +void curl_global_cleanup(void) +{ + if(!initialized) + return; + + if(--initialized) + return; + + Curl_global_host_cache_dtor(); + + if(init_flags & CURL_GLOBAL_SSL) + Curl_ssl_cleanup(); + + Curl_resolver_global_cleanup(); + + if(init_flags & CURL_GLOBAL_WIN32) + win32_cleanup(); + + Curl_amiga_cleanup(); + +#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT) + (void)libssh2_exit(); +#endif + + init_flags = 0; +} + +/* + * curl_easy_init() is the external interface to alloc, setup and init an + * easy handle that is returned. If anything goes wrong, NULL is returned. + */ +CURL *curl_easy_init(void) +{ + CURLcode result; + struct SessionHandle *data; + + /* Make sure we inited the global SSL stuff */ + if(!initialized) { + result = curl_global_init(CURL_GLOBAL_DEFAULT); + if(result) { + /* something in the global init failed, return nothing */ + DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); + return NULL; + } + } + + /* We use curl_open() with undefined URL so far */ + result = Curl_open(&data); + if(result) { + DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); + return NULL; + } + + return data; +} + +/* + * curl_easy_setopt() is the external interface for setting options on an + * easy handle. + */ + +//#undef curl_easy_setopt +CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...) +{ + va_list arg; + struct SessionHandle *data = curl; + CURLcode result; + + if(!curl) + return CURLE_BAD_FUNCTION_ARGUMENT; + + va_start(arg, tag); + + result = Curl_setopt(data, tag, arg); + + va_end(arg); + return result; +} + +#ifdef CURLDEBUG + +struct socketmonitor { + struct socketmonitor *next; /* the next node in the list or NULL */ + struct pollfd socket; /* socket info of what to monitor */ +}; + +struct events { + long ms; /* timeout, run the timeout function when reached */ + bool msbump; /* set TRUE when timeout is set by callback */ + int num_sockets; /* number of nodes in the monitor list */ + struct socketmonitor *list; /* list of sockets to monitor */ + int running_handles; /* store the returned number */ +}; + +/* events_timer + * + * Callback that gets called with a new value when the timeout should be + * updated. + */ + +static int events_timer(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp) /* private callback pointer */ +{ + struct events *ev = userp; + (void)multi; + if(timeout_ms == -1) + /* timeout removed */ + timeout_ms = 0; + else if(timeout_ms == 0) + /* timeout is already reached! */ + timeout_ms = 1; /* trigger asap */ + + ev->ms = timeout_ms; + ev->msbump = TRUE; + return 0; +} + + +/* poll2cselect + * + * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones + */ +static int poll2cselect(int pollmask) +{ + int omask=0; + if(pollmask & POLLIN) + omask |= CURL_CSELECT_IN; + if(pollmask & POLLOUT) + omask |= CURL_CSELECT_OUT; + if(pollmask & POLLERR) + omask |= CURL_CSELECT_ERR; + return omask; +} + + +/* socketcb2poll + * + * convert from libcurl' CURL_POLL_* bit definitions to poll()'s + */ +static short socketcb2poll(int pollmask) +{ + short omask=0; + if(pollmask & CURL_POLL_IN) + omask |= POLLIN; + if(pollmask & CURL_POLL_OUT) + omask |= POLLOUT; + return omask; +} + +/* events_socket + * + * Callback that gets called with information about socket activity to + * monitor. + */ +static int events_socket(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp) /* private socket + pointer */ +{ + struct events *ev = userp; + struct socketmonitor *m; + struct socketmonitor *prev=NULL; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) easy; +#endif + (void)socketp; + + m = ev->list; + while(m) { + if(m->socket.fd == s) { + + if(what == CURL_POLL_REMOVE) { + struct socketmonitor *nxt = m->next; + /* remove this node from the list of monitored sockets */ + if(prev) + prev->next = nxt; + else + ev->list = nxt; + free(m); + m = nxt; + infof(easy, "socket cb: socket %d REMOVED\n", s); + } + else { + /* The socket 's' is already being monitored, update the activity + mask. Convert from libcurl bitmask to the poll one. */ + m->socket.events = socketcb2poll(what); + infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s, + what&CURL_POLL_IN?"IN":"", + what&CURL_POLL_OUT?"OUT":""); + } + break; + } + prev = m; + m = m->next; /* move to next node */ + } + if(!m) { + if(what == CURL_POLL_REMOVE) { + /* this happens a bit too often, libcurl fix perhaps? */ + /* fprintf(stderr, + "%s: socket %d asked to be REMOVED but not present!\n", + __func__, s); */ + } + else { + m = malloc(sizeof(struct socketmonitor)); + m->next = ev->list; + m->socket.fd = s; + m->socket.events = socketcb2poll(what); + m->socket.revents = 0; + ev->list = m; + infof(easy, "socket cb: socket %d ADDED as %s%s\n", s, + what&CURL_POLL_IN?"IN":"", + what&CURL_POLL_OUT?"OUT":""); + } + } + + return 0; +} + + +/* + * events_setup() + * + * Do the multi handle setups that only event-based transfers need. + */ +static void events_setup(CURLM *multi, struct events *ev) +{ + /* timer callback */ + curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer); + curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev); + + /* socket callback */ + curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket); + curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev); +} + + +/* wait_or_timeout() + * + * waits for activity on any of the given sockets, or the timeout to trigger. + */ + +static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) +{ + bool done = FALSE; + CURLMcode mcode; + CURLcode result = CURLE_OK; + + while(!done) { + CURLMsg *msg; + struct socketmonitor *m; + struct pollfd *f; + struct pollfd fds[4]; + int numfds=0; + int pollrc; + int i; + struct timeval before; + struct timeval after; + + /* populate the fds[] array */ + for(m = ev->list, f=&fds[0]; m; m = m->next) { + f->fd = m->socket.fd; + f->events = m->socket.events; + f->revents = 0; + /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */ + f++; + numfds++; + } + + /* get the time stamp to use to figure out how long poll takes */ + before = curlx_tvnow(); + + /* wait for activity or timeout */ + pollrc = Curl_poll(fds, numfds, (int)ev->ms); + + after = curlx_tvnow(); + + ev->msbump = FALSE; /* reset here */ + + if(0 == pollrc) { + /* timeout! */ + ev->ms = 0; + /* fprintf(stderr, "call curl_multi_socket_action( TIMEOUT )\n"); */ + mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, + &ev->running_handles); + } + else if(pollrc > 0) { + /* loop over the monitored sockets to see which ones had activity */ + for(i = 0; i< numfds; i++) { + if(fds[i].revents) { + /* socket activity, tell libcurl */ + int act = poll2cselect(fds[i].revents); /* convert */ + infof(multi->easyp, "call curl_multi_socket_action( socket %d )\n", + fds[i].fd); + mcode = curl_multi_socket_action(multi, fds[i].fd, act, + &ev->running_handles); + } + } + + if(!ev->msbump) + /* If nothing updated the timeout, we decrease it by the spent time. + * If it was updated, it has the new timeout time stored already. + */ + ev->ms += curlx_tvdiff(after, before); + + } + else + return CURLE_RECV_ERROR; + + if(mcode) + return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */ + + /* we don't really care about the "msgs_in_queue" value returned in the + second argument */ + msg = curl_multi_info_read(multi, &pollrc); + if(msg) { + result = msg->data.result; + done = TRUE; + } + } + + return result; +} + + +/* easy_events() + * + * Runs a transfer in a blocking manner using the events-based API + */ +static CURLcode easy_events(CURLM *multi) +{ + struct events evs= {2, FALSE, 0, NULL, 0}; + + /* if running event-based, do some further multi inits */ + events_setup(multi, &evs); + + return wait_or_timeout(multi, &evs); +} +#else /* CURLDEBUG */ +/* when not built with debug, this function doesn't exist */ +#define easy_events(x) CURLE_NOT_BUILT_IN +#endif + +static CURLcode easy_transfer(CURLM *multi) +{ + bool done = FALSE; + CURLMcode mcode = CURLM_OK; + CURLcode result = CURLE_OK; + struct timeval before; + int without_fds = 0; /* count number of consecutive returns from + curl_multi_wait() without any filedescriptors */ + + while(!done && !mcode) { + int still_running = 0; + int ret; + + before = curlx_tvnow(); + mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret); + + if(mcode == CURLM_OK) { + if(ret == -1) { + /* poll() failed not on EINTR, indicate a network problem */ + result = CURLE_RECV_ERROR; + break; + } + else if(ret == 0) { + struct timeval after = curlx_tvnow(); + /* If it returns without any filedescriptor instantly, we need to + avoid busy-looping during periods where it has nothing particular + to wait for */ + if(curlx_tvdiff(after, before) <= 10) { + without_fds++; + if(without_fds > 2) { + int sleep_ms = without_fds < 10 ? (1 << (without_fds-1)): 1000; + Curl_wait_ms(sleep_ms); + } + } + else + /* it wasn't "instant", restart counter */ + without_fds = 0; + } + else + /* got file descriptor, restart counter */ + without_fds = 0; + + mcode = curl_multi_perform(multi, &still_running); + } + + /* only read 'still_running' if curl_multi_perform() return OK */ + if((mcode == CURLM_OK) && !still_running) { + int rc; + CURLMsg *msg = curl_multi_info_read(multi, &rc); + if(msg) { + result = msg->data.result; + done = TRUE; + } + } + } + + /* Make sure to return some kind of error if there was a multi problem */ + if(mcode) { + return (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY : + /* The other multi errors should never happen, so return + something suitably generic */ + CURLE_BAD_FUNCTION_ARGUMENT; + } + + return result; +} + + +/* + * easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + * + * CONCEPT: This function creates a multi handle, adds the easy handle to it, + * runs curl_multi_perform() until the transfer is done, then detaches the + * easy handle, destroys the multi handle and returns the easy handle's return + * code. + * + * REALITY: it can't just create and destroy the multi handle that easily. It + * needs to keep it around since if this easy handle is used again by this + * function, the same multi handle must be re-used so that the same pools and + * caches can be used. + * + * DEBUG: if 'events' is set TRUE, this function will use a replacement engine + * instead of curl_multi_perform() and use curl_multi_socket_action(). + */ +static CURLcode easy_perform(struct SessionHandle *data, bool events) +{ + CURLM *multi; + CURLMcode mcode; + CURLcode result = CURLE_OK; + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->multi) { + failf(data, "easy handle already used in multi handle"); + return CURLE_FAILED_INIT; + } + + if(data->multi_easy) + multi = data->multi_easy; + else { + /* this multi handle will only ever have a single easy handled attached + to it, so make it use minimal hashes */ + multi = Curl_multi_handle(1, 3); + if(!multi) + return CURLE_OUT_OF_MEMORY; + data->multi_easy = multi; + } + + /* Copy the MAXCONNECTS option to the multi handle */ + curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); + + mcode = curl_multi_add_handle(multi, data); + if(mcode) { + curl_multi_cleanup(multi); + if(mcode == CURLM_OUT_OF_MEMORY) + return CURLE_OUT_OF_MEMORY; + else + return CURLE_FAILED_INIT; + } + + sigpipe_ignore(data, &pipe_st); + + /* assign this after curl_multi_add_handle() since that function checks for + it and rejects this handle otherwise */ + data->multi = multi; + + /* run the transfer */ + result = events ? easy_events(multi) : easy_transfer(multi); + + /* ignoring the return code isn't nice, but atm we can't really handle + a failure here, room for future improvement! */ + (void)curl_multi_remove_handle(multi, data); + + sigpipe_restore(&pipe_st); + + /* The multi handle is kept alive, owned by the easy handle */ + return result; +} + + +/* + * curl_easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + */ +CURLcode curl_easy_perform(CURL *easy) +{ + return easy_perform(easy, FALSE); +} + +#ifdef CURLDEBUG +/* + * curl_easy_perform_ev() is the external interface that performs a blocking + * transfer using the event-based API internally. + */ +CURLcode curl_easy_perform_ev(CURL *easy) +{ + return easy_perform(easy, TRUE); +} + +#endif + +/* + * curl_easy_cleanup() is the external interface to cleaning/freeing the given + * easy handle. + */ +void curl_easy_cleanup(CURL *curl) +{ + struct SessionHandle *data = (struct SessionHandle *)curl; + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return; + + sigpipe_ignore(data, &pipe_st); + Curl_close(data); + sigpipe_restore(&pipe_st); +} + +/* + * curl_easy_getinfo() is an external interface that allows an app to retrieve + * information from a performed transfer and similar. + */ +//#undef curl_easy_getinfo +CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) +{ + va_list arg; + void *paramp; + CURLcode result; + struct SessionHandle *data = (struct SessionHandle *)curl; + + va_start(arg, info); + paramp = va_arg(arg, void *); + + result = Curl_getinfo(data, info, paramp); + + va_end(arg); + return result; +} + +/* + * curl_easy_duphandle() is an external interface to allow duplication of a + * given input easy handle. The returned handle will be a new working handle + * with all options set exactly as the input source handle. + */ +CURL *curl_easy_duphandle(CURL *incurl) +{ + struct SessionHandle *data=(struct SessionHandle *)incurl; + + struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle)); + if(NULL == outcurl) + goto fail; + + /* + * We setup a few buffers we need. We should probably make them + * get setup on-demand in the code, as that would probably decrease + * the likeliness of us forgetting to init a buffer here in the future. + */ + outcurl->state.headerbuff = malloc(HEADERSIZE); + if(!outcurl->state.headerbuff) + goto fail; + outcurl->state.headersize = HEADERSIZE; + + /* copy all userdefined values */ + if(Curl_dupset(outcurl, data)) + goto fail; + + /* the connection cache is setup on demand */ + outcurl->state.conn_cache = NULL; + + outcurl->state.lastconnect = NULL; + + outcurl->progress.flags = data->progress.flags; + outcurl->progress.callback = data->progress.callback; + + if(data->cookies) { + /* If cookies are enabled in the parent handle, we enable them + in the clone as well! */ + outcurl->cookies = Curl_cookie_init(data, + data->cookies->filename, + outcurl->cookies, + data->set.cookiesession); + if(!outcurl->cookies) + goto fail; + } + + /* duplicate all values in 'change' */ + if(data->change.cookielist) { + outcurl->change.cookielist = + Curl_slist_duplicate(data->change.cookielist); + if(!outcurl->change.cookielist) + goto fail; + } + + if(data->change.url) { + outcurl->change.url = strdup(data->change.url); + if(!outcurl->change.url) + goto fail; + outcurl->change.url_alloc = TRUE; + } + + if(data->change.referer) { + outcurl->change.referer = strdup(data->change.referer); + if(!outcurl->change.referer) + goto fail; + outcurl->change.referer_alloc = TRUE; + } + + /* Clone the resolver handle, if present, for the new handle */ + if(Curl_resolver_duphandle(&outcurl->state.resolver, + data->state.resolver)) + goto fail; + + Curl_convert_setup(outcurl); + + outcurl->magic = CURLEASY_MAGIC_NUMBER; + + /* we reach this point and thus we are OK */ + + return outcurl; + + fail: + + if(outcurl) { + curl_slist_free_all(outcurl->change.cookielist); + outcurl->change.cookielist = NULL; + Curl_safefree(outcurl->state.headerbuff); + Curl_safefree(outcurl->change.url); + Curl_safefree(outcurl->change.referer); + Curl_freeset(outcurl); + free(outcurl); + } + + return NULL; +} + +/* + * curl_easy_reset() is an external interface that allows an app to re- + * initialize a session handle to the default values. + */ +void curl_easy_reset(CURL *curl) +{ + struct SessionHandle *data = (struct SessionHandle *)curl; + + Curl_safefree(data->state.pathbuffer); + + data->state.path = NULL; + + Curl_free_request_state(data); + + /* zero out UserDefined data: */ + Curl_freeset(data); + memset(&data->set, 0, sizeof(struct UserDefined)); + (void)Curl_init_userdefined(&data->set); + + /* zero out Progress data: */ + memset(&data->progress, 0, sizeof(struct Progress)); + + data->progress.flags |= PGRS_HIDE; + data->state.current_speed = -1; /* init to negative == impossible */ +} + +/* + * curl_easy_pause() allows an application to pause or unpause a specific + * transfer and direction. This function sets the full new state for the + * current connection this easy handle operates on. + * + * NOTE: if you have the receiving paused and you call this function to remove + * the pausing, you may get your write callback called at this point. + * + * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h + */ +CURLcode curl_easy_pause(CURL *curl, int action) +{ + struct SessionHandle *data = (struct SessionHandle *)curl; + struct SingleRequest *k = &data->req; + CURLcode result = CURLE_OK; + + /* first switch off both pause bits */ + int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); + + /* set the new desired pause bits */ + newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | + ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); + + /* put it back in the keepon */ + k->keepon = newstate; + + if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) { + /* we have a buffer for sending that we now seem to be able to deliver + since the receive pausing is lifted! */ + + /* get the pointer in local copy since the function may return PAUSE + again and then we'll get a new copy allocted and stored in + the tempwrite variables */ + char *tempwrite = data->state.tempwrite; + + data->state.tempwrite = NULL; + result = Curl_client_chop_write(data->easy_conn, data->state.tempwritetype, + tempwrite, data->state.tempwritesize); + free(tempwrite); + } + + /* if there's no error and we're not pausing both directions, we want + to have this handle checked soon */ + if(!result && + ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != + (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) + Curl_expire(data, 1); /* get this handle going again */ + + return result; +} + + +static CURLcode easy_connection(struct SessionHandle *data, + curl_socket_t *sfd, + struct connectdata **connp) +{ + if(data == NULL) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ + if(!data->set.connect_only) { + failf(data, "CONNECT_ONLY is required!"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + *sfd = Curl_getconnectinfo(data, connp); + + if(*sfd == CURL_SOCKET_BAD) { + failf(data, "Failed to get recent socket"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + return CURLE_OK; +} + +/* + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + * Returns CURLE_OK on success, error code on error. + */ +CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n) +{ + curl_socket_t sfd; + CURLcode result; + ssize_t n1; + struct connectdata *c; + struct SessionHandle *data = (struct SessionHandle *)curl; + + result = easy_connection(data, &sfd, &c); + if(result) + return result; + + *n = 0; + result = Curl_read(c, sfd, buffer, buflen, &n1); + + if(result) + return result; + + *n = (size_t)n1; + + return CURLE_OK; +} + +/* + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen, + size_t *n) +{ + curl_socket_t sfd; + CURLcode result; + ssize_t n1; + struct connectdata *c = NULL; + struct SessionHandle *data = (struct SessionHandle *)curl; + + result = easy_connection(data, &sfd, &c); + if(result) + return result; + + *n = 0; + result = Curl_write(c, sfd, buffer, buflen, &n1); + + if(n1 == -1) + return CURLE_SEND_ERROR; + + /* detect EAGAIN */ + if(!result && !n1) + return CURLE_AGAIN; + + *n = (size_t)n1; + + return result; +} diff --git a/libcurl/src/lib/easyif.h b/libcurl/src/lib/easyif.h new file mode 100644 index 0000000..043ff43 --- /dev/null +++ b/libcurl/src/lib/easyif.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_EASYIF_H +#define HEADER_CURL_EASYIF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by easy.c + */ +#ifdef CURLDEBUG +CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy); +#endif + +#endif /* HEADER_CURL_EASYIF_H */ + diff --git a/libcurl/src/lib/escape.c b/libcurl/src/lib/escape.c new file mode 100644 index 0000000..417a91a --- /dev/null +++ b/libcurl/src/lib/escape.c @@ -0,0 +1,231 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "warnless.h" +#include "non-ascii.h" +#include "escape.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Portable character check (remember EBCDIC). Do not use isalnum() because + its behavior is altered by the current locale. + See http://tools.ietf.org/html/rfc3986#section-2.3 +*/ +static bool Curl_isunreserved(unsigned char in) +{ + switch (in) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '-': case '.': case '_': case '~': + return TRUE; + default: + break; + } + return FALSE; +} + +/* for ABI-compatibility with previous versions */ +char *curl_escape(const char *string, int inlength) +{ + return curl_easy_escape(NULL, string, inlength); +} + +/* for ABI-compatibility with previous versions */ +char *curl_unescape(const char *string, int length) +{ + return curl_easy_unescape(NULL, string, length, NULL); +} + +char *curl_easy_escape(CURL *handle, const char *string, int inlength) +{ + size_t alloc = (inlength?(size_t)inlength:strlen(string))+1; + char *ns; + char *testing_ptr = NULL; + unsigned char in; /* we need to treat the characters unsigned */ + size_t newlen = alloc; + size_t strindex=0; + size_t length; + CURLcode result; + + ns = malloc(alloc); + if(!ns) + return NULL; + + length = alloc-1; + while(length--) { + in = *string; + + if(Curl_isunreserved(in)) + /* just copy this */ + ns[strindex++]=in; + else { + /* encode it */ + newlen += 2; /* the size grows with two, since this'll become a %XX */ + if(newlen > alloc) { + alloc *= 2; + testing_ptr = realloc(ns, alloc); + if(!testing_ptr) { + free( ns ); + return NULL; + } + else { + ns = testing_ptr; + } + } + + result = Curl_convert_to_network(handle, &in, 1); + if(result) { + /* Curl_convert_to_network calls failf if unsuccessful */ + free(ns); + return NULL; + } + + snprintf(&ns[strindex], 4, "%%%02X", in); + + strindex+=3; + } + string++; + } + ns[strindex]=0; /* terminate it */ + return ns; +} + +/* + * Curl_urldecode() URL decodes the given string. + * + * Optionally detects control characters (byte codes lower than 32) in the + * data and rejects such data. + * + * Returns a pointer to a malloced string in *ostring with length given in + * *olen. If length == 0, the length is assumed to be strlen(string). + * + */ +CURL_STATIC CURLcode Curl_urldecode(struct SessionHandle *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_ctrl) +{ + size_t alloc = (length?length:strlen(string))+1; + char *ns = malloc(alloc); + unsigned char in; + size_t strindex=0; + unsigned long hex; + CURLcode result; + + if(!ns) + return CURLE_OUT_OF_MEMORY; + + while(--alloc > 0) { + in = *string; + if(('%' == in) && (alloc > 2) && + ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { + /* this is two hexadecimal digits following a '%' */ + char hexstr[3]; + char *ptr; + hexstr[0] = string[1]; + hexstr[1] = string[2]; + hexstr[2] = 0; + + hex = strtoul(hexstr, &ptr, 16); + + in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */ + + result = Curl_convert_from_network(data, &in, 1); + if(result) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(ns); + return result; + } + + string+=2; + alloc-=2; + } + + if(reject_ctrl && (in < 0x20)) { + free(ns); + return CURLE_URL_MALFORMAT; + } + + ns[strindex++] = in; + string++; + } + ns[strindex]=0; /* terminate it */ + + if(olen) + /* store output size */ + *olen = strindex; + + /* store output string */ + *ostring = ns; + + return CURLE_OK; +} + +/* + * Unescapes the given URL escaped string of given length. Returns a + * pointer to a malloced string with length given in *olen. + * If length == 0, the length is assumed to be strlen(string). + * If olen == NULL, no output length is stored. + */ +char *curl_easy_unescape(CURL *handle, const char *string, int length, + int *olen) +{ + char *str = NULL; + size_t inputlen = length; + size_t outputlen; + CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen, + FALSE); + if(res) + return NULL; + if(olen) + *olen = curlx_uztosi(outputlen); + return str; +} + +/* For operating systems/environments that use different malloc/free + systems for the app and for this library, we provide a free that uses + the library's memory system */ +void curl_free(void *p) +{ + free(p); +} diff --git a/libcurl/src/lib/escape.h b/libcurl/src/lib/escape.h new file mode 100644 index 0000000..b640c17 --- /dev/null +++ b/libcurl/src/lib/escape.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_ESCAPE_H +#define HEADER_CURL_ESCAPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ + +CURL_STATIC CURLcode Curl_urldecode(struct SessionHandle *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_crlf); + +#endif /* HEADER_CURL_ESCAPE_H */ + diff --git a/libcurl/src/lib/file.c b/libcurl/src/lib/file.c new file mode 100644 index 0000000..324d4e2 --- /dev/null +++ b/libcurl/src/lib/file.c @@ -0,0 +1,588 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FILE + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include "strtoofft.h" +#include "urldata.h" +#include +#include "progress.h" +#include "sendf.h" +#include "escape.h" +#include "file.h" +#include "speedcheck.h" +#include "getinfo.h" +#include "transfer.h" +#include "url.h" +#include "parsedate.h" /* for the week day and month names */ +#include "warnless.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \ + defined(__SYMBIAN32__) +#define DOS_FILESYSTEM 1 +#endif + +#ifdef OPEN_NEEDS_ARG3 +# define open_readonly(p,f) open((p),(f),(0)) +#else +# define open_readonly(p,f) open((p),(f)) +#endif + +/* + * Forward declarations. + */ + +static CURLcode file_do(struct connectdata *, bool *done); +static CURLcode file_done(struct connectdata *conn, + CURLcode status, bool premature); +static CURLcode file_connect(struct connectdata *conn, bool *done); +static CURLcode file_disconnect(struct connectdata *conn, + bool dead_connection); +static CURLcode file_setup_connection(struct connectdata *conn); + +/* + * FILE scheme handler. + */ + +const struct Curl_handler Curl_handler_file = { + "FILE", /* scheme */ + file_setup_connection, /* setup_connection */ + file_do, /* do_it */ + file_done, /* done */ + ZERO_NULL, /* do_more */ + file_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + file_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + 0, /* defport */ + CURLPROTO_FILE, /* protocol */ + PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */ +}; + + +static CURLcode file_setup_connection(struct connectdata *conn) +{ + /* allocate the FILE specific struct */ + conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO)); + if(!conn->data->req.protop) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + + /* + Check if this is a range download, and if so, set the internal variables + properly. This code is copied from the FTP implementation and might as + well be factored out. + */ +static CURLcode file_range(struct connectdata *conn) +{ + curl_off_t from, to; + curl_off_t totalsize=-1; + char *ptr; + char *ptr2; + struct SessionHandle *data = conn->data; + + if(data->state.use_range && data->state.range) { + from=curlx_strtoofft(data->state.range, &ptr, 0); + while(*ptr && (ISSPACE(*ptr) || (*ptr=='-'))) + ptr++; + to=curlx_strtoofft(ptr, &ptr2, 0); + if(ptr == ptr2) { + /* we didn't get any digit */ + to=-1; + } + if((-1 == to) && (from>=0)) { + /* X - */ + data->state.resume_from = from; + DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n", + from)); + } + else if(from < 0) { + /* -Y */ + data->req.maxdownload = -from; + data->state.resume_from = from; + DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n", + -from)); + } + else { + /* X-Y */ + totalsize = to-from; + data->req.maxdownload = totalsize+1; /* include last byte */ + data->state.resume_from = from; + DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T + " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n", + from, data->req.maxdownload)); + } + DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T + " to %" CURL_FORMAT_CURL_OFF_T ", totally %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + from, to, data->req.maxdownload)); + } + else + data->req.maxdownload = -1; + return CURLE_OK; +} + +/* + * file_connect() gets called from Curl_protocol_connect() to allow us to + * do protocol-specific actions at connect-time. We emulate a + * connect-then-transfer protocol and "connect" to the file here + */ +static CURLcode file_connect(struct connectdata *conn, bool *done) +{ + struct SessionHandle *data = conn->data; + char *real_path; + struct FILEPROTO *file = data->req.protop; + int fd; +#ifdef DOS_FILESYSTEM + int i; + char *actual_path; +#endif + int real_path_len; + + real_path = curl_easy_unescape(data, data->state.path, 0, &real_path_len); + if(!real_path) + return CURLE_OUT_OF_MEMORY; + +#ifdef DOS_FILESYSTEM + /* If the first character is a slash, and there's + something that looks like a drive at the beginning of + the path, skip the slash. If we remove the initial + slash in all cases, paths without drive letters end up + relative to the current directory which isn't how + browsers work. + + Some browsers accept | instead of : as the drive letter + separator, so we do too. + + On other platforms, we need the slash to indicate an + absolute pathname. On Windows, absolute paths start + with a drive letter. + */ + actual_path = real_path; + if((actual_path[0] == '/') && + actual_path[1] && + (actual_path[2] == ':' || actual_path[2] == '|')) { + actual_path[2] = ':'; + actual_path++; + real_path_len--; + } + + /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */ + for(i=0; i < real_path_len; ++i) + if(actual_path[i] == '/') + actual_path[i] = '\\'; + else if(!actual_path[i]) /* binary zero */ + return CURLE_URL_MALFORMAT; + + fd = open_readonly(actual_path, O_RDONLY|O_BINARY); + file->path = actual_path; +#else + if(memchr(real_path, 0, real_path_len)) + /* binary zeroes indicate foul play */ + return CURLE_URL_MALFORMAT; + + fd = open_readonly(real_path, O_RDONLY); + file->path = real_path; +#endif + file->freepath = real_path; /* free this when done */ + + file->fd = fd; + if(!data->set.upload && (fd == -1)) { + failf(data, "Couldn't open file %s", data->state.path); + file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); + return CURLE_FILE_COULDNT_READ_FILE; + } + *done = TRUE; + + return CURLE_OK; +} + +static CURLcode file_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct FILEPROTO *file = conn->data->req.protop; + (void)status; /* not used */ + (void)premature; /* not used */ + + if(file) { + Curl_safefree(file->freepath); + file->path = NULL; + if(file->fd != -1) + close(file->fd); + file->fd = -1; + } + + return CURLE_OK; +} + +static CURLcode file_disconnect(struct connectdata *conn, + bool dead_connection) +{ + struct FILEPROTO *file = conn->data->req.protop; + (void)dead_connection; /* not used */ + + if(file) { + Curl_safefree(file->freepath); + file->path = NULL; + if(file->fd != -1) + close(file->fd); + file->fd = -1; + } + + return CURLE_OK; +} + +#ifdef DOS_FILESYSTEM +#define DIRSEP '\\' +#else +#define DIRSEP '/' +#endif + +static CURLcode file_upload(struct connectdata *conn) +{ + struct FILEPROTO *file = conn->data->req.protop; + const char *dir = strchr(file->path, DIRSEP); + int fd; + int mode; + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + char *buf = data->state.buffer; + size_t nread; + size_t nwrite; + curl_off_t bytecount = 0; + struct timeval now = Curl_tvnow(); + struct_stat file_stat; + const char* buf2; + + /* + * Since FILE: doesn't do the full init, we need to provide some extra + * assignments here. + */ + conn->fread_func = data->set.fread_func; + conn->fread_in = data->set.in; + conn->data->req.upload_fromhere = buf; + + if(!dir) + return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ + + if(!dir[1]) + return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ + +#ifdef O_BINARY +#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY +#else +#define MODE_DEFAULT O_WRONLY|O_CREAT +#endif + + if(data->state.resume_from) + mode = MODE_DEFAULT|O_APPEND; + else + mode = MODE_DEFAULT|O_TRUNC; + + fd = open(file->path, mode, conn->data->set.new_file_perms); + if(fd < 0) { + failf(data, "Can't open %s for writing", file->path); + return CURLE_WRITE_ERROR; + } + + if(-1 != data->state.infilesize) + /* known size of data to "upload" */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* treat the negative resume offset value as the case of "-" */ + if(data->state.resume_from < 0) { + if(fstat(fd, &file_stat)) { + close(fd); + failf(data, "Can't get the size of %s", file->path); + return CURLE_WRITE_ERROR; + } + else + data->state.resume_from = (curl_off_t)file_stat.st_size; + } + + while(!result) { + int readcount; + result = Curl_fillreadbuffer(conn, BUFSIZE, &readcount); + if(result) + break; + + if(readcount <= 0) /* fix questionable compare error. curlvms */ + break; + + nread = (size_t)readcount; + + /*skip bytes before resume point*/ + if(data->state.resume_from) { + if((curl_off_t)nread <= data->state.resume_from ) { + data->state.resume_from -= nread; + nread = 0; + buf2 = buf; + } + else { + buf2 = buf + data->state.resume_from; + nread -= (size_t)data->state.resume_from; + data->state.resume_from = 0; + } + } + else + buf2 = buf; + + /* write the data to the target */ + nwrite = write(fd, buf2, nread); + if(nwrite != nread) { + result = CURLE_SEND_ERROR; + break; + } + + bytecount += nread; + + Curl_pgrsSetUploadCounter(data, bytecount); + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, now); + } + if(!result && Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + close(fd); + + return result; +} + +/* + * file_do() is the protocol-specific function for the do-phase, separated + * from the connect-phase above. Other protocols merely setup the transfer in + * the do-phase, to have it done in the main transfer loop but since some + * platforms we support don't allow select()ing etc on file handles (as + * opposed to sockets) we instead perform the whole do-operation in this + * function. + */ +static CURLcode file_do(struct connectdata *conn, bool *done) +{ + /* This implementation ignores the host name in conformance with + RFC 1738. Only local files (reachable via the standard file system) + are supported. This means that files on remotely mounted directories + (via NFS, Samba, NT sharing) can be accessed through a file:// URL + */ + CURLcode result = CURLE_OK; + struct_stat statbuf; /* struct_stat instead of struct stat just to allow the + Windows version to have a different struct without + having to redefine the simple word 'stat' */ + curl_off_t expected_size=0; + bool fstated=FALSE; + ssize_t nread; + struct SessionHandle *data = conn->data; + char *buf = data->state.buffer; + curl_off_t bytecount = 0; + int fd; + struct timeval now = Curl_tvnow(); + struct FILEPROTO *file; + + *done = TRUE; /* unconditionally */ + + Curl_initinfo(data); + Curl_pgrsStartNow(data); + + if(data->set.upload) + return file_upload(conn); + + file = conn->data->req.protop; + + /* get the fd from the connection phase */ + fd = file->fd; + + /* VMS: This only works reliable for STREAMLF files */ + if(-1 != fstat(fd, &statbuf)) { + /* we could stat it, then read out the size */ + expected_size = statbuf.st_size; + /* and store the modification time */ + data->info.filetime = (long)statbuf.st_mtime; + fstated = TRUE; + } + + if(fstated && !data->state.range && data->set.timecondition) { + if(!Curl_meets_timecondition(data, (time_t)data->info.filetime)) { + *done = TRUE; + return CURLE_OK; + } + } + + /* If we have selected NOBODY and HEADER, it means that we only want file + information. Which for FILE can't be much more than the file size and + date. */ + if(data->set.opt_no_body && data->set.include_header && fstated) { + snprintf(buf, sizeof(data->state.buffer), + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); + if(result) + return result; + + result = Curl_client_write(conn, CLIENTWRITE_BOTH, + (char *)"Accept-ranges: bytes\r\n", 0); + if(result) + return result; + + if(fstated) { + time_t filetime = (time_t)statbuf.st_mtime; + struct tm buffer; + const struct tm *tm = &buffer; + result = Curl_gmtime(filetime, &buffer); + if(result) + return result; + + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + snprintf(buf, BUFSIZE-1, + "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); + } + /* if we fstat()ed the file, set the file size to make it available post- + transfer */ + if(fstated) + Curl_pgrsSetDownloadSize(data, expected_size); + return result; + } + + /* Check whether file range has been specified */ + file_range(conn); + + /* Adjust the start offset in case we want to get the N last bytes + * of the stream iff the filesize could be determined */ + if(data->state.resume_from < 0) { + if(!fstated) { + failf(data, "Can't get the size of file."); + return CURLE_READ_ERROR; + } + else + data->state.resume_from += (curl_off_t)statbuf.st_size; + } + + if(data->state.resume_from <= expected_size) + expected_size -= data->state.resume_from; + else { + failf(data, "failed to resume file:// transfer"); + return CURLE_BAD_DOWNLOAD_RESUME; + } + + /* A high water mark has been specified so we obey... */ + if(data->req.maxdownload > 0) + expected_size = data->req.maxdownload; + + if(fstated && (expected_size == 0)) + return CURLE_OK; + + /* The following is a shortcut implementation of file reading + this is both more efficient than the former call to download() and + it avoids problems with select() and recv() on file descriptors + in Winsock */ + if(fstated) + Curl_pgrsSetDownloadSize(data, expected_size); + + if(data->state.resume_from) { + if(data->state.resume_from != + lseek(fd, data->state.resume_from, SEEK_SET)) + return CURLE_BAD_DOWNLOAD_RESUME; + } + + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + + while(!result) { + /* Don't fill a whole buffer if we want less than all data */ + size_t bytestoread = + (expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ? + curlx_sotouz(expected_size) : BUFSIZE - 1; + + nread = read(fd, buf, bytestoread); + + if(nread > 0) + buf[nread] = 0; + + if(nread <= 0 || expected_size == 0) + break; + + bytecount += nread; + expected_size -= nread; + + result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); + if(result) + return result; + + Curl_pgrsSetDownloadCounter(data, bytecount); + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, now); + } + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + return result; +} + +#endif diff --git a/libcurl/src/lib/file.h b/libcurl/src/lib/file.h new file mode 100644 index 0000000..997474b --- /dev/null +++ b/libcurl/src/lib/file.h @@ -0,0 +1,41 @@ +#ifndef HEADER_CURL_FILE_H +#define HEADER_CURL_FILE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/**************************************************************************** + * FILE unique setup + ***************************************************************************/ +struct FILEPROTO { + char *path; /* the path we operate on */ + char *freepath; /* pointer to the allocated block we must free, this might + differ from the 'path' pointer */ + int fd; /* open file descriptor to read from! */ +}; + +#ifndef CURL_DISABLE_FILE +extern const struct Curl_handler Curl_handler_file; +#endif + +#endif /* HEADER_CURL_FILE_H */ + diff --git a/libcurl/src/lib/fileinfo.c b/libcurl/src/lib/fileinfo.c new file mode 100644 index 0000000..68a2e9c --- /dev/null +++ b/libcurl/src/lib/fileinfo.c @@ -0,0 +1,50 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "strdup.h" +#include "fileinfo.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +CURL_STATIC struct curl_fileinfo *Curl_fileinfo_alloc(void) +{ + struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo)); + if(!tmp) + return NULL; + memset(tmp, 0, sizeof(struct curl_fileinfo)); + return tmp; +} + +CURL_STATIC void Curl_fileinfo_dtor(void *user, void *element) +{ + struct curl_fileinfo *finfo = element; + (void) user; + if(!finfo) + return; + + Curl_safefree(finfo->b_data); + + free(finfo); +} diff --git a/libcurl/src/lib/fileinfo.h b/libcurl/src/lib/fileinfo.h new file mode 100644 index 0000000..7e73fad --- /dev/null +++ b/libcurl/src/lib/fileinfo.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_FILEINFO_H +#define HEADER_CURL_FILEINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +CURL_STATIC struct curl_fileinfo *Curl_fileinfo_alloc(void); + +CURL_STATIC void Curl_fileinfo_dtor(void *, void *); + +CURL_STATIC struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src); + +#endif /* HEADER_CURL_FILEINFO_H */ diff --git a/libcurl/src/lib/formdata.c b/libcurl/src/lib/formdata.c new file mode 100644 index 0000000..3e97830 --- /dev/null +++ b/libcurl/src/lib/formdata.c @@ -0,0 +1,1551 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifndef CURL_DISABLE_HTTP + +#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) +#include +#endif + +#include "urldata.h" /* for struct SessionHandle */ +#include "formdata.h" +#include "vtls/vtls.h" +#include "strequal.h" +#include "sendf.h" +#include "strdup.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef HAVE_BASENAME +static char *Curl_basename(char *path); +#define basename(x) Curl_basename((x)) +#endif + +static size_t readfromfile(struct Form *form, char *buffer, size_t size); +static char *formboundary(struct SessionHandle *data); + +/* What kind of Content-Type to use on un-specified files with unrecognized + extensions. */ +#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream" + +#define FORM_FILE_SEPARATOR ',' +#define FORM_TYPE_SEPARATOR ';' + +/*************************************************************************** + * + * AddHttpPost() + * + * Adds a HttpPost structure to the list, if parent_post is given becomes + * a subpost of parent_post instead of a direct list element. + * + * Returns newly allocated HttpPost on success and NULL if malloc failed. + * + ***************************************************************************/ +static struct curl_httppost * +AddHttpPost(char *name, size_t namelength, + char *value, size_t contentslength, + char *buffer, size_t bufferlength, + char *contenttype, + long flags, + struct curl_slist* contentHeader, + char *showfilename, char *userp, + struct curl_httppost *parent_post, + struct curl_httppost **httppost, + struct curl_httppost **last_post) +{ + struct curl_httppost *post; + post = calloc(1, sizeof(struct curl_httppost)); + if(post) { + post->name = name; + post->namelength = (long)(name?(namelength?namelength:strlen(name)):0); + post->contents = value; + post->contentslength = (long)contentslength; + post->buffer = buffer; + post->bufferlength = (long)bufferlength; + post->contenttype = contenttype; + post->contentheader = contentHeader; + post->showfilename = showfilename; + post->userp = userp, + post->flags = flags; + } + else + return NULL; + + if(parent_post) { + /* now, point our 'more' to the original 'more' */ + post->more = parent_post->more; + + /* then move the original 'more' to point to ourselves */ + parent_post->more = post; + } + else { + /* make the previous point to this */ + if(*last_post) + (*last_post)->next = post; + else + (*httppost) = post; + + (*last_post) = post; + } + return post; +} + +/*************************************************************************** + * + * AddFormInfo() + * + * Adds a FormInfo structure to the list presented by parent_form_info. + * + * Returns newly allocated FormInfo on success and NULL if malloc failed/ + * parent_form_info is NULL. + * + ***************************************************************************/ +static FormInfo * AddFormInfo(char *value, + char *contenttype, + FormInfo *parent_form_info) +{ + FormInfo *form_info; + form_info = calloc(1, sizeof(struct FormInfo)); + if(form_info) { + if(value) + form_info->value = value; + if(contenttype) + form_info->contenttype = contenttype; + form_info->flags = HTTPPOST_FILENAME; + } + else + return NULL; + + if(parent_form_info) { + /* now, point our 'more' to the original 'more' */ + form_info->more = parent_form_info->more; + + /* then move the original 'more' to point to ourselves */ + parent_form_info->more = form_info; + } + + return form_info; +} + +/*************************************************************************** + * + * ContentTypeForFilename() + * + * Provides content type for filename if one of the known types (else + * (either the prevtype or the default is returned). + * + * Returns some valid contenttype for filename. + * + ***************************************************************************/ +static const char *ContentTypeForFilename(const char *filename, + const char *prevtype) +{ + const char *contenttype = NULL; + unsigned int i; + /* + * No type was specified, we scan through a few well-known + * extensions and pick the first we match! + */ + struct ContentType { + const char *extension; + const char *type; + }; + static const struct ContentType ctts[]={ + {".gif", "image/gif"}, + {".jpg", "image/jpeg"}, + {".jpeg", "image/jpeg"}, + {".txt", "text/plain"}, + {".html", "text/html"}, + {".xml", "application/xml"} + }; + + if(prevtype) + /* default to the previously set/used! */ + contenttype = prevtype; + else + contenttype = HTTPPOST_CONTENTTYPE_DEFAULT; + + if(filename) { /* in case a NULL was passed in */ + for(i=0; i= strlen(ctts[i].extension)) { + if(strequal(filename + + strlen(filename) - strlen(ctts[i].extension), + ctts[i].extension)) { + contenttype = ctts[i].type; + break; + } + } + } + } + /* we have a contenttype by now */ + return contenttype; +} + +/*************************************************************************** + * + * FormAdd() + * + * Stores a formpost parameter and builds the appropriate linked list. + * + * Has two principal functionalities: using files and byte arrays as + * post parts. Byte arrays are either copied or just the pointer is stored + * (as the user requests) while for files only the filename and not the + * content is stored. + * + * While you may have only one byte array for each name, multiple filenames + * are allowed (and because of this feature CURLFORM_END is needed after + * using CURLFORM_FILE). + * + * Examples: + * + * Simple name/value pair with copied contents: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_COPYCONTENTS, "value", CURLFORM_END); + * + * name/value pair where only the content pointer is remembered: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END); + * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used) + * + * storing a filename (CONTENTTYPE is optional!): + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text", + * CURLFORM_END); + * + * storing multiple filenames: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ + +static +CURLFORMcode FormAdd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + va_list params) +{ + FormInfo *first_form, *current_form, *form = NULL; + CURLFORMcode return_value = CURL_FORMADD_OK; + const char *prevtype = NULL; + struct curl_httppost *post = NULL; + CURLformoption option; + struct curl_forms *forms = NULL; + char *array_value=NULL; /* value read from an array */ + + /* This is a state variable, that if TRUE means that we're parsing an + array that we got passed to us. If FALSE we're parsing the input + va_list arguments. */ + bool array_state = FALSE; + + /* + * We need to allocate the first struct to fill in. + */ + first_form = calloc(1, sizeof(struct FormInfo)); + if(!first_form) + return CURL_FORMADD_MEMORY; + + current_form = first_form; + + /* + * Loop through all the options set. Break if we have an error to report. + */ + while(return_value == CURL_FORMADD_OK) { + + /* first see if we have more parts of the array param */ + if(array_state && forms) { + /* get the upcoming option from the given array */ + option = forms->option; + array_value = (char *)forms->value; + + forms++; /* advance this to next entry */ + if(CURLFORM_END == option) { + /* end of array state */ + array_state = FALSE; + continue; + } + } + else { + /* This is not array-state, get next option */ + option = va_arg(params, CURLformoption); + if(CURLFORM_END == option) + break; + } + + switch (option) { + case CURLFORM_ARRAY: + if(array_state) + /* we don't support an array from within an array */ + return_value = CURL_FORMADD_ILLEGAL_ARRAY; + else { + forms = va_arg(params, struct curl_forms *); + if(forms) + array_state = TRUE; + else + return_value = CURL_FORMADD_NULL; + } + break; + + /* + * Set the Name property. + */ + case CURLFORM_PTRNAME: +#ifdef CURL_DOES_CONVERSIONS + /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy + * the data in all cases so that we'll have safe memory for the eventual + * conversion. + */ +#else + current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ +#endif + case CURLFORM_COPYNAME: + if(current_form->name) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *name = array_state? + array_value:va_arg(params, char *); + if(name) + current_form->name = name; /* store for the moment */ + else + return_value = CURL_FORMADD_NULL; + } + break; + case CURLFORM_NAMELENGTH: + if(current_form->namelength) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->namelength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + /* + * Set the contents property. + */ + case CURLFORM_PTRCONTENTS: + current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */ + case CURLFORM_COPYCONTENTS: + if(current_form->value) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *value = + array_state?array_value:va_arg(params, char *); + if(value) + current_form->value = value; /* store for the moment */ + else + return_value = CURL_FORMADD_NULL; + } + break; + case CURLFORM_CONTENTSLENGTH: + if(current_form->contentslength) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->contentslength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + /* Get contents from a given file name */ + case CURLFORM_FILECONTENT: + if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE)) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + const char *filename = array_state? + array_value:va_arg(params, char *); + if(filename) { + current_form->value = strdup(filename); + if(!current_form->value) + return_value = CURL_FORMADD_MEMORY; + else { + current_form->flags |= HTTPPOST_READFILE; + current_form->value_alloc = TRUE; + } + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + /* We upload a file */ + case CURLFORM_FILE: + { + const char *filename = array_state?array_value: + va_arg(params, char *); + + if(current_form->value) { + if(current_form->flags & HTTPPOST_FILENAME) { + if(filename) { + char *fname = strdup(filename); + if(!fname) + return_value = CURL_FORMADD_MEMORY; + else { + form = AddFormInfo(fname, NULL, current_form); + if(!form) { + free(fname); + return_value = CURL_FORMADD_MEMORY; + } + else { + form->value_alloc = TRUE; + current_form = form; + form = NULL; + } + } + } + else + return_value = CURL_FORMADD_NULL; + } + else + return_value = CURL_FORMADD_OPTION_TWICE; + } + else { + if(filename) { + current_form->value = strdup(filename); + if(!current_form->value) + return_value = CURL_FORMADD_MEMORY; + else { + current_form->flags |= HTTPPOST_FILENAME; + current_form->value_alloc = TRUE; + } + } + else + return_value = CURL_FORMADD_NULL; + } + break; + } + + case CURLFORM_BUFFERPTR: + current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER; + if(current_form->buffer) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *buffer = + array_state?array_value:va_arg(params, char *); + if(buffer) { + current_form->buffer = buffer; /* store for the moment */ + current_form->value = buffer; /* make it non-NULL to be accepted + as fine */ + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + case CURLFORM_BUFFERLENGTH: + if(current_form->bufferlength) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->bufferlength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + case CURLFORM_STREAM: + current_form->flags |= HTTPPOST_CALLBACK; + if(current_form->userp) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *userp = + array_state?array_value:va_arg(params, char *); + if(userp) { + current_form->userp = userp; + current_form->value = userp; /* this isn't strictly true but we + derive a value from this later on + and we need this non-NULL to be + accepted as a fine form part */ + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + case CURLFORM_CONTENTTYPE: + { + const char *contenttype = + array_state?array_value:va_arg(params, char *); + if(current_form->contenttype) { + if(current_form->flags & HTTPPOST_FILENAME) { + if(contenttype) { + char *type = strdup(contenttype); + if(!type) + return_value = CURL_FORMADD_MEMORY; + else { + form = AddFormInfo(NULL, type, current_form); + if(!form) { + free(type); + return_value = CURL_FORMADD_MEMORY; + } + else { + form->contenttype_alloc = TRUE; + current_form = form; + form = NULL; + } + } + } + else + return_value = CURL_FORMADD_NULL; + } + else + return_value = CURL_FORMADD_OPTION_TWICE; + } + else { + if(contenttype) { + current_form->contenttype = strdup(contenttype); + if(!current_form->contenttype) + return_value = CURL_FORMADD_MEMORY; + else + current_form->contenttype_alloc = TRUE; + } + else + return_value = CURL_FORMADD_NULL; + } + break; + } + case CURLFORM_CONTENTHEADER: + { + /* this "cast increases required alignment of target type" but + we consider it OK anyway */ + struct curl_slist* list = array_state? + (struct curl_slist*)array_value: + va_arg(params, struct curl_slist*); + + if(current_form->contentheader) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->contentheader = list; + + break; + } + case CURLFORM_FILENAME: + case CURLFORM_BUFFER: + { + const char *filename = array_state?array_value: + va_arg(params, char *); + if(current_form->showfilename) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + current_form->showfilename = strdup(filename); + if(!current_form->showfilename) + return_value = CURL_FORMADD_MEMORY; + else + current_form->showfilename_alloc = TRUE; + } + break; + } + default: + return_value = CURL_FORMADD_UNKNOWN_OPTION; + break; + } + } + + if(CURL_FORMADD_OK != return_value) { + /* On error, free allocated fields for all nodes of the FormInfo linked + list without deallocating nodes. List nodes are deallocated later on */ + FormInfo *ptr; + for(ptr = first_form; ptr != NULL; ptr = ptr->more) { + if(ptr->name_alloc) { + Curl_safefree(ptr->name); + ptr->name_alloc = FALSE; + } + if(ptr->value_alloc) { + Curl_safefree(ptr->value); + ptr->value_alloc = FALSE; + } + if(ptr->contenttype_alloc) { + Curl_safefree(ptr->contenttype); + ptr->contenttype_alloc = FALSE; + } + if(ptr->showfilename_alloc) { + Curl_safefree(ptr->showfilename); + ptr->showfilename_alloc = FALSE; + } + } + } + + if(CURL_FORMADD_OK == return_value) { + /* go through the list, check for completeness and if everything is + * alright add the HttpPost item otherwise set return_value accordingly */ + + post = NULL; + for(form = first_form; + form != NULL; + form = form->more) { + if(((!form->name || !form->value) && !post) || + ( (form->contentslength) && + (form->flags & HTTPPOST_FILENAME) ) || + ( (form->flags & HTTPPOST_FILENAME) && + (form->flags & HTTPPOST_PTRCONTENTS) ) || + + ( (!form->buffer) && + (form->flags & HTTPPOST_BUFFER) && + (form->flags & HTTPPOST_PTRBUFFER) ) || + + ( (form->flags & HTTPPOST_READFILE) && + (form->flags & HTTPPOST_PTRCONTENTS) ) + ) { + return_value = CURL_FORMADD_INCOMPLETE; + break; + } + else { + if(((form->flags & HTTPPOST_FILENAME) || + (form->flags & HTTPPOST_BUFFER)) && + !form->contenttype ) { + char *f = form->flags & HTTPPOST_BUFFER? + form->showfilename : form->value; + + /* our contenttype is missing */ + form->contenttype = strdup(ContentTypeForFilename(f, prevtype)); + if(!form->contenttype) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->contenttype_alloc = TRUE; + } + if(!(form->flags & HTTPPOST_PTRNAME) && + (form == first_form) ) { + /* Note that there's small risk that form->name is NULL here if the + app passed in a bad combo, so we better check for that first. */ + if(form->name) { + /* copy name (without strdup; possibly contains null characters) */ + form->name = Curl_memdup(form->name, form->namelength? + form->namelength: + strlen(form->name)+1); + } + if(!form->name) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->name_alloc = TRUE; + } + if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | + HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | + HTTPPOST_CALLBACK)) && form->value) { + /* copy value (without strdup; possibly contains null characters) */ + form->value = Curl_memdup(form->value, form->contentslength? + form->contentslength: + strlen(form->value)+1); + if(!form->value) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->value_alloc = TRUE; + } + post = AddHttpPost(form->name, form->namelength, + form->value, form->contentslength, + form->buffer, form->bufferlength, + form->contenttype, form->flags, + form->contentheader, form->showfilename, + form->userp, + post, httppost, + last_post); + + if(!post) { + return_value = CURL_FORMADD_MEMORY; + break; + } + + if(form->contenttype) + prevtype = form->contenttype; + } + } + if(CURL_FORMADD_OK != return_value) { + /* On error, free allocated fields for nodes of the FormInfo linked + list which are not already owned by the httppost linked list + without deallocating nodes. List nodes are deallocated later on */ + FormInfo *ptr; + for(ptr = form; ptr != NULL; ptr = ptr->more) { + if(ptr->name_alloc) { + Curl_safefree(ptr->name); + ptr->name_alloc = FALSE; + } + if(ptr->value_alloc) { + Curl_safefree(ptr->value); + ptr->value_alloc = FALSE; + } + if(ptr->contenttype_alloc) { + Curl_safefree(ptr->contenttype); + ptr->contenttype_alloc = FALSE; + } + if(ptr->showfilename_alloc) { + Curl_safefree(ptr->showfilename); + ptr->showfilename_alloc = FALSE; + } + } + } + } + + /* Always deallocate FormInfo linked list nodes without touching node + fields given that these have either been deallocated or are owned + now by the httppost linked list */ + while(first_form) { + FormInfo *ptr = first_form->more; + free(first_form); + first_form = ptr; + } + + return return_value; +} + +/* + * curl_formadd() is a public API to add a section to the multipart formpost. + * + * @unittest: 1308 + */ + +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...) +{ + va_list arg; + CURLFORMcode result; + va_start(arg, last_post); + result = FormAdd(httppost, last_post, arg); + va_end(arg); + return result; +} + +#ifdef __VMS +#include +/* + * get_vms_file_size does what it takes to get the real size of the file + * + * For fixed files, find out the size of the EOF block and adjust. + * + * For all others, have to read the entire file in, discarding the contents. + * Most posted text files will be small, and binary files like zlib archives + * and CD/DVD images should be either a STREAM_LF format or a fixed format. + * + */ +curl_off_t VmsRealFileSize(const char * name, + const struct_stat * stat_buf) +{ + char buffer[8192]; + curl_off_t count; + int ret_stat; + FILE * file; + + file = fopen(name, "r"); + if(file == NULL) + return 0; + + count = 0; + ret_stat = 1; + while(ret_stat > 0) { + ret_stat = fread(buffer, 1, sizeof(buffer), file); + if(ret_stat != 0) + count += ret_stat; + } + fclose(file); + + return count; +} + +/* + * + * VmsSpecialSize checks to see if the stat st_size can be trusted and + * if not to call a routine to get the correct size. + * + */ +static curl_off_t VmsSpecialSize(const char * name, + const struct_stat * stat_buf) +{ + switch(stat_buf->st_fab_rfm) { + case FAB$C_VAR: + case FAB$C_VFC: + return VmsRealFileSize(name, stat_buf); + break; + default: + return stat_buf->st_size; + } +} + +#endif + +#ifndef __VMS +#define filesize(name, stat_data) (stat_data.st_size) +#else + /* Getting the expected file size needs help on VMS */ +#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data) +#endif + +/* + * AddFormData() adds a chunk of data to the FormData linked list. + * + * size is incremented by the chunk length, unless it is NULL + */ +static CURLcode AddFormData(struct FormData **formp, + enum formtype type, + const void *line, + size_t length, + curl_off_t *size) +{ + struct FormData *newform = malloc(sizeof(struct FormData)); + if(!newform) + return CURLE_OUT_OF_MEMORY; + newform->next = NULL; + + if(type <= FORM_CONTENT) { + /* we make it easier for plain strings: */ + if(!length) + length = strlen((char *)line); + + newform->line = malloc(length+1); + if(!newform->line) { + free(newform); + return CURLE_OUT_OF_MEMORY; + } + memcpy(newform->line, line, length); + newform->length = length; + newform->line[length]=0; /* zero terminate for easier debugging */ + } + else + /* For callbacks and files we don't have any actual data so we just keep a + pointer to whatever this points to */ + newform->line = (char *)line; + + newform->type = type; + + if(*formp) { + (*formp)->next = newform; + *formp = newform; + } + else + *formp = newform; + + if(size) { + if(type != FORM_FILE) + /* for static content as well as callback data we add the size given + as input argument */ + *size += length; + else { + /* Since this is a file to be uploaded here, add the size of the actual + file */ + if(!strequal("-", newform->line)) { + struct_stat file; + if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode)) + *size += filesize(newform->line, file); + else + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + } + return CURLE_OK; +} + +/* + * AddFormDataf() adds printf()-style formatted data to the formdata chain. + */ + +static CURLcode AddFormDataf(struct FormData **formp, + curl_off_t *size, + const char *fmt, ...) +{ + char s[4096]; + va_list ap; + va_start(ap, fmt); + vsnprintf(s, sizeof(s), fmt, ap); + va_end(ap); + + return AddFormData(formp, FORM_DATA, s, 0, size); +} + +/* + * Curl_formclean() is used from http.c, this cleans a built FormData linked + * list + */ +CURL_STATIC void Curl_formclean(struct FormData **form_ptr) +{ + struct FormData *next, *form; + + form = *form_ptr; + if(!form) + return; + + do { + next=form->next; /* the following form line */ + if(form->type <= FORM_CONTENT) + free(form->line); /* free the line */ + free(form); /* free the struct */ + + } while((form = next) != NULL); /* continue */ + + *form_ptr = NULL; +} + +/* + * curl_formget() + * Serialize a curl_httppost struct. + * Returns 0 on success. + * + * @unittest: 1308 + */ +int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append) +{ + CURLcode result; + curl_off_t size; + struct FormData *data, *ptr; + + result = Curl_getformdata(NULL, &data, form, NULL, &size); + if(result) + return (int)result; + + for(ptr = data; ptr; ptr = ptr->next) { + if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) { + char buffer[8192]; + size_t nread; + struct Form temp; + + Curl_FormInit(&temp, ptr); + + do { + nread = readfromfile(&temp, buffer, sizeof(buffer)); + if((nread == (size_t) -1) || + (nread > sizeof(buffer)) || + (nread != append(arg, buffer, nread))) { + if(temp.fp) + fclose(temp.fp); + Curl_formclean(&data); + return -1; + } + } while(nread); + } + else { + if(ptr->length != append(arg, ptr->line, ptr->length)) { + Curl_formclean(&data); + return -1; + } + } + } + Curl_formclean(&data); + return 0; +} + +/* + * curl_formfree() is an external function to free up a whole form post + * chain + */ +void curl_formfree(struct curl_httppost *form) +{ + struct curl_httppost *next; + + if(!form) + /* no form to free, just get out of this */ + return; + + do { + next=form->next; /* the following form line */ + + /* recurse to sub-contents */ + curl_formfree(form->more); + + if(!(form->flags & HTTPPOST_PTRNAME)) + free(form->name); /* free the name */ + if(!(form->flags & + (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) + ) + free(form->contents); /* free the contents */ + free(form->contenttype); /* free the content type */ + free(form->showfilename); /* free the faked file name */ + free(form); /* free the struct */ + + } while((form = next) != NULL); /* continue */ +} + +#ifndef HAVE_BASENAME +/* + (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 + Edition) + + The basename() function shall take the pathname pointed to by path and + return a pointer to the final component of the pathname, deleting any + trailing '/' characters. + + If the string pointed to by path consists entirely of the '/' character, + basename() shall return a pointer to the string "/". If the string pointed + to by path is exactly "//", it is implementation-defined whether '/' or "//" + is returned. + + If path is a null pointer or points to an empty string, basename() shall + return a pointer to the string ".". + + The basename() function may modify the string pointed to by path, and may + return a pointer to static storage that may then be overwritten by a + subsequent call to basename(). + + The basename() function need not be reentrant. A function that is not + required to be reentrant is not required to be thread-safe. + +*/ +static char *Curl_basename(char *path) +{ + /* Ignore all the details above for now and make a quick and simple + implementaion here */ + char *s1; + char *s2; + + s1=strrchr(path, '/'); + s2=strrchr(path, '\\'); + + if(s1 && s2) { + path = (s1 > s2? s1 : s2)+1; + } + else if(s1) + path = s1 + 1; + else if(s2) + path = s2 + 1; + + return path; +} +#endif + +static char *strippath(const char *fullfile) +{ + char *filename; + char *base; + filename = strdup(fullfile); /* duplicate since basename() may ruin the + buffer it works on */ + if(!filename) + return NULL; + base = strdup(basename(filename)); + + free(filename); /* free temporary buffer */ + + return base; /* returns an allocated string or NULL ! */ +} + +static CURLcode formdata_add_filename(const struct curl_httppost *file, + struct FormData **form, + curl_off_t *size) +{ + CURLcode result = CURLE_OK; + char *filename = file->showfilename; + char *filebasename = NULL; + char *filename_escaped = NULL; + + if(!filename) { + filebasename = strippath(file->contents); + if(!filebasename) + return CURLE_OUT_OF_MEMORY; + filename = filebasename; + } + + if(strchr(filename, '\\') || strchr(filename, '"')) { + char *p0, *p1; + + /* filename need be escaped */ + filename_escaped = malloc(strlen(filename)*2+1); + if(!filename_escaped) { + free(filebasename); + return CURLE_OUT_OF_MEMORY; + } + p0 = filename_escaped; + p1 = filename; + while(*p1) { + if(*p1 == '\\' || *p1 == '"') + *p0++ = '\\'; + *p0++ = *p1++; + } + *p0 = '\0'; + filename = filename_escaped; + } + result = AddFormDataf(form, size, + "; filename=\"%s\"", + filename); + free(filename_escaped); + free(filebasename); + return result; +} + +/* + * Curl_getformdata() converts a linked list of "meta data" into a complete + * (possibly huge) multipart formdata. The input list is in 'post', while the + * output resulting linked lists gets stored in '*finalform'. *sizep will get + * the total size of the whole POST. + * A multipart/form_data content-type is built, unless a custom content-type + * is passed in 'custom_content_type'. + * + * This function will not do a failf() for the potential memory failures but + * should for all other errors it spots. Just note that this function MAY get + * a NULL pointer in the 'data' argument. + */ + +CURL_STATIC CURLcode Curl_getformdata(struct SessionHandle *data, + struct FormData **finalform, + struct curl_httppost *post, + const char *custom_content_type, + curl_off_t *sizep) +{ + struct FormData *form = NULL; + struct FormData *firstform; + struct curl_httppost *file; + CURLcode result = CURLE_OK; + + curl_off_t size = 0; /* support potentially ENORMOUS formposts */ + char *boundary; + char *fileboundary = NULL; + struct curl_slist* curList; + + *finalform = NULL; /* default form is empty */ + + if(!post) + return result; /* no input => no output! */ + + boundary = formboundary(data); + if(!boundary) + return CURLE_OUT_OF_MEMORY; + + /* Make the first line of the output */ + result = AddFormDataf(&form, NULL, + "%s; boundary=%s\r\n", + custom_content_type?custom_content_type: + "Content-Type: multipart/form-data", + boundary); + + if(result) { + free(boundary); + return result; + } + /* we DO NOT include that line in the total size of the POST, since it'll be + part of the header! */ + + firstform = form; + + do { + + if(size) { + result = AddFormDataf(&form, &size, "\r\n"); + if(result) + break; + } + + /* boundary */ + result = AddFormDataf(&form, &size, "--%s\r\n", boundary); + if(result) + break; + + /* Maybe later this should be disabled when a custom_content_type is + passed, since Content-Disposition is not meaningful for all multipart + types. + */ + result = AddFormDataf(&form, &size, + "Content-Disposition: form-data; name=\""); + if(result) + break; + + result = AddFormData(&form, FORM_DATA, post->name, post->namelength, + &size); + if(result) + break; + + result = AddFormDataf(&form, &size, "\""); + if(result) + break; + + if(post->more) { + /* If used, this is a link to more file names, we must then do + the magic to include several files with the same field name */ + + free(fileboundary); + fileboundary = formboundary(data); + if(!fileboundary) { + result = CURLE_OUT_OF_MEMORY; + break; + } + + result = AddFormDataf(&form, &size, + "\r\nContent-Type: multipart/mixed;" + " boundary=%s\r\n", + fileboundary); + if(result) + break; + } + + file = post; + + do { + + /* If 'showfilename' is set, that is a faked name passed on to us + to use to in the formpost. If that is not set, the actually used + local file name should be added. */ + + if(post->more) { + /* if multiple-file */ + result = AddFormDataf(&form, &size, + "\r\n--%s\r\nContent-Disposition: " + "attachment", + fileboundary); + if(result) + break; + result = formdata_add_filename(file, &form, &size); + if(result) + break; + } + else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER| + HTTPPOST_CALLBACK)) { + /* it should be noted that for the HTTPPOST_FILENAME and + HTTPPOST_CALLBACK cases the ->showfilename struct member is always + assigned at this point */ + if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) { + result = formdata_add_filename(post, &form, &size); + } + + if(result) + break; + } + + if(file->contenttype) { + /* we have a specified type */ + result = AddFormDataf(&form, &size, + "\r\nContent-Type: %s", + file->contenttype); + if(result) + break; + } + + curList = file->contentheader; + while(curList) { + /* Process the additional headers specified for this form */ + result = AddFormDataf( &form, &size, "\r\n%s", curList->data ); + if(result) + break; + curList = curList->next; + } + if(result) + break; + + result = AddFormDataf(&form, &size, "\r\n\r\n"); + if(result) + break; + + if((post->flags & HTTPPOST_FILENAME) || + (post->flags & HTTPPOST_READFILE)) { + /* we should include the contents from the specified file */ + FILE *fileread; + + fileread = strequal("-", file->contents)? + stdin:fopen(file->contents, "rb"); /* binary read for win32 */ + + /* + * VMS: This only allows for stream files on VMS. Stream files are + * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC, + * every record needs to have a \n appended & 1 added to SIZE + */ + + if(fileread) { + if(fileread != stdin) { + /* close the file */ + fclose(fileread); + /* add the file name only - for later reading from this */ + result = AddFormData(&form, FORM_FILE, file->contents, 0, &size); + } + else { + /* When uploading from stdin, we can't know the size of the file, + * thus must read the full file as before. We *could* use chunked + * transfer-encoding, but that only works for HTTP 1.1 and we + * can't be sure we work with such a server. + */ + size_t nread; + char buffer[512]; + while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) { + result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size); + if(result) + break; + } + } + } + else { + if(data) + failf(data, "couldn't open file \"%s\"", file->contents); + *finalform = NULL; + result = CURLE_READ_ERROR; + } + } + else if(post->flags & HTTPPOST_BUFFER) + /* include contents of buffer */ + result = AddFormData(&form, FORM_CONTENT, post->buffer, + post->bufferlength, &size); + else if(post->flags & HTTPPOST_CALLBACK) + /* the contents should be read with the callback and the size + is set with the contentslength */ + result = AddFormData(&form, FORM_CALLBACK, post->userp, + post->contentslength, &size); + else + /* include the contents we got */ + result = AddFormData(&form, FORM_CONTENT, post->contents, + post->contentslength, &size); + + file = file->more; + } while(file && !result); /* for each specified file for this field */ + + if(result) + break; + + if(post->more) { + /* this was a multiple-file inclusion, make a termination file + boundary: */ + result = AddFormDataf(&form, &size, + "\r\n--%s--", + fileboundary); + if(result) + break; + } + + } while((post = post->next) != NULL); /* for each field */ + + /* end-boundary for everything */ + if(!result) + result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary); + + if(result) { + Curl_formclean(&firstform); + free(fileboundary); + free(boundary); + return result; + } + + *sizep = size; + + free(fileboundary); + free(boundary); + + *finalform = firstform; + + return result; +} + +/* + * Curl_FormInit() inits the struct 'form' points to with the 'formdata' + * and resets the 'sent' counter. + */ +CURL_STATIC int Curl_FormInit(struct Form *form, struct FormData *formdata ) +{ + if(!formdata) + return 1; /* error */ + + form->data = formdata; + form->sent = 0; + form->fp = NULL; + form->fread_func = ZERO_NULL; + + return 0; +} + +#ifndef __VMS +# define fopen_read fopen +#else + /* + * vmsfopenread + * + * For upload to work as expected on VMS, different optional + * parameters must be added to the fopen command based on + * record format of the file. + * + */ +# define fopen_read vmsfopenread +static FILE * vmsfopenread(const char *file, const char *mode) { + struct_stat statbuf; + int result; + + result = stat(file, &statbuf); + + switch (statbuf.st_fab_rfm) { + case FAB$C_VAR: + case FAB$C_VFC: + case FAB$C_STMCR: + return fopen(file, "r"); + break; + default: + return fopen(file, "r", "rfm=stmlf", "ctx=stm"); + } +} +#endif + +/* + * readfromfile() + * + * The read callback that this function may use can return a value larger than + * 'size' (which then this function returns) that indicates a problem and it + * must be properly dealt with + */ +static size_t readfromfile(struct Form *form, char *buffer, + size_t size) +{ + size_t nread; + bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE; + + if(callback) { + if(form->fread_func == ZERO_NULL) + return 0; + else + nread = form->fread_func(buffer, 1, size, form->data->line); + } + else { + if(!form->fp) { + /* this file hasn't yet been opened */ + form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */ + if(!form->fp) + return (size_t)-1; /* failure */ + } + nread = fread(buffer, 1, size, form->fp); + } + if(!nread) { + /* this is the last chunk from the file, move on */ + if(form->fp) { + fclose(form->fp); + form->fp = NULL; + } + form->data = form->data->next; + } + + return nread; +} + +/* + * Curl_FormReader() is the fread() emulation function that will be used to + * deliver the formdata to the transfer loop and then sent away to the peer. + */ +CURL_STATIC size_t Curl_FormReader(char *buffer, + size_t size, + size_t nitems, + FILE *mydata) +{ + struct Form *form; + size_t wantedsize; + size_t gotsize = 0; + + form=(struct Form *)mydata; + + wantedsize = size * nitems; + + if(!form->data) + return 0; /* nothing, error, empty */ + + if((form->data->type == FORM_FILE) || + (form->data->type == FORM_CALLBACK)) { + gotsize = readfromfile(form, buffer, wantedsize); + + if(gotsize) + /* If positive or -1, return. If zero, continue! */ + return gotsize; + } + do { + + if((form->data->length - form->sent ) > wantedsize - gotsize) { + + memcpy(buffer + gotsize , form->data->line + form->sent, + wantedsize - gotsize); + + form->sent += wantedsize-gotsize; + + return wantedsize; + } + + memcpy(buffer+gotsize, + form->data->line + form->sent, + (form->data->length - form->sent) ); + gotsize += form->data->length - form->sent; + + form->sent = 0; + + form->data = form->data->next; /* advance */ + + } while(form->data && (form->data->type < FORM_CALLBACK)); + /* If we got an empty line and we have more data, we proceed to the next + line immediately to avoid returning zero before we've reached the end. */ + + return gotsize; +} + +/* + * Curl_formpostheader() returns the first line of the formpost, the + * request-header part (which is not part of the request-body like the rest of + * the post). + */ +CURL_STATIC char *Curl_formpostheader(void *formp, size_t *len) +{ + char *header; + struct Form *form=(struct Form *)formp; + + if(!form->data) + return 0; /* nothing, ERROR! */ + + header = form->data->line; + *len = form->data->length; + + form->data = form->data->next; /* advance */ + + return header; +} + +/* + * formboundary() creates a suitable boundary string and returns an allocated + * one. + */ +static char *formboundary(struct SessionHandle *data) +{ + /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615) + combinations */ + return aprintf("------------------------%08x%08x", + Curl_rand(data), Curl_rand(data)); +} + +#else /* CURL_DISABLE_HTTP */ +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...) +{ + (void)httppost; + (void)last_post; + return CURL_FORMADD_DISABLED; +} + +int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append) +{ + (void) form; + (void) arg; + (void) append; + return CURL_FORMADD_DISABLED; +} + +void curl_formfree(struct curl_httppost *form) +{ + (void)form; + /* does nothing HTTP is disabled */ +} + + +#endif /* !defined(CURL_DISABLE_HTTP) */ diff --git a/libcurl/src/lib/formdata.h b/libcurl/src/lib/formdata.h new file mode 100644 index 0000000..25480f1 --- /dev/null +++ b/libcurl/src/lib/formdata.h @@ -0,0 +1,98 @@ +#ifndef HEADER_CURL_FORMDATA_H +#define HEADER_CURL_FORMDATA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +enum formtype { + FORM_DATA, /* form metadata (convert to network encoding if necessary) */ + FORM_CONTENT, /* form content (never convert) */ + FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback + */ + FORM_FILE /* 'line' points to a file name we should read from + to create the form data (never convert) */ +}; + +/* plain and simple linked list with lines to send */ +struct FormData { + struct FormData *next; + enum formtype type; + char *line; + size_t length; +}; + +struct Form { + struct FormData *data; /* current form line to send */ + size_t sent; /* number of bytes of the current line that has + already been sent in a previous invoke */ + FILE *fp; /* file to read from */ + curl_read_callback fread_func; /* fread callback pointer */ +}; + +/* used by FormAdd for temporary storage */ +typedef struct FormInfo { + char *name; + bool name_alloc; + size_t namelength; + char *value; + bool value_alloc; + size_t contentslength; + char *contenttype; + bool contenttype_alloc; + long flags; + char *buffer; /* pointer to existing buffer used for file upload */ + size_t bufferlength; + char *showfilename; /* The file name to show. If not set, the actual + file name will be used */ + bool showfilename_alloc; + char *userp; /* pointer for the read callback */ + struct curl_slist* contentheader; + struct FormInfo *more; +} FormInfo; + +CURL_STATIC int Curl_FormInit(struct Form *form, struct FormData *formdata ); + +CURL_STATIC CURLcode Curl_getformdata(struct SessionHandle *data, + struct FormData **, + struct curl_httppost *post, + const char *custom_contenttype, + curl_off_t *size); + +/* fread() emulation */ +CURL_STATIC size_t Curl_FormReader(char *buffer, + size_t size, + size_t nitems, + FILE *mydata); + +/* + * Curl_formpostheader() returns the first line of the formpost, the + * request-header part (which is not part of the request-body like the rest of + * the post). + */ +CURL_STATIC char *Curl_formpostheader(void *formp, size_t *len); + +CURL_STATIC char *Curl_FormBoundary(void); + +CURL_STATIC void Curl_formclean(struct FormData **); + +CURL_STATIC CURLcode Curl_formconvert(struct SessionHandle *, struct FormData *); + +#endif /* HEADER_CURL_FORMDATA_H */ diff --git a/libcurl/src/lib/ftp.c b/libcurl/src/lib/ftp.c new file mode 100644 index 0000000..527d209 --- /dev/null +++ b/libcurl/src/lib/ftp.c @@ -0,0 +1,4586 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "if2ip.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "ftp.h" +#include "fileinfo.h" +#include "ftplistparser.h" +#include "curl_sec.h" +#include "strtoofft.h" +#include "strequal.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "inet_pton.h" +#include "select.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "multiif.h" +#include "url.h" +#include "rawstr.h" +#include "speedcheck.h" +#include "warnless.h" +#include "http_proxy.h" +#include "non-ascii.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt +#endif + +/* Local API functions */ +#ifndef DEBUGBUILD +static void _state(struct connectdata *conn, + ftpstate newstate); +#define state(x,y) _state(x,y) +#else +static void _state(struct connectdata *conn, + ftpstate newstate, + int lineno); +#define state(x,y) _state(x,y,__LINE__) +#endif + +static CURLcode ftp_sendquote(struct connectdata *conn, + struct curl_slist *quote); +static CURLcode ftp_quit(struct connectdata *conn); +static CURLcode ftp_parse_url_path(struct connectdata *conn); +static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done); +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void ftp_pasv_verbose(struct connectdata *conn, + Curl_addrinfo *ai, + char *newhost, /* ascii version */ + int port); +#endif +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn); +static CURLcode ftp_state_mdtm(struct connectdata *conn); +static CURLcode ftp_state_quote(struct connectdata *conn, + bool init, ftpstate instate); +static CURLcode ftp_nb_type(struct connectdata *conn, + bool ascii, ftpstate newstate); +static int ftp_need_type(struct connectdata *conn, + bool ascii); +static CURLcode ftp_do(struct connectdata *conn, bool *done); +static CURLcode ftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode ftp_connect(struct connectdata *conn, bool *done); +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection); +static CURLcode ftp_do_more(struct connectdata *conn, int *completed); +static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); +static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode ftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode ftp_setup_connection(struct connectdata * conn); + +static CURLcode init_wc_data(struct connectdata *conn); +static CURLcode wc_statemach(struct connectdata *conn); + +static void wc_data_dtor(void *ptr); + +static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize); + +static CURLcode ftp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *ftpcode, + size_t *size); +static CURLcode ftp_dophase_done(struct connectdata *conn, + bool connected); + +/* easy-to-use macro: */ +#define PPSENDF(x,y,z) if((result = Curl_pp_sendf(x,y,z))) \ + return result + + +/* + * FTP protocol handler. + */ + +const struct Curl_handler Curl_handler_ftp = { + "FTP", /* scheme */ + ftp_setup_connection, /* setup_connection */ + ftp_do, /* do_it */ + ftp_done, /* done */ + ftp_do_more, /* do_more */ + ftp_connect, /* connect_it */ + ftp_multi_statemach, /* connecting */ + ftp_doing, /* doing */ + ftp_getsock, /* proto_getsock */ + ftp_getsock, /* doing_getsock */ + ftp_domore_getsock, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_FTP, /* defport */ + CURLPROTO_FTP, /* protocol */ + PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD + | PROTOPT_NOURLQUERY /* flags */ +}; + + +#ifdef USE_SSL +/* + * FTPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ftps = { + "FTPS", /* scheme */ + ftp_setup_connection, /* setup_connection */ + ftp_do, /* do_it */ + ftp_done, /* done */ + ftp_do_more, /* do_more */ + ftp_connect, /* connect_it */ + ftp_multi_statemach, /* connecting */ + ftp_doing, /* doing */ + ftp_getsock, /* proto_getsock */ + ftp_getsock, /* doing_getsock */ + ftp_domore_getsock, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_FTPS, /* defport */ + CURLPROTO_FTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | + PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY /* flags */ +}; +#endif + +#ifndef CURL_DISABLE_HTTP +/* + * HTTP-proxyed FTP protocol handler. + */ + +static const struct Curl_handler Curl_handler_ftp_proxy = { + "FTP", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_FTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + + +#ifdef USE_SSL +/* + * HTTP-proxyed FTPS protocol handler. + */ + +static const struct Curl_handler Curl_handler_ftps_proxy = { + "FTPS", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_FTPS, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; +#endif +#endif + + +/* + * NOTE: back in the old days, we added code in the FTP code that made NOBODY + * requests on files respond with headers passed to the client/stdout that + * looked like HTTP ones. + * + * This approach is not very elegant, it causes confusion and is error-prone. + * It is subject for removal at the next (or at least a future) soname bump. + * Until then you can test the effects of the removal by undefining the + * following define named CURL_FTP_HTTPSTYLE_HEAD. + */ +#define CURL_FTP_HTTPSTYLE_HEAD 1 + +static void freedirs(struct ftp_conn *ftpc) +{ + int i; + if(ftpc->dirs) { + for(i=0; i < ftpc->dirdepth; i++) { + free(ftpc->dirs[i]); + ftpc->dirs[i]=NULL; + } + free(ftpc->dirs); + ftpc->dirs = NULL; + ftpc->dirdepth = 0; + } + Curl_safefree(ftpc->file); + + /* no longer of any use */ + Curl_safefree(ftpc->newhost); +} + +/* Returns non-zero if the given string contains CR (\r) or LF (\n), + which are not allowed within RFC 959 . + Note: The input string is in the client's encoding which might + not be ASCII, so escape sequences \r & \n must be used instead + of hex values 0x0d & 0x0a. +*/ +static bool isBadFtpString(const char *string) +{ + return ((NULL != strchr(string, '\r')) || + (NULL != strchr(string, '\n'))) ? TRUE : FALSE; +} + +/*********************************************************************** + * + * AcceptServerConnect() + * + * After connection request is received from the server this function is + * called to accept the connection and close the listening socket + * + */ +static CURLcode AcceptServerConnect(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + curl_socket_t sock = conn->sock[SECONDARYSOCKET]; + curl_socket_t s = CURL_SOCKET_BAD; +#ifdef ENABLE_IPV6 + struct Curl_sockaddr_storage add; +#else + struct sockaddr_in add; +#endif + curl_socklen_t size = (curl_socklen_t) sizeof(add); + + if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) { + size = sizeof(add); + + s=accept(sock, (struct sockaddr *) &add, &size); + } + Curl_closesocket(conn, sock); /* close the first socket */ + + if(CURL_SOCKET_BAD == s) { + failf(data, "Error accept()ing server connect"); + return CURLE_FTP_PORT_FAILED; + } + infof(data, "Connection accepted from server\n"); + + conn->sock[SECONDARYSOCKET] = s; + (void)curlx_nonblock(s, TRUE); /* enable non-blocking */ + conn->sock_accepted[SECONDARYSOCKET] = TRUE; + + if(data->set.fsockopt) { + int error = 0; + + /* activate callback for setting socket options */ + error = data->set.fsockopt(data->set.sockopt_client, + s, + CURLSOCKTYPE_ACCEPT); + + if(error) { + Curl_closesocket(conn, s); /* close the socket and bail out */ + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; + return CURLE_ABORTED_BY_CALLBACK; + } + } + + return CURLE_OK; + +} + +/* + * ftp_timeleft_accept() returns the amount of milliseconds left allowed for + * waiting server to connect. If the value is negative, the timeout time has + * already elapsed. + * + * The start time is stored in progress.t_acceptdata - as set with + * Curl_pgrsTime(..., TIMER_STARTACCEPT); + * + */ +static long ftp_timeleft_accept(struct SessionHandle *data) +{ + long timeout_ms = DEFAULT_ACCEPT_TIMEOUT; + long other; + struct timeval now; + + if(data->set.accepttimeout > 0) + timeout_ms = data->set.accepttimeout; + + now = Curl_tvnow(); + + /* check if the generic timeout possibly is set shorter */ + other = Curl_timeleft(data, &now, FALSE); + if(other && (other < timeout_ms)) + /* note that this also works fine for when other happens to be negative + due to it already having elapsed */ + timeout_ms = other; + else { + /* subtract elapsed time */ + timeout_ms -= Curl_tvdiff(now, data->progress.t_acceptdata); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; + } + + return timeout_ms; +} + + +/*********************************************************************** + * + * ReceivedServerConnect() + * + * After allowing server to connect to us from data port, this function + * checks both data connection for connection establishment and ctrl + * connection for a negative response regarding a failure in connecting + * + */ +static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) +{ + struct SessionHandle *data = conn->data; + curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET]; + curl_socket_t data_sock = conn->sock[SECONDARYSOCKET]; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + int result; + long timeout_ms; + ssize_t nread; + int ftpcode; + + *received = FALSE; + + timeout_ms = ftp_timeleft_accept(data); + infof(data, "Checking for server connect\n"); + if(timeout_ms < 0) { + /* if a timeout was already reached, bail out */ + failf(data, "Accept timeout occurred while waiting server connect"); + return CURLE_FTP_ACCEPT_TIMEOUT; + } + + /* First check whether there is a cached response from server */ + if(pp->cache_size && pp->cache && pp->cache[0] > '3') { + /* Data connection could not be established, let's return */ + infof(data, "There is negative response in cache while serv connect\n"); + Curl_GetFTPResponse(&nread, conn, &ftpcode); + return CURLE_FTP_ACCEPT_FAILED; + } + + result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0); + + /* see if the connection request is already here */ + switch (result) { + case -1: /* error */ + /* let's die here */ + failf(data, "Error while waiting for server connect"); + return CURLE_FTP_ACCEPT_FAILED; + case 0: /* Server connect is not received yet */ + break; /* loop */ + default: + + if(result & CURL_CSELECT_IN2) { + infof(data, "Ready to accept data connection from server\n"); + *received = TRUE; + } + else if(result & CURL_CSELECT_IN) { + infof(data, "Ctrl conn has data while waiting for data conn\n"); + Curl_GetFTPResponse(&nread, conn, &ftpcode); + + if(ftpcode/100 > 3) + return CURLE_FTP_ACCEPT_FAILED; + + return CURLE_FTP_WEIRD_SERVER_REPLY; + } + + break; + } /* switch() */ + + return CURLE_OK; +} + + +/*********************************************************************** + * + * InitiateTransfer() + * + * After connection from server is accepted this function is called to + * setup transfer parameters and initiate the data transfer. + * + */ +static CURLcode InitiateTransfer(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + struct FTP *ftp = data->req.protop; + CURLcode result = CURLE_OK; + + if(conn->ssl[SECONDARYSOCKET].use) { + /* since we only have a plaintext TCP connection here, we must now + * do the TLS stuff */ + infof(data, "Doing the SSL/TLS handshake on the data stream\n"); + result = Curl_ssl_connect(conn, SECONDARYSOCKET); + if(result) + return result; + } + + if(conn->proto.ftpc.state_saved == FTP_STOR) { + *(ftp->bytecountp)=0; + + /* When we know we're uploading a specified file, we can get the file + size prior to the actual upload. */ + + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* set the SO_SNDBUF for the secondary socket for those who need it */ + Curl_sndbufset(conn->sock[SECONDARYSOCKET]); + + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ + SECONDARYSOCKET, ftp->bytecountp); + } + else { + /* FTP download: */ + Curl_setup_transfer(conn, SECONDARYSOCKET, + conn->proto.ftpc.retr_size_saved, FALSE, + ftp->bytecountp, -1, NULL); /* no upload here */ + } + + conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ + state(conn, FTP_STOP); + + return CURLE_OK; +} + +/*********************************************************************** + * + * AllowServerConnect() + * + * When we've issue the PORT command, we have told the server to connect to + * us. This function checks whether data connection is established if so it is + * accepted. + * + */ +static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) +{ + struct SessionHandle *data = conn->data; + long timeout_ms; + CURLcode result = CURLE_OK; + + *connected = FALSE; + infof(data, "Preparing for accepting server on data port\n"); + + /* Save the time we start accepting server connect */ + Curl_pgrsTime(data, TIMER_STARTACCEPT); + + timeout_ms = ftp_timeleft_accept(data); + if(timeout_ms < 0) { + /* if a timeout was already reached, bail out */ + failf(data, "Accept timeout occurred while waiting server connect"); + return CURLE_FTP_ACCEPT_TIMEOUT; + } + + /* see if the connection request is already here */ + result = ReceivedServerConnect(conn, connected); + if(result) + return result; + + if(*connected) { + result = AcceptServerConnect(conn); + if(result) + return result; + + result = InitiateTransfer(conn); + if(result) + return result; + } + else { + /* Add timeout to multi handle and break out of the loop */ + if(!result && *connected == FALSE) { + if(data->set.accepttimeout > 0) + Curl_expire(data, data->set.accepttimeout); + else + Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT); + } + } + + return result; +} + +/* macro to check for a three-digit ftp status code at the start of the + given string */ +#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \ + ISDIGIT(line[2])) + +/* macro to check for the last line in an FTP server response */ +#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3])) + +static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len, + int *code) +{ + (void)conn; + + if((len > 3) && LASTLINE(line)) { + *code = curlx_sltosi(strtol(line, NULL, 10)); + return TRUE; + } + + return FALSE; +} + +static CURLcode ftp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *ftpcode, /* return the ftp-code if done */ + size_t *size) /* size of the response */ +{ + struct connectdata *conn = pp->conn; + struct SessionHandle *data = conn->data; +#ifdef HAVE_GSSAPI + char * const buf = data->state.buffer; +#endif + CURLcode result = CURLE_OK; + int code; + + result = Curl_pp_readresp(sockfd, pp, &code, size); + +#if defined(HAVE_GSSAPI) + /* handle the security-oriented responses 6xx ***/ + /* FIXME: some errorchecking perhaps... ***/ + switch(code) { + case 631: + code = Curl_sec_read_msg(conn, buf, PROT_SAFE); + break; + case 632: + code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE); + break; + case 633: + code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL); + break; + default: + /* normal ftp stuff we pass through! */ + break; + } +#endif + + /* store the latest code for later retrieval */ + data->info.httpcode=code; + + if(ftpcode) + *ftpcode = code; + + if(421 == code) { + /* 421 means "Service not available, closing control connection." and FTP + * servers use it to signal that idle session timeout has been exceeded. + * If we ignored the response, it could end up hanging in some cases. + * + * This response code can come at any point so having it treated + * generically is a good idea. + */ + infof(data, "We got a 421 - timeout!\n"); + state(conn, FTP_STOP); + return CURLE_OPERATION_TIMEDOUT; + } + + return result; +} + +/* --- parse FTP server responses --- */ + +/* + * Curl_GetFTPResponse() is a BLOCKING function to read the full response + * from a server after a command. + * + */ + +CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ + struct connectdata *conn, + int *ftpcode) /* return the ftp-code */ +{ + /* + * We cannot read just one byte per read() and then go back to select() as + * the OpenSSL read() doesn't grok that properly. + * + * Alas, read as much as possible, split up into lines, use the ending + * line in a response or continue reading. */ + + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + long timeout; /* timeout in milliseconds */ + long interval_ms; + struct SessionHandle *data = conn->data; + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + size_t nread; + int cache_skip=0; + int value_to_be_ignored=0; + + if(ftpcode) + *ftpcode = 0; /* 0 for errors */ + else + /* make the pointer point to something for the rest of this function */ + ftpcode = &value_to_be_ignored; + + *nreadp=0; + + while(!*ftpcode && !result) { + /* check and reset timeout value every lap */ + timeout = Curl_pp_state_timeout(pp); + + if(timeout <=0 ) { + failf(data, "FTP response timeout"); + return CURLE_OPERATION_TIMEDOUT; /* already too little time */ + } + + interval_ms = 1000; /* use 1 second timeout intervals */ + if(timeout < interval_ms) + interval_ms = timeout; + + /* + * Since this function is blocking, we need to wait here for input on the + * connection and only then we call the response reading function. We do + * timeout at least every second to make the timeout check run. + * + * A caution here is that the ftp_readresp() function has a cache that may + * contain pieces of a response from the previous invoke and we need to + * make sure we don't just wait for input while there is unhandled data in + * that cache. But also, if the cache is there, we call ftp_readresp() and + * the cache wasn't good enough to continue we must not just busy-loop + * around this function. + * + */ + + if(pp->cache && (cache_skip < 2)) { + /* + * There's a cache left since before. We then skipping the wait for + * socket action, unless this is the same cache like the previous round + * as then the cache was deemed not enough to act on and we then need to + * wait for more data anyway. + */ + } + else { + switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) { + case -1: /* select() error, stop reading */ + failf(data, "FTP response aborted due to select/poll error: %d", + SOCKERRNO); + return CURLE_RECV_ERROR; + + case 0: /* timeout */ + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + continue; /* just continue in our loop for the timeout duration */ + + default: /* for clarity */ + break; + } + } + result = ftp_readresp(sockfd, pp, ftpcode, &nread); + if(result) + break; + + if(!nread && pp->cache) + /* bump cache skip counter as on repeated skips we must wait for more + data */ + cache_skip++; + else + /* when we got data or there is no cache left, we reset the cache skip + counter */ + cache_skip=0; + + *nreadp += nread; + + } /* while there's buffer left and loop is requested */ + + pp->pending_resp = FALSE; + + return result; +} + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ +static const char * const ftp_state_names[]={ + "STOP", + "WAIT220", + "AUTH", + "USER", + "PASS", + "ACCT", + "PBSZ", + "PROT", + "CCC", + "PWD", + "SYST", + "NAMEFMT", + "QUOTE", + "RETR_PREQUOTE", + "STOR_PREQUOTE", + "POSTQUOTE", + "CWD", + "MKD", + "MDTM", + "TYPE", + "LIST_TYPE", + "RETR_TYPE", + "STOR_TYPE", + "SIZE", + "RETR_SIZE", + "STOR_SIZE", + "REST", + "RETR_REST", + "PORT", + "PRET", + "PASV", + "LIST", + "RETR", + "STOR", + "QUIT" +}; +#endif + +/* This is the ONLY way to change FTP state! */ +static void _state(struct connectdata *conn, + ftpstate newstate +#ifdef DEBUGBUILD + , int lineno +#endif + ) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + +#if defined(DEBUGBUILD) + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) lineno; +#else + if(ftpc->state != newstate) + infof(conn->data, "FTP %p (line %d) state change from %s to %s\n", + (void *)ftpc, lineno, ftp_state_names[ftpc->state], + ftp_state_names[newstate]); +#endif +#endif + + ftpc->state = newstate; +} + +static CURLcode ftp_state_user(struct connectdata *conn) +{ + CURLcode result; + struct FTP *ftp = conn->data->req.protop; + /* send USER */ + PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:""); + + state(conn, FTP_USER); + conn->data->state.ftp_trying_alternative = FALSE; + + return CURLE_OK; +} + +static CURLcode ftp_state_pwd(struct connectdata *conn) +{ + CURLcode result; + + /* send PWD to discover our entry point */ + PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD"); + state(conn, FTP_PWD); + + return CURLE_OK; +} + +/* For the FTP "protocol connect" and "doing" phases only */ +static int ftp_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); +} + +/* For the FTP "DO_MORE" phase only */ +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(!numsocks) + return GETSOCK_BLANK; + + /* When in DO_MORE state, we could be either waiting for us to connect to a + * remote site, or we could wait for that site to connect to us. Or just + * handle ordinary commands. + */ + + if(FTP_STOP == ftpc->state) { + int bits = GETSOCK_READSOCK(0); + + /* if stopped and still in this state, then we're also waiting for a + connect on the secondary connection */ + socks[0] = conn->sock[FIRSTSOCKET]; + + if(!conn->data->set.ftp_use_port) { + int s; + int i; + /* PORT is used to tell the server to connect to us, and during that we + don't do happy eyeballs, but we do if we connect to the server */ + for(s=1, i=0; i<2; i++) { + if(conn->tempsock[i] != CURL_SOCKET_BAD) { + socks[s] = conn->tempsock[i]; + bits |= GETSOCK_WRITESOCK(s++); + } + } + } + else { + socks[1] = conn->sock[SECONDARYSOCKET]; + bits |= GETSOCK_WRITESOCK(1); + } + + return bits; + } + else + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); +} + +/* This is called after the FTP_QUOTE state is passed. + + ftp_state_cwd() sends the range of CWD commands to the server to change to + the correct directory. It may also need to send MKD commands to create + missing ones, if that option is enabled. +*/ +static CURLcode ftp_state_cwd(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(ftpc->cwddone) + /* already done and fine */ + result = ftp_state_mdtm(conn); + else { + ftpc->count2 = 0; /* count2 counts failed CWDs */ + + /* count3 is set to allow a MKD to fail once. In the case when first CWD + fails and then MKD fails (due to another session raced it to create the + dir) this then allows for a second try to CWD to it */ + ftpc->count3 = (conn->data->set.ftp_create_missing_dirs==2)?1:0; + + if(conn->bits.reuse && ftpc->entrypath) { + /* This is a re-used connection. Since we change directory to where the + transfer is taking place, we must first get back to the original dir + where we ended up after login: */ + ftpc->count1 = 0; /* we count this as the first path, then we add one + for all upcoming ones in the ftp->dirs[] array */ + PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath); + state(conn, FTP_CWD); + } + else { + if(ftpc->dirdepth) { + ftpc->count1 = 1; + /* issue the first CWD, the rest is sent when the CWD responses are + received... */ + PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->count1 -1]); + state(conn, FTP_CWD); + } + else { + /* No CWD necessary */ + result = ftp_state_mdtm(conn); + } + } + } + return result; +} + +typedef enum { + EPRT, + PORT, + DONE +} ftpport; + +static CURLcode ftp_state_use_port(struct connectdata *conn, + ftpport fcmd) /* start with this */ + +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct SessionHandle *data=conn->data; + curl_socket_t portsock= CURL_SOCKET_BAD; + char myhost[256] = ""; + + struct Curl_sockaddr_storage ss; + Curl_addrinfo *res, *ai; + curl_socklen_t sslen; + char hbuf[NI_MAXHOST]; + struct sockaddr *sa=(struct sockaddr *)&ss; + struct sockaddr_in * const sa4 = (void *)sa; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 * const sa6 = (void *)sa; +#endif + char tmp[1024]; + static const char mode[][5] = { "EPRT", "PORT" }; + int rc; + int error; + char *host = NULL; + char *string_ftpport = data->set.str[STRING_FTPPORT]; + struct Curl_dns_entry *h=NULL; + unsigned short port_min = 0; + unsigned short port_max = 0; + unsigned short port; + bool possibly_non_local = TRUE; + + char *addr = NULL; + + /* Step 1, figure out what is requested, + * accepted format : + * (ipv4|ipv6|domain|interface)?(:port(-range)?)? + */ + + if(data->set.str[STRING_FTPPORT] && + (strlen(data->set.str[STRING_FTPPORT]) > 1)) { + +#ifdef ENABLE_IPV6 + size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ? + INET6_ADDRSTRLEN : strlen(string_ftpport); +#else + size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ? + INET_ADDRSTRLEN : strlen(string_ftpport); +#endif + char *ip_start = string_ftpport; + char *ip_end = NULL; + char *port_start = NULL; + char *port_sep = NULL; + + addr = calloc(addrlen+1, 1); + if(!addr) + return CURLE_OUT_OF_MEMORY; + +#ifdef ENABLE_IPV6 + if(*string_ftpport == '[') { + /* [ipv6]:port(-range) */ + ip_start = string_ftpport + 1; + if((ip_end = strchr(string_ftpport, ']')) != NULL ) + strncpy(addr, ip_start, ip_end - ip_start); + } + else +#endif + if(*string_ftpport == ':') { + /* :port */ + ip_end = string_ftpport; + } + else if((ip_end = strchr(string_ftpport, ':')) != NULL) { + /* either ipv6 or (ipv4|domain|interface):port(-range) */ +#ifdef ENABLE_IPV6 + if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { + /* ipv6 */ + port_min = port_max = 0; + strcpy(addr, string_ftpport); + ip_end = NULL; /* this got no port ! */ + } + else +#endif + /* (ipv4|domain|interface):port(-range) */ + strncpy(addr, string_ftpport, ip_end - ip_start ); + } + else + /* ipv4|interface */ + strcpy(addr, string_ftpport); + + /* parse the port */ + if(ip_end != NULL) { + if((port_start = strchr(ip_end, ':')) != NULL) { + port_min = curlx_ultous(strtoul(port_start+1, NULL, 10)); + if((port_sep = strchr(port_start, '-')) != NULL) { + port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); + } + else + port_max = port_min; + } + } + + /* correct errors like: + * :1234-1230 + * :-4711 , in this case port_min is (unsigned)-1, + * therefore port_min > port_max for all cases + * but port_max = (unsigned)-1 + */ + if(port_min > port_max ) + port_min = port_max = 0; + + + if(*addr != '\0') { + /* attempt to get the address of the given interface name */ + switch(Curl_if2ip(conn->ip_addr->ai_family, + Curl_ipv6_scope(conn->ip_addr->ai_addr), + conn->scope_id, addr, hbuf, sizeof(hbuf))) { + case IF2IP_NOT_FOUND: + /* not an interface, use the given string as host name instead */ + host = addr; + break; + case IF2IP_AF_NOT_SUPPORTED: + return CURLE_FTP_PORT_FAILED; + case IF2IP_FOUND: + host = hbuf; /* use the hbuf for host name */ + } + } + else + /* there was only a port(-range) given, default the host */ + host = NULL; + } /* data->set.ftpport */ + + if(!host) { + /* not an interface and not a host name, get default by extracting + the IP from the control connection */ + + sslen = sizeof(ss); + if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(conn, SOCKERRNO) ); + free(addr); + return CURLE_FTP_PORT_FAILED; + } + switch(sa->sa_family) { +#ifdef ENABLE_IPV6 + case AF_INET6: + Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf)); + break; +#endif + default: + Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf)); + break; + } + host = hbuf; /* use this host name */ + possibly_non_local = FALSE; /* we know it is local now */ + } + + /* resolv ip/host to ip */ + rc = Curl_resolv(conn, host, 0, &h); + if(rc == CURLRESOLV_PENDING) + (void)Curl_resolver_wait_resolv(conn, &h); + if(h) { + res = h->addr; + /* when we return from this function, we can forget about this entry + to we can unlock it now already */ + Curl_resolv_unlock(data, h); + } /* (h) */ + else + res = NULL; /* failure! */ + + if(res == NULL) { + failf(data, "failed to resolve the address provided to PORT: %s", host); + free(addr); + return CURLE_FTP_PORT_FAILED; + } + + free(addr); + host = NULL; + + /* step 2, create a socket for the requested address */ + + portsock = CURL_SOCKET_BAD; + error = 0; + for(ai = res; ai; ai = ai->ai_next) { + result = Curl_socket(conn, ai, NULL, &portsock); + if(result) { + error = SOCKERRNO; + continue; + } + break; + } + if(!ai) { + failf(data, "socket failure: %s", Curl_strerror(conn, error)); + return CURLE_FTP_PORT_FAILED; + } + + /* step 3, bind to a suitable local address */ + + memcpy(sa, ai->ai_addr, ai->ai_addrlen); + sslen = ai->ai_addrlen; + + for(port = port_min; port <= port_max;) { + if(sa->sa_family == AF_INET) + sa4->sin_port = htons(port); +#ifdef ENABLE_IPV6 + else + sa6->sin6_port = htons(port); +#endif + /* Try binding the given address. */ + if(bind(portsock, sa, sslen) ) { + /* It failed. */ + error = SOCKERRNO; + if(possibly_non_local && (error == EADDRNOTAVAIL)) { + /* The requested bind address is not local. Use the address used for + * the control connection instead and restart the port loop + */ + + infof(data, "bind(port=%hu) on non-local address failed: %s\n", port, + Curl_strerror(conn, error) ); + + sslen = sizeof(ss); + if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(conn, SOCKERRNO) ); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + port = port_min; + possibly_non_local = FALSE; /* don't try this again */ + continue; + } + else if(error != EADDRINUSE && error != EACCES) { + failf(data, "bind(port=%hu) failed: %s", port, + Curl_strerror(conn, error) ); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + } + else + break; + + port++; + } + + /* maybe all ports were in use already*/ + if(port > port_max) { + failf(data, "bind() failed, we ran out of ports!"); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* get the name again after the bind() so that we can extract the + port number it uses now */ + sslen = sizeof(ss); + if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(conn, SOCKERRNO) ); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* step 4, listen on the socket */ + + if(listen(portsock, 1)) { + failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO)); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* step 5, send the proper FTP command */ + + /* get a plain printable version of the numerical address to work with + below */ + Curl_printable_address(ai, myhost, sizeof(myhost)); + +#ifdef ENABLE_IPV6 + if(!conn->bits.ftp_use_eprt && conn->bits.ipv6) + /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the + request and enable EPRT again! */ + conn->bits.ftp_use_eprt = TRUE; +#endif + + for(; fcmd != DONE; fcmd++) { + + if(!conn->bits.ftp_use_eprt && (EPRT == fcmd)) + /* if disabled, goto next */ + continue; + + if((PORT == fcmd) && sa->sa_family != AF_INET) + /* PORT is IPv4 only */ + continue; + + switch(sa->sa_family) { + case AF_INET: + port = ntohs(sa4->sin_port); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + port = ntohs(sa6->sin6_port); + break; +#endif + default: + continue; /* might as well skip this */ + } + + if(EPRT == fcmd) { + /* + * Two fine examples from RFC2428; + * + * EPRT |1|132.235.1.2|6275| + * + * EPRT |2|1080::8:800:200C:417A|5282| + */ + + result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd], + sa->sa_family == AF_INET?1:2, + myhost, port); + if(result) { + failf(data, "Failure sending EPRT command: %s", + curl_easy_strerror(result)); + Curl_closesocket(conn, portsock); + /* don't retry using PORT */ + ftpc->count1 = PORT; + /* bail out */ + state(conn, FTP_STOP); + return result; + } + break; + } + else if(PORT == fcmd) { + char *source = myhost; + char *dest = tmp; + + /* translate x.x.x.x to x,x,x,x */ + while(source && *source) { + if(*source == '.') + *dest=','; + else + *dest = *source; + dest++; + source++; + } + *dest = 0; + snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff)); + + result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp); + if(result) { + failf(data, "Failure sending PORT command: %s", + curl_easy_strerror(result)); + Curl_closesocket(conn, portsock); + /* bail out */ + state(conn, FTP_STOP); + return result; + } + break; + } + } + + /* store which command was sent */ + ftpc->count1 = fcmd; + + /* we set the secondary socket variable to this for now, it is only so that + the cleanup function will close it in case we fail before the true + secondary stuff is made */ + if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + conn->sock[SECONDARYSOCKET] = portsock; + + /* this tcpconnect assignment below is a hackish work-around to make the + multi interface with active FTP work - as it will not wait for a + (passive) connect in Curl_is_connected(). + + The *proper* fix is to make sure that the active connection from the + server is done in a non-blocking way. Currently, it is still BLOCKING. + */ + conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE; + + state(conn, FTP_PORT); + return result; +} + +static CURLcode ftp_state_use_pasv(struct connectdata *conn) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + /* + Here's the excecutive summary on what to do: + + PASV is RFC959, expect: + 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) + + LPSV is RFC1639, expect: + 228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2) + + EPSV is RFC2428, expect: + 229 Entering Extended Passive Mode (|||port|) + + */ + + static const char mode[][5] = { "EPSV", "PASV" }; + int modeoff; + +#ifdef PF_INET6 + if(!conn->bits.ftp_use_epsv && conn->bits.ipv6) + /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the + request and enable EPSV again! */ + conn->bits.ftp_use_epsv = TRUE; +#endif + + modeoff = conn->bits.ftp_use_epsv?0:1; + + PPSENDF(&ftpc->pp, "%s", mode[modeoff]); + + ftpc->count1 = modeoff; + state(conn, FTP_PASV); + infof(conn->data, "Connect data stream passively\n"); + + return result; +} + +/* + * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc. + * + * REST is the last command in the chain of commands when a "head"-like + * request is made. Thus, if an actual transfer is to be made this is where we + * take off for real. + */ +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct SessionHandle *data = conn->data; + + if(ftp->transfer != FTPTRANSFER_BODY) { + /* doesn't transfer any data */ + + /* still possibly do PRE QUOTE jobs */ + state(conn, FTP_RETR_PREQUOTE); + result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + } + else if(data->set.ftp_use_port) { + /* We have chosen to use the PORT (or similar) command */ + result = ftp_state_use_port(conn, EPRT); + } + else { + /* We have chosen (this is default) to use the PASV (or similar) command */ + if(data->set.ftp_use_pret) { + /* The user has requested that we send a PRET command + to prepare the server for the upcoming PASV */ + if(!conn->proto.ftpc.file) { + PPSENDF(&conn->proto.ftpc.pp, "PRET %s", + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->set.ftp_list_only?"NLST":"LIST")); + } + else if(data->set.upload) { + PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file); + } + else { + PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file); + } + state(conn, FTP_PRET); + } + else { + result = ftp_state_use_pasv(conn); + } + } + return result; +} + +static CURLcode ftp_state_rest(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { + /* if a "head"-like request is being made (on a file) */ + + /* Determine if server can respond to REST command and therefore + whether it supports range */ + PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0); + + state(conn, FTP_REST); + } + else + result = ftp_state_prepare_transfer(conn); + + return result; +} + +static CURLcode ftp_state_size(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { + /* if a "head"-like request is being made (on a file) */ + + /* we know ftpc->file is a valid pointer to a file name */ + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + + state(conn, FTP_SIZE); + } + else + result = ftp_state_rest(conn); + + return result; +} + +static CURLcode ftp_state_list(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + /* If this output is to be machine-parsed, the NLST command might be better + to use, since the LIST command output is not specified or standard in any + way. It has turned out that the NLST list output is not the same on all + servers either... */ + + /* + if FTPFILE_NOCWD was specified, we are currently in + the user's home directory, so we should add the path + as argument for the LIST / NLST / or custom command. + Whether the server will support this, is uncertain. + + The other ftp_filemethods will CWD into dir/dir/ first and + then just do LIST (in that case: nothing to do here) + */ + char *cmd, *lstArg, *slashPos; + + lstArg = NULL; + if((data->set.ftp_filemethod == FTPFILE_NOCWD) && + data->state.path && + data->state.path[0] && + strchr(data->state.path, '/')) { + + lstArg = strdup(data->state.path); + if(!lstArg) + return CURLE_OUT_OF_MEMORY; + + /* Check if path does not end with /, as then we cut off the file part */ + if(lstArg[strlen(lstArg) - 1] != '/') { + + /* chop off the file part if format is dir/dir/file */ + slashPos = strrchr(lstArg, '/'); + if(slashPos) + *(slashPos+1) = '\0'; + } + } + + cmd = aprintf( "%s%s%s", + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->set.ftp_list_only?"NLST":"LIST"), + lstArg? " ": "", + lstArg? lstArg: "" ); + + if(!cmd) { + free(lstArg); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd); + + free(lstArg); + free(cmd); + + if(result) + return result; + + state(conn, FTP_LIST); + + return result; +} + +static CURLcode ftp_state_retr_prequote(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* We've sent the TYPE, now we must send the list of prequote strings */ + + result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + + return result; +} + +static CURLcode ftp_state_stor_prequote(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* We've sent the TYPE, now we must send the list of prequote strings */ + + result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE); + + return result; +} + +static CURLcode ftp_state_type(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct SessionHandle *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + /* If we have selected NOBODY and HEADER, it means that we only want file + information. Which in FTP can't be much more than the file size and + date. */ + if(data->set.opt_no_body && ftpc->file && + ftp_need_type(conn, data->set.prefer_ascii)) { + /* The SIZE command is _not_ RFC 959 specified, and therefor many servers + may not support it! It is however the only way we have to get a file's + size! */ + + ftp->transfer = FTPTRANSFER_INFO; + /* this means no actual transfer will be made */ + + /* Some servers return different sizes for different modes, and thus we + must set the proper type before we check the size */ + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE); + if(result) + return result; + } + else + result = ftp_state_size(conn); + + return result; +} + +/* This is called after the CWD commands have been done in the beginning of + the DO phase */ +static CURLcode ftp_state_mdtm(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + /* Requested time of file or time-depended transfer? */ + if((data->set.get_filetime || data->set.timecondition) && ftpc->file) { + + /* we have requested to get the modified-time of the file, this is a white + spot as the MDTM is not mentioned in RFC959 */ + PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file); + + state(conn, FTP_MDTM); + } + else + result = ftp_state_type(conn); + + return result; +} + + +/* This is called after the TYPE and possible quote commands have been sent */ +static CURLcode ftp_state_ul_setup(struct connectdata *conn, + bool sizechecked) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct SessionHandle *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + int seekerr = CURL_SEEKFUNC_OK; + + if((data->state.resume_from && !sizechecked) || + ((data->state.resume_from > 0) && sizechecked)) { + /* we're about to continue the uploading of a file */ + /* 1. get already existing file's size. We use the SIZE command for this + which may not exist in the server! The SIZE command is not in + RFC959. */ + + /* 2. This used to set REST. But since we can do append, we + don't another ftp command. We just skip the source file + offset and then we APPEND the rest on the file instead */ + + /* 3. pass file-size number of bytes in the source file */ + /* 4. lower the infilesize counter */ + /* => transfer as usual */ + + if(data->state.resume_from < 0 ) { + /* Got no given size to start from, figure it out */ + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + state(conn, FTP_STOR_SIZE); + return result; + } + + /* enable append */ + data->set.ftp_append = TRUE; + + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + else { + curl_off_t passed=0; + do { + size_t readthisamountnow = + (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? + BUFSIZE : curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + conn->fread_func(data->state.buffer, 1, readthisamountnow, + conn->fread_in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); + } + } + /* now, decrease the size of the read */ + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; + + if(data->state.infilesize <= 0) { + infof(data, "File already completely uploaded\n"); + + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + + /* Set ->transfer so that we won't get any error in + * ftp_done() because we didn't transfer anything! */ + ftp->transfer = FTPTRANSFER_NONE; + + state(conn, FTP_STOP); + return CURLE_OK; + } + } + /* we've passed, proceed as normal */ + } /* resume_from */ + + PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s", + ftpc->file); + + state(conn, FTP_STOR); + + return result; +} + +static CURLcode ftp_state_quote(struct connectdata *conn, + bool init, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + bool quote=FALSE; + struct curl_slist *item; + + switch(instate) { + case FTP_QUOTE: + default: + item = data->set.quote; + break; + case FTP_RETR_PREQUOTE: + case FTP_STOR_PREQUOTE: + item = data->set.prequote; + break; + case FTP_POSTQUOTE: + item = data->set.postquote; + break; + } + + /* + * This state uses: + * 'count1' to iterate over the commands to send + * 'count2' to store wether to allow commands to fail + */ + + if(init) + ftpc->count1 = 0; + else + ftpc->count1++; + + if(item) { + int i = 0; + + /* Skip count1 items in the linked list */ + while((i< ftpc->count1) && item) { + item = item->next; + i++; + } + if(item) { + char *cmd = item->data; + if(cmd[0] == '*') { + cmd++; + ftpc->count2 = 1; /* the sent command is allowed to fail */ + } + else + ftpc->count2 = 0; /* failure means cancel operation */ + + PPSENDF(&ftpc->pp, "%s", cmd); + state(conn, instate); + quote = TRUE; + } + } + + if(!quote) { + /* No more quote to send, continue to ... */ + switch(instate) { + case FTP_QUOTE: + default: + result = ftp_state_cwd(conn); + break; + case FTP_RETR_PREQUOTE: + if(ftp->transfer != FTPTRANSFER_BODY) + state(conn, FTP_STOP); + else { + if(ftpc->known_filesize != -1) { + Curl_pgrsSetDownloadSize(data, ftpc->known_filesize); + result = ftp_state_retr(conn, ftpc->known_filesize); + } + else { + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + state(conn, FTP_RETR_SIZE); + } + } + break; + case FTP_STOR_PREQUOTE: + result = ftp_state_ul_setup(conn, FALSE); + break; + case FTP_POSTQUOTE: + break; + } + } + + return result; +} + +/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV + problems */ +static CURLcode ftp_epsv_disable(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->bits.ipv6) { + /* We can't disable EPSV when doing IPv6, so this is instead a fail */ + failf(conn->data, "Failed EPSV attempt, exiting\n"); + return CURLE_FTP_WEIRD_SERVER_REPLY; + } + + infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n"); + /* disable it for next transfer */ + conn->bits.ftp_use_epsv = FALSE; + conn->data->state.errorbuf = FALSE; /* allow error message to get + rewritten */ + PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV"); + conn->proto.ftpc.count1++; + /* remain in/go to the FTP_PASV state */ + state(conn, FTP_PASV); + return result; +} + +/* + * Perform the necessary magic that needs to be done once the TCP connection + * to the proxy has completed. + */ +static CURLcode proxy_magic(struct connectdata *conn, + char *newhost, unsigned short newport, + bool *magicdone) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + +#if defined(CURL_DISABLE_PROXY) + (void) newhost; + (void) newport; +#endif + + *magicdone = FALSE; + + switch(conn->proxytype) { + case CURLPROXY_SOCKS5: + case CURLPROXY_SOCKS5_HOSTNAME: + result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, + newport, SECONDARYSOCKET, conn); + *magicdone = TRUE; + break; + case CURLPROXY_SOCKS4: + result = Curl_SOCKS4(conn->proxyuser, newhost, newport, + SECONDARYSOCKET, conn, FALSE); + *magicdone = TRUE; + break; + case CURLPROXY_SOCKS4A: + result = Curl_SOCKS4(conn->proxyuser, newhost, newport, + SECONDARYSOCKET, conn, TRUE); + *magicdone = TRUE; + break; + case CURLPROXY_HTTP: + case CURLPROXY_HTTP_1_0: + /* do nothing here. handled later. */ + break; + default: + failf(data, "unknown proxytype option given"); + result = CURLE_COULDNT_CONNECT; + break; + } + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { + /* BLOCKING */ + /* We want "seamless" FTP operations through HTTP proxy tunnel */ + + /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the + * member conn->proto.http; we want FTP through HTTP and we have to + * change the member temporarily for connecting to the HTTP proxy. After + * Curl_proxyCONNECT we have to set back the member to the original + * struct FTP pointer + */ + struct HTTP http_proxy; + struct FTP *ftp_save = data->req.protop; + memset(&http_proxy, 0, sizeof(http_proxy)); + data->req.protop = &http_proxy; + + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); + + data->req.protop = ftp_save; + + if(result) + return result; + + if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) { + /* the CONNECT procedure is not complete, the tunnel is not yet up */ + state(conn, FTP_STOP); /* this phase is completed */ + return result; + } + else + *magicdone = TRUE; + } + + return result; +} + +static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + int ftpcode) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result; + struct SessionHandle *data=conn->data; + struct Curl_dns_entry *addr=NULL; + int rc; + unsigned short connectport; /* the local port connect() should use! */ + char *str=&data->state.buffer[4]; /* start on the first letter */ + + /* if we come here again, make sure the former name is cleared */ + Curl_safefree(ftpc->newhost); + + if((ftpc->count1 == 0) && + (ftpcode == 229)) { + /* positive EPSV response */ + char *ptr = strchr(str, '('); + if(ptr) { + unsigned int num; + char separator[4]; + ptr++; + if(5 == sscanf(ptr, "%c%c%c%u%c", + &separator[0], + &separator[1], + &separator[2], + &num, + &separator[3])) { + const char sep1 = separator[0]; + int i; + + /* The four separators should be identical, or else this is an oddly + formatted reply and we bail out immediately. */ + for(i=1; i<4; i++) { + if(separator[i] != sep1) { + ptr=NULL; /* set to NULL to signal error */ + break; + } + } + if(num > 0xffff) { + failf(data, "Illegal port number in EPSV reply"); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + if(ptr) { + ftpc->newport = (unsigned short)(num & 0xffff); + + /* use the original host name again */ + ftpc->newhost = strdup(conn->host.name); + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + } + } + else + ptr=NULL; + } + if(!ptr) { + failf(data, "Weirdly formatted EPSV reply"); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + } + else if((ftpc->count1 == 1) && + (ftpcode == 227)) { + /* positive PASV response */ + int ip[4]; + int port[2]; + + /* + * Scan for a sequence of six comma-separated numbers and use them as + * IP+port indicators. + * + * Found reply-strings include: + * "227 Entering Passive Mode (127,0,0,1,4,51)" + * "227 Data transfer will passively listen to 127,0,0,1,4,51" + * "227 Entering passive mode. 127,0,0,1,4,51" + */ + while(*str) { + if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d", + &ip[0], &ip[1], &ip[2], &ip[3], + &port[0], &port[1])) + break; + str++; + } + + if(!*str) { + failf(data, "Couldn't interpret the 227-response"); + return CURLE_FTP_WEIRD_227_FORMAT; + } + + /* we got OK from server */ + if(data->set.ftp_skip_ip) { + /* told to ignore the remotely given IP but instead use the host we used + for the control connection */ + infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n", + ip[0], ip[1], ip[2], ip[3], + conn->host.name); + + /* use the original host name again */ + ftpc->newhost = strdup(conn->host.name); + } + else + ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + + ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); + } + else if(ftpc->count1 == 0) { + /* EPSV failed, move on to PASV */ + return ftp_epsv_disable(conn); + } + else { + failf(data, "Bad PASV/EPSV response: %03d", ftpcode); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + + if(conn->bits.proxy) { + /* + * This connection uses a proxy and we need to connect to the proxy again + * here. We don't want to rely on a former host lookup that might've + * expired now, instead we remake the lookup here and now! + */ + rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING, ignores the return code but 'addr' will be NULL in + case of failure */ + (void)Curl_resolver_wait_resolv(conn, &addr); + + connectport = + (unsigned short)conn->port; /* we connect to the proxy's port */ + + if(!addr) { + failf(data, "Can't resolve proxy host %s:%hu", + conn->proxy.name, connectport); + return CURLE_FTP_CANT_GET_HOST; + } + } + else { + /* normal, direct, ftp connection */ + rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING */ + (void)Curl_resolver_wait_resolv(conn, &addr); + + connectport = ftpc->newport; /* we connect to the remote port */ + + if(!addr) { + failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport); + return CURLE_FTP_CANT_GET_HOST; + } + } + + conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; + result = Curl_connecthost(conn, addr); + + Curl_resolv_unlock(data, addr); /* we're done using this address */ + + if(result) { + if(ftpc->count1 == 0 && ftpcode == 229) + return ftp_epsv_disable(conn); + + return result; + } + + + /* + * When this is used from the multi interface, this might've returned with + * the 'connected' set to FALSE and thus we are now awaiting a non-blocking + * connect to connect. + */ + + if(data->set.verbose) + /* this just dumps information about this second connection */ + ftp_pasv_verbose(conn, conn->ip_addr, ftpc->newhost, connectport); + + conn->bits.do_more = TRUE; + state(conn, FTP_STOP); /* this phase is completed */ + + return result; +} + +static CURLcode ftp_state_port_resp(struct connectdata *conn, + int ftpcode) +{ + struct SessionHandle *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + ftpport fcmd = (ftpport)ftpc->count1; + CURLcode result = CURLE_OK; + + /* The FTP spec tells a positive response should have code 200. + Be more permissive here to tolerate deviant servers. */ + if(ftpcode / 100 != 2) { + /* the command failed */ + + if(EPRT == fcmd) { + infof(data, "disabling EPRT usage\n"); + conn->bits.ftp_use_eprt = FALSE; + } + fcmd++; + + if(fcmd == DONE) { + failf(data, "Failed to do PORT"); + result = CURLE_FTP_PORT_FAILED; + } + else + /* try next */ + result = ftp_state_use_port(conn, fcmd); + } + else { + infof(data, "Connect data stream actively\n"); + state(conn, FTP_STOP); /* end of DO phase */ + result = ftp_dophase_done(conn, FALSE); + } + + return result; +} + +static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, + int ftpcode) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data=conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + switch(ftpcode) { + case 213: + { + /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the + last .sss part is optional and means fractions of a second */ + int year, month, day, hour, minute, second; + char *buf = data->state.buffer; + if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d", + &year, &month, &day, &hour, &minute, &second)) { + /* we have a time, reformat it */ + time_t secs=time(NULL); + /* using the good old yacc/bison yuck */ + snprintf(buf, sizeof(conn->data->state.buffer), + "%04d%02d%02d %02d:%02d:%02d GMT", + year, month, day, hour, minute, second); + /* now, convert this into a time() value: */ + data->info.filetime = (long)curl_getdate(buf, &secs); + } + +#ifdef CURL_FTP_HTTPSTYLE_HEAD + /* If we asked for a time of the file and we actually got one as well, + we "emulate" a HTTP-style header in our output. */ + + if(data->set.opt_no_body && + ftpc->file && + data->set.get_filetime && + (data->info.filetime>=0) ) { + time_t filetime = (time_t)data->info.filetime; + struct tm buffer; + const struct tm *tm = &buffer; + + result = Curl_gmtime(filetime, &buffer); + if(result) + return result; + + /* format: "Tue, 15 Nov 1994 12:45:26" */ + snprintf(buf, BUFSIZE-1, + "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); + if(result) + return result; + } /* end of a ridiculous amount of conditionals */ +#endif + } + break; + default: + infof(data, "unsupported MDTM reply format\n"); + break; + case 550: /* "No such file or directory" */ + failf(data, "Given file does not exist"); + result = CURLE_FTP_COULDNT_RETR_FILE; + break; + } + + if(data->set.timecondition) { + if((data->info.filetime > 0) && (data->set.timevalue > 0)) { + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + if(data->info.filetime <= data->set.timevalue) { + infof(data, "The requested document is not new enough\n"); + ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + data->info.timecond = TRUE; + state(conn, FTP_STOP); + return CURLE_OK; + } + break; + case CURL_TIMECOND_IFUNMODSINCE: + if(data->info.filetime > data->set.timevalue) { + infof(data, "The requested document is not old enough\n"); + ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + data->info.timecond = TRUE; + state(conn, FTP_STOP); + return CURLE_OK; + } + break; + } /* switch */ + } + else { + infof(data, "Skipping time comparison\n"); + } + } + + if(!result) + result = ftp_state_type(conn); + + return result; +} + +static CURLcode ftp_state_type_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data=conn->data; + + if(ftpcode/100 != 2) { + /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a + successful 'TYPE I'. While that is not as RFC959 says, it is still a + positive response code and we allow that. */ + failf(data, "Couldn't set desired mode"); + return CURLE_FTP_COULDNT_SET_TYPE; + } + if(ftpcode != 200) + infof(data, "Got a %03d response code instead of the assumed 200\n", + ftpcode); + + if(instate == FTP_TYPE) + result = ftp_state_size(conn); + else if(instate == FTP_LIST_TYPE) + result = ftp_state_list(conn); + else if(instate == FTP_RETR_TYPE) + result = ftp_state_retr_prequote(conn); + else if(instate == FTP_STOR_TYPE) + result = ftp_state_stor_prequote(conn); + + return result; +} + +static CURLcode ftp_state_retr(struct connectdata *conn, + curl_off_t filesize) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data=conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(data->set.max_filesize && (filesize > data->set.max_filesize)) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + ftp->downloadsize = filesize; + + if(data->state.resume_from) { + /* We always (attempt to) get the size of downloads, so it is done before + this even when not doing resumes. */ + if(filesize == -1) { + infof(data, "ftp server doesn't support SIZE\n"); + /* We couldn't get the size and therefore we can't know if there really + is a part of the file left to get, although the server will just + close the connection when we start the connection so it won't cause + us any harm, just not make us exit as nicely. */ + } + else { + /* We got a file size report, so we check that there actually is a + part of the file left to get, or else we go home. */ + if(data->state.resume_from< 0) { + /* We're supposed to download the last abs(from) bytes */ + if(filesize < -data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* convert to size to download */ + ftp->downloadsize = -data->state.resume_from; + /* download from where? */ + data->state.resume_from = filesize - ftp->downloadsize; + } + else { + if(filesize < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* Now store the number of bytes we are expected to download */ + ftp->downloadsize = filesize-data->state.resume_from; + } + } + + if(ftp->downloadsize == 0) { + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + infof(data, "File already completely downloaded\n"); + + /* Set ->transfer so that we won't get any error in ftp_done() + * because we didn't transfer the any file */ + ftp->transfer = FTPTRANSFER_NONE; + state(conn, FTP_STOP); + return CURLE_OK; + } + + /* Set resume file transfer offset */ + infof(data, "Instructs server to resume from offset %" + CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); + + PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T, + data->state.resume_from); + + state(conn, FTP_RETR_REST); + } + else { + /* no resume */ + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + + return result; +} + +static CURLcode ftp_state_size_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data=conn->data; + curl_off_t filesize; + char *buf = data->state.buffer; + + /* get the size from the ascii string: */ + filesize = (ftpcode == 213)?curlx_strtoofft(buf+4, NULL, 0):-1; + + if(instate == FTP_SIZE) { +#ifdef CURL_FTP_HTTPSTYLE_HEAD + if(-1 != filesize) { + snprintf(buf, sizeof(data->state.buffer), + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); + if(result) + return result; + } +#endif + Curl_pgrsSetDownloadSize(data, filesize); + result = ftp_state_rest(conn); + } + else if(instate == FTP_RETR_SIZE) { + Curl_pgrsSetDownloadSize(data, filesize); + result = ftp_state_retr(conn, filesize); + } + else if(instate == FTP_STOR_SIZE) { + data->state.resume_from = filesize; + result = ftp_state_ul_setup(conn, TRUE); + } + + return result; +} + +static CURLcode ftp_state_rest_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + switch(instate) { + case FTP_REST: + default: +#ifdef CURL_FTP_HTTPSTYLE_HEAD + if(ftpcode == 350) { + char buffer[24]= { "Accept-ranges: bytes\r\n" }; + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0); + if(result) + return result; + } +#endif + result = ftp_state_prepare_transfer(conn); + break; + + case FTP_RETR_REST: + if(ftpcode != 350) { + failf(conn->data, "Couldn't use REST"); + result = CURLE_FTP_COULDNT_USE_REST; + } + else { + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + break; + } + + return result; +} + +static CURLcode ftp_state_stor_resp(struct connectdata *conn, + int ftpcode, ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + if(ftpcode>=400) { + failf(data, "Failed FTP upload: %0d", ftpcode); + state(conn, FTP_STOP); + /* oops, we never close the sockets! */ + return CURLE_UPLOAD_FAILED; + } + + conn->proto.ftpc.state_saved = instate; + + /* PORT means we are now awaiting the server to connect to us. */ + if(data->set.ftp_use_port) { + bool connected; + + state(conn, FTP_STOP); /* no longer in STOR state */ + + result = AllowServerConnect(conn, &connected); + if(result) + return result; + + if(!connected) { + struct ftp_conn *ftpc = &conn->proto.ftpc; + infof(data, "Data conn was not available immediately\n"); + ftpc->wait_data_conn = TRUE; + } + + return CURLE_OK; + } + else + return InitiateTransfer(conn); +} + +/* for LIST and RETR responses */ +static CURLcode ftp_state_get_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct FTP *ftp = data->req.protop; + char *buf = data->state.buffer; + + if((ftpcode == 150) || (ftpcode == 125)) { + + /* + A; + 150 Opening BINARY mode data connection for /etc/passwd (2241 + bytes). (ok, the file is being transferred) + + B: + 150 Opening ASCII mode data connection for /bin/ls + + C: + 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes). + + D: + 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes) + + E: + 125 Data connection already open; Transfer starting. */ + + curl_off_t size=-1; /* default unknown size */ + + + /* + * It appears that there are FTP-servers that return size 0 for files when + * SIZE is used on the file while being in BINARY mode. To work around + * that (stupid) behavior, we attempt to parse the RETR response even if + * the SIZE returned size zero. + * + * Debugging help from Salvatore Sorrentino on February 26, 2003. + */ + + if((instate != FTP_LIST) && + !data->set.prefer_ascii && + (ftp->downloadsize < 1)) { + /* + * It seems directory listings either don't show the size or very + * often uses size 0 anyway. ASCII transfers may very well turn out + * that the transferred amount of data is not the same as this line + * tells, why using this number in those cases only confuses us. + * + * Example D above makes this parsing a little tricky */ + char *bytes; + bytes=strstr(buf, " bytes"); + if(bytes--) { + long in=(long)(bytes-buf); + /* this is a hint there is size information in there! ;-) */ + while(--in) { + /* scan for the left parenthesis and break there */ + if('(' == *bytes) + break; + /* skip only digits */ + if(!ISDIGIT(*bytes)) { + bytes=NULL; + break; + } + /* one more estep backwards */ + bytes--; + } + /* if we have nothing but digits: */ + if(bytes++) { + /* get the number! */ + size = curlx_strtoofft(bytes, NULL, 0); + } + } + } + else if(ftp->downloadsize > -1) + size = ftp->downloadsize; + + if(size > data->req.maxdownload && data->req.maxdownload > 0) + size = data->req.size = data->req.maxdownload; + else if((instate != FTP_LIST) && (data->set.prefer_ascii)) + size = -1; /* kludge for servers that understate ASCII mode file size */ + + infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n", + data->req.maxdownload); + + if(instate != FTP_LIST) + infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n", + size); + + /* FTP download: */ + conn->proto.ftpc.state_saved = instate; + conn->proto.ftpc.retr_size_saved = size; + + if(data->set.ftp_use_port) { + bool connected; + + result = AllowServerConnect(conn, &connected); + if(result) + return result; + + if(!connected) { + struct ftp_conn *ftpc = &conn->proto.ftpc; + infof(data, "Data conn was not available immediately\n"); + state(conn, FTP_STOP); + ftpc->wait_data_conn = TRUE; + } + } + else + return InitiateTransfer(conn); + } + else { + if((instate == FTP_LIST) && (ftpcode == 450)) { + /* simply no matching files in the dir listing */ + ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */ + state(conn, FTP_STOP); /* this phase is over */ + } + else { + failf(data, "RETR response: %03d", ftpcode); + return instate == FTP_RETR && ftpcode == 550? + CURLE_REMOTE_FILE_NOT_FOUND: + CURLE_FTP_COULDNT_RETR_FILE; + } + } + + return result; +} + +/* after USER, PASS and ACCT */ +static CURLcode ftp_state_loggedin(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->ssl[FIRSTSOCKET].use) { + /* PBSZ = PROTECTION BUFFER SIZE. + + The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says: + + Specifically, the PROT command MUST be preceded by a PBSZ + command and a PBSZ command MUST be preceded by a successful + security data exchange (the TLS negotiation in this case) + + ... (and on page 8): + + Thus the PBSZ command must still be issued, but must have a + parameter of '0' to indicate that no buffering is taking place + and the data connection should not be encapsulated. + */ + PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0); + state(conn, FTP_PBSZ); + } + else { + result = ftp_state_pwd(conn); + } + return result; +} + +/* for USER and PASS responses */ +static CURLcode ftp_state_user_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + (void)instate; /* no use for this yet */ + + /* some need password anyway, and others just return 2xx ignored */ + if((ftpcode == 331) && (ftpc->state == FTP_USER)) { + /* 331 Password required for ... + (the server requires to send the user's password too) */ + PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:""); + state(conn, FTP_PASS); + } + else if(ftpcode/100 == 2) { + /* 230 User ... logged in. + (the user logged in with or without password) */ + result = ftp_state_loggedin(conn); + } + else if(ftpcode == 332) { + if(data->set.str[STRING_FTP_ACCOUNT]) { + PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]); + state(conn, FTP_ACCT); + } + else { + failf(data, "ACCT requested but none available"); + result = CURLE_LOGIN_DENIED; + } + } + else { + /* All other response codes, like: + + 530 User ... access denied + (the server denies to log the specified user) */ + + if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && + !conn->data->state.ftp_trying_alternative) { + /* Ok, USER failed. Let's try the supplied command. */ + PPSENDF(&conn->proto.ftpc.pp, "%s", + conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); + conn->data->state.ftp_trying_alternative = TRUE; + state(conn, FTP_USER); + result = CURLE_OK; + } + else { + failf(data, "Access denied: %03d", ftpcode); + result = CURLE_LOGIN_DENIED; + } + } + return result; +} + +/* for ACCT response */ +static CURLcode ftp_state_acct_resp(struct connectdata *conn, + int ftpcode) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + if(ftpcode != 230) { + failf(data, "ACCT rejected by server: %03d", ftpcode); + result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */ + } + else + result = ftp_state_loggedin(conn); + + return result; +} + + +static CURLcode ftp_statemach_act(struct connectdata *conn) +{ + CURLcode result; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct SessionHandle *data=conn->data; + int ftpcode; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + static const char ftpauth[][4] = { "SSL", "TLS" }; + size_t nread = 0; + + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + result = ftp_readresp(sock, pp, &ftpcode, &nread); + if(result) + return result; + + if(ftpcode) { + /* we have now received a full FTP server response */ + switch(ftpc->state) { + case FTP_WAIT220: + if(ftpcode == 230) + /* 230 User logged in - already! */ + return ftp_state_user_resp(conn, ftpcode, ftpc->state); + else if(ftpcode != 220) { + failf(data, "Got a %03d ftp-server response when 220 was expected", + ftpcode); + return CURLE_FTP_WEIRD_SERVER_REPLY; + } + + /* We have received a 220 response fine, now we proceed. */ +#ifdef HAVE_GSSAPI + if(data->set.krb) { + /* If not anonymous login, try a secure login. Note that this + procedure is still BLOCKING. */ + + Curl_sec_request_prot(conn, "private"); + /* We set private first as default, in case the line below fails to + set a valid level */ + Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); + + if(Curl_sec_login(conn)) + infof(data, "Logging in with password in cleartext!\n"); + else + infof(data, "Authentication successful\n"); + } +#endif + + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but FTPS is + requested. Try a FTPS connection now */ + + ftpc->count3=0; + switch(data->set.ftpsslauth) { + case CURLFTPAUTH_DEFAULT: + case CURLFTPAUTH_SSL: + ftpc->count2 = 1; /* add one to get next */ + ftpc->count1 = 0; + break; + case CURLFTPAUTH_TLS: + ftpc->count2 = -1; /* subtract one to get next */ + ftpc->count1 = 1; + break; + default: + failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d", + (int)data->set.ftpsslauth); + return CURLE_UNKNOWN_OPTION; /* we don't know what to do */ + } + PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + state(conn, FTP_AUTH); + } + else { + result = ftp_state_user(conn); + if(result) + return result; + } + + break; + + case FTP_AUTH: + /* we have gotten the response to a previous AUTH command */ + + /* RFC2228 (page 5) says: + * + * If the server is willing to accept the named security mechanism, + * and does not require any security data, it must respond with + * reply code 234/334. + */ + + if((ftpcode == 234) || (ftpcode == 334)) { + /* Curl_ssl_connect is BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(!result) { + conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */ + result = ftp_state_user(conn); + } + } + else if(ftpc->count3 < 1) { + ftpc->count3++; + ftpc->count1 += ftpc->count2; /* get next attempt */ + result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + /* remain in this same state */ + } + else { + if(data->set.use_ssl > CURLUSESSL_TRY) + /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */ + result = CURLE_USE_SSL_FAILED; + else + /* ignore the failure and continue */ + result = ftp_state_user(conn); + } + + if(result) + return result; + break; + + case FTP_USER: + case FTP_PASS: + result = ftp_state_user_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_ACCT: + result = ftp_state_acct_resp(conn, ftpcode); + break; + + case FTP_PBSZ: + PPSENDF(&ftpc->pp, "PROT %c", + data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P'); + state(conn, FTP_PROT); + + break; + + case FTP_PROT: + if(ftpcode/100 == 2) + /* We have enabled SSL for the data connection! */ + conn->ssl[SECONDARYSOCKET].use = + (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE; + /* FTP servers typically responds with 500 if they decide to reject + our 'P' request */ + else if(data->set.use_ssl > CURLUSESSL_CONTROL) + /* we failed and bails out */ + return CURLE_USE_SSL_FAILED; + + if(data->set.ftp_ccc) { + /* CCC - Clear Command Channel + */ + PPSENDF(&ftpc->pp, "%s", "CCC"); + state(conn, FTP_CCC); + } + else { + result = ftp_state_pwd(conn); + if(result) + return result; + } + break; + + case FTP_CCC: + if(ftpcode < 500) { + /* First shut down the SSL layer (note: this call will block) */ + result = Curl_ssl_shutdown(conn, FIRSTSOCKET); + + if(result) { + failf(conn->data, "Failed to clear the command channel (CCC)"); + return result; + } + } + + /* Then continue as normal */ + result = ftp_state_pwd(conn); + if(result) + return result; + break; + + case FTP_PWD: + if(ftpcode == 257) { + char *ptr=&data->state.buffer[4]; /* start on the first letter */ + char *dir; + char *store; + + dir = malloc(nread + 1); + if(!dir) + return CURLE_OUT_OF_MEMORY; + + /* Reply format is like + 257[rubbish]"" and the + RFC959 says + + The directory name can contain any character; embedded + double-quotes should be escaped by double-quotes (the + "quote-doubling" convention). + */ + + /* scan for the first double-quote for non-standard responses */ + while(ptr < &data->state.buffer[sizeof(data->state.buffer)] + && *ptr != '\n' && *ptr != '\0' && *ptr != '"') + ptr++; + + if('\"' == *ptr) { + /* it started good */ + ptr++; + for(store = dir; *ptr;) { + if('\"' == *ptr) { + if('\"' == ptr[1]) { + /* "quote-doubling" */ + *store = ptr[1]; + ptr++; + } + else { + /* end of path */ + *store = '\0'; /* zero terminate */ + break; /* get out of this loop */ + } + } + else + *store = *ptr; + store++; + ptr++; + } + + /* If the path name does not look like an absolute path (i.e.: it + does not start with a '/'), we probably need some server-dependent + adjustments. For example, this is the case when connecting to + an OS400 FTP server: this server supports two name syntaxes, + the default one being incompatible with standard pathes. In + addition, this server switches automatically to the regular path + syntax when one is encountered in a command: this results in + having an entrypath in the wrong syntax when later used in CWD. + The method used here is to check the server OS: we do it only + if the path name looks strange to minimize overhead on other + systems. */ + + if(!ftpc->server_os && dir[0] != '/') { + + result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST"); + if(result) { + free(dir); + return result; + } + Curl_safefree(ftpc->entrypath); + ftpc->entrypath = dir; /* remember this */ + infof(data, "Entry path is '%s'\n", ftpc->entrypath); + /* also save it where getinfo can access it: */ + data->state.most_recent_ftp_entrypath = ftpc->entrypath; + state(conn, FTP_SYST); + break; + } + + Curl_safefree(ftpc->entrypath); + ftpc->entrypath = dir; /* remember this */ + infof(data, "Entry path is '%s'\n", ftpc->entrypath); + /* also save it where getinfo can access it: */ + data->state.most_recent_ftp_entrypath = ftpc->entrypath; + } + else { + /* couldn't get the path */ + free(dir); + infof(data, "Failed to figure out path\n"); + } + } + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_SYST: + if(ftpcode == 215) { + char *ptr=&data->state.buffer[4]; /* start on the first letter */ + char *os; + char *store; + + os = malloc(nread + 1); + if(!os) + return CURLE_OUT_OF_MEMORY; + + /* Reply format is like + 215 + */ + while(*ptr == ' ') + ptr++; + for(store = os; *ptr && *ptr != ' ';) + *store++ = *ptr++; + *store = '\0'; /* zero terminate */ + + /* Check for special servers here. */ + + if(strequal(os, "OS/400")) { + /* Force OS400 name format 1. */ + result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1"); + if(result) { + free(os); + return result; + } + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; + state(conn, FTP_NAMEFMT); + break; + } + else { + /* Nothing special for the target server. */ + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; + } + } + else { + /* Cannot identify server OS. Continue anyway and cross fingers. */ + } + + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_NAMEFMT: + if(ftpcode == 250) { + /* Name format change successful: reload initial path. */ + ftp_state_pwd(conn); + break; + } + + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_QUOTE: + case FTP_POSTQUOTE: + case FTP_RETR_PREQUOTE: + case FTP_STOR_PREQUOTE: + if((ftpcode >= 400) && !ftpc->count2) { + /* failure response code, and not allowed to fail */ + failf(conn->data, "QUOT command failed with %03d", ftpcode); + return CURLE_QUOTE_ERROR; + } + result = ftp_state_quote(conn, FALSE, ftpc->state); + if(result) + return result; + + break; + + case FTP_CWD: + if(ftpcode/100 != 2) { + /* failure to CWD there */ + if(conn->data->set.ftp_create_missing_dirs && + ftpc->count1 && !ftpc->count2) { + /* try making it */ + ftpc->count2++; /* counter to prevent CWD-MKD loops */ + PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->count1 - 1]); + state(conn, FTP_MKD); + } + else { + /* return failure */ + failf(data, "Server denied you to change to the given directory"); + ftpc->cwdfail = TRUE; /* don't remember this path as we failed + to enter it */ + return CURLE_REMOTE_ACCESS_DENIED; + } + } + else { + /* success */ + ftpc->count2=0; + if(++ftpc->count1 <= ftpc->dirdepth) { + /* send next CWD */ + PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]); + } + else { + result = ftp_state_mdtm(conn); + if(result) + return result; + } + } + break; + + case FTP_MKD: + if((ftpcode/100 != 2) && !ftpc->count3--) { + /* failure to MKD the dir */ + failf(data, "Failed to MKD dir: %03d", ftpcode); + return CURLE_REMOTE_ACCESS_DENIED; + } + state(conn, FTP_CWD); + /* send CWD */ + PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]); + break; + + case FTP_MDTM: + result = ftp_state_mdtm_resp(conn, ftpcode); + break; + + case FTP_TYPE: + case FTP_LIST_TYPE: + case FTP_RETR_TYPE: + case FTP_STOR_TYPE: + result = ftp_state_type_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_SIZE: + case FTP_RETR_SIZE: + case FTP_STOR_SIZE: + result = ftp_state_size_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_REST: + case FTP_RETR_REST: + result = ftp_state_rest_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_PRET: + if(ftpcode != 200) { + /* there only is this one standard OK return code. */ + failf(data, "PRET command not accepted: %03d", ftpcode); + return CURLE_FTP_PRET_FAILED; + } + result = ftp_state_use_pasv(conn); + break; + + case FTP_PASV: + result = ftp_state_pasv_resp(conn, ftpcode); + break; + + case FTP_PORT: + result = ftp_state_port_resp(conn, ftpcode); + break; + + case FTP_LIST: + case FTP_RETR: + result = ftp_state_get_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_STOR: + result = ftp_state_stor_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, FTP_STOP); + break; + } + } /* if(ftpcode) */ + + return result; +} + + +/* called repeatedly until done from multi.c */ +static CURLcode ftp_multi_statemach(struct connectdata *conn, + bool *done) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE); + + /* Check for the state outside of the Curl_socket_ready() return code checks + since at times we are in fact already in this state when this function + gets called. */ + *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode ftp_block_statemach(struct connectdata *conn) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + CURLcode result = CURLE_OK; + + while(ftpc->state != FTP_STOP) { + result = Curl_pp_statemach(pp, TRUE); + if(result) + break; + } + + return result; +} + +/* + * ftp_connect() should do everything that is to be considered a part of + * the connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + * + */ +static CURLcode ftp_connect(struct connectdata *conn, + bool *done) /* see description above */ +{ + CURLcode result; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections on ftp */ + connkeep(conn, "FTP default"); + + pp->response_time = RESP_TIMEOUT; /* set default response time-out */ + pp->statemach_act = ftp_statemach_act; + pp->endofresp = ftp_endofresp; + pp->conn = conn; + + if(conn->handler->flags & PROTOPT_SSL) { + /* BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(result) + return result; + } + + Curl_pp_init(pp); /* init the generic pingpong data */ + + /* When we connect, we start in the state where we await the 220 + response */ + state(conn, FTP_WAIT220); + + result = ftp_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * ftp_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode ftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct SessionHandle *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + ssize_t nread; + int ftpcode; + CURLcode result = CURLE_OK; + bool was_ctl_valid = ftpc->ctl_valid; + char *path; + const char *path_to_use = data->state.path; + + if(!ftp) + /* When the easy handle is removed from the multi while libcurl is still + * trying to resolve the host name, it seems that the ftp struct is not + * yet initialized, but the removal action calls Curl_done() which calls + * this function. So we simply return success if no ftp pointer is set. + */ + return CURLE_OK; + + switch(status) { + case CURLE_BAD_DOWNLOAD_RESUME: + case CURLE_FTP_WEIRD_PASV_REPLY: + case CURLE_FTP_PORT_FAILED: + case CURLE_FTP_ACCEPT_FAILED: + case CURLE_FTP_ACCEPT_TIMEOUT: + case CURLE_FTP_COULDNT_SET_TYPE: + case CURLE_FTP_COULDNT_RETR_FILE: + case CURLE_PARTIAL_FILE: + case CURLE_UPLOAD_FAILED: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_FILESIZE_EXCEEDED: + case CURLE_REMOTE_FILE_NOT_FOUND: + case CURLE_WRITE_ERROR: + /* the connection stays alive fine even though this happened */ + /* fall-through */ + case CURLE_OK: /* doesn't affect the control connection's status */ + if(!premature) { + ftpc->ctl_valid = was_ctl_valid; + break; + } + /* until we cope better with prematurely ended requests, let them + * fallback as if in complete failure */ + default: /* by default, an error means the control connection is + wedged and should not be used anymore */ + ftpc->ctl_valid = FALSE; + ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the + current path, as this connection is going */ + connclose(conn, "FTP ended with bad error code"); + result = status; /* use the already set error code */ + break; + } + + /* now store a copy of the directory we are in */ + free(ftpc->prevpath); + + if(data->set.wildcardmatch) { + if(data->set.chunk_end && ftpc->file) { + data->set.chunk_end(data->wildcard.customptr); + } + ftpc->known_filesize = -1; + } + + /* get the "raw" path */ + path = curl_easy_unescape(data, path_to_use, 0, NULL); + if(!path) { + /* out of memory, but we can limp along anyway (and should try to + * since we may already be in the out of memory cleanup path) */ + if(!result) + result = CURLE_OUT_OF_MEMORY; + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "FTP: out of memory!"); /* mark for connection closure */ + ftpc->prevpath = NULL; /* no path remembering */ + } + else { + size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */ + size_t dlen = strlen(path)-flen; + if(!ftpc->cwdfail) { + if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) { + ftpc->prevpath = path; + if(flen) + /* if 'path' is not the whole string */ + ftpc->prevpath[dlen]=0; /* terminate */ + } + else { + /* we never changed dir */ + ftpc->prevpath=strdup(""); + free(path); + } + if(ftpc->prevpath) + infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath); + } + else { + ftpc->prevpath = NULL; /* no path */ + free(path); + } + } + /* free the dir tree and file parts */ + freedirs(ftpc); + + /* shut down the socket to inform the server we're done */ + +#ifdef _WIN32_WCE + shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */ +#endif + + if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { + if(!result && ftpc->dont_check && data->req.maxdownload > 0) { + /* partial download completed */ + result = Curl_pp_sendf(pp, "%s", "ABOR"); + if(result) { + failf(data, "Failure sending ABOR command: %s", + curl_easy_strerror(result)); + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "ABOR command failed"); /* connection closure */ + } + } + + if(conn->ssl[SECONDARYSOCKET].use) { + /* The secondary socket is using SSL so we must close down that part + first before we close the socket for real */ + Curl_ssl_close(conn, SECONDARYSOCKET); + + /* Note that we keep "use" set to TRUE since that (next) connection is + still requested to use SSL */ + } + if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; + conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; + } + } + + if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid && + pp->pending_resp && !premature) { + /* + * Let's see what the server says about the transfer we just performed, + * but lower the timeout as sometimes this connection has died while the + * data has been transferred. This happens when doing through NATs etc that + * abandon old silent connections. + */ + long old_time = pp->response_time; + + pp->response_time = 60*1000; /* give it only a minute for now */ + pp->response = Curl_tvnow(); /* timeout relative now */ + + result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + + pp->response_time = old_time; /* set this back to previous value */ + + if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) { + failf(data, "control connection looks dead"); + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */ + } + + if(result) + return result; + + if(ftpc->dont_check && data->req.maxdownload > 0) { + /* we have just sent ABOR and there is no reliable way to check if it was + * successful or not; we have to close the connection now */ + infof(data, "partial download completed, closing connection\n"); + connclose(conn, "Partial download with no ability to check"); + return result; + } + + if(!ftpc->dont_check) { + /* 226 Transfer complete, 250 Requested file action okay, completed. */ + if((ftpcode != 226) && (ftpcode != 250)) { + failf(data, "server did not report OK, got %d", ftpcode); + result = CURLE_PARTIAL_FILE; + } + } + } + + if(result || premature) + /* the response code from the transfer showed an error already so no + use checking further */ + ; + else if(data->set.upload) { + if((-1 != data->state.infilesize) && + (data->state.infilesize != *ftp->bytecountp) && + !data->set.crlf && + (ftp->transfer == FTPTRANSFER_BODY)) { + failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T + " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", + *ftp->bytecountp, data->state.infilesize); + result = CURLE_PARTIAL_FILE; + } + } + else { + if((-1 != data->req.size) && + (data->req.size != *ftp->bytecountp) && +#ifdef CURL_DO_LINEEND_CONV + /* Most FTP servers don't adjust their file SIZE response for CRLFs, so + * we'll check to see if the discrepancy can be explained by the number + * of CRLFs we've changed to LFs. + */ + ((data->req.size + data->state.crlf_conversions) != + *ftp->bytecountp) && +#endif /* CURL_DO_LINEEND_CONV */ + (data->req.maxdownload != *ftp->bytecountp)) { + failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T + " bytes", *ftp->bytecountp); + result = CURLE_PARTIAL_FILE; + } + else if(!ftpc->dont_check && + !*ftp->bytecountp && + (data->req.size>0)) { + failf(data, "No data was received!"); + result = CURLE_FTP_COULDNT_RETR_FILE; + } + } + + /* clear these for next connection */ + ftp->transfer = FTPTRANSFER_BODY; + ftpc->dont_check = FALSE; + + /* Send any post-transfer QUOTE strings? */ + if(!status && !result && !premature && data->set.postquote) + result = ftp_sendquote(conn, data->set.postquote); + + return result; +} + +/*********************************************************************** + * + * ftp_sendquote() + * + * Where a 'quote' means a list of custom commands to send to the server. + * The quote list is passed as an argument. + * + * BLOCKING + */ + +static +CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote) +{ + struct curl_slist *item; + ssize_t nread; + int ftpcode; + CURLcode result; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + item = quote; + while(item) { + if(item->data) { + char *cmd = item->data; + bool acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal FTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + acceptfail = TRUE; + } + + PPSENDF(&conn->proto.ftpc.pp, "%s", cmd); + + pp->response = Curl_tvnow(); /* timeout relative now */ + + result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + if(result) + return result; + + if(!acceptfail && (ftpcode >= 400)) { + failf(conn->data, "QUOT string not accepted: %s", cmd); + return CURLE_QUOTE_ERROR; + } + } + + item = item->next; + } + + return CURLE_OK; +} + +/*********************************************************************** + * + * ftp_need_type() + * + * Returns TRUE if we in the current situation should send TYPE + */ +static int ftp_need_type(struct connectdata *conn, + bool ascii_wanted) +{ + return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I'); +} + +/*********************************************************************** + * + * ftp_nb_type() + * + * Set TYPE. We only deal with ASCII or BINARY so this function + * sets one of them. + * If the transfer type is not sent, simulate on OK response in newstate + */ +static CURLcode ftp_nb_type(struct connectdata *conn, + bool ascii, ftpstate newstate) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result; + char want = (char)(ascii?'A':'I'); + + if(ftpc->transfertype == want) { + state(conn, newstate); + return ftp_state_type_resp(conn, 200, newstate); + } + + PPSENDF(&ftpc->pp, "TYPE %c", want); + state(conn, newstate); + + /* keep track of our current transfer type */ + ftpc->transfertype = want; + return CURLE_OK; +} + +/*************************************************************************** + * + * ftp_pasv_verbose() + * + * This function only outputs some informationals about this second connection + * when we've issued a PASV command before and thus we have connected to a + * possibly new IP address. + * + */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void +ftp_pasv_verbose(struct connectdata *conn, + Curl_addrinfo *ai, + char *newhost, /* ascii version */ + int port) +{ + char buf[256]; + Curl_printable_address(ai, buf, sizeof(buf)); + infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port); +} +#endif + +/* + Check if this is a range download, and if so, set the internal variables + properly. + */ + +static CURLcode ftp_range(struct connectdata *conn) +{ + curl_off_t from, to; + char *ptr; + char *ptr2; + struct SessionHandle *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(data->state.use_range && data->state.range) { + from=curlx_strtoofft(data->state.range, &ptr, 0); + while(*ptr && (ISSPACE(*ptr) || (*ptr=='-'))) + ptr++; + to=curlx_strtoofft(ptr, &ptr2, 0); + if(ptr == ptr2) { + /* we didn't get any digit */ + to=-1; + } + if((-1 == to) && (from>=0)) { + /* X - */ + data->state.resume_from = from; + DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T + " to end of file\n", from)); + } + else if(from < 0) { + /* -Y */ + data->req.maxdownload = -from; + data->state.resume_from = from; + DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T + " bytes\n", -from)); + } + else { + /* X-Y */ + data->req.maxdownload = (to-from)+1; /* include last byte */ + data->state.resume_from = from; + DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T + " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n", + from, data->req.maxdownload)); + } + DEBUGF(infof(conn->data, "range-download from %" CURL_FORMAT_CURL_OFF_T + " to %" CURL_FORMAT_CURL_OFF_T ", totally %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + from, to, data->req.maxdownload)); + ftpc->dont_check = TRUE; /* dont check for successful transfer */ + } + else + data->req.maxdownload = -1; + return CURLE_OK; +} + + +/* + * ftp_do_more() + * + * This function shall be called when the second FTP (data) connection is + * connected. + * + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back + * (which basically is only for when PASV is being sent to retry a failed + * EPSV). + */ + +static CURLcode ftp_do_more(struct connectdata *conn, int *completep) +{ + struct SessionHandle *data=conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + bool connected = FALSE; + bool complete = FALSE; + + /* the ftp struct is inited in ftp_connect() */ + struct FTP *ftp = data->req.protop; + + /* if the second connection isn't done yet, wait for it */ + if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { + if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) { + /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port + aren't used so we blank their arguments. TODO: make this nicer */ + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0); + + return result; + } + + result = Curl_is_connected(conn, SECONDARYSOCKET, &connected); + + /* Ready to do more? */ + if(connected) { + DEBUGF(infof(data, "DO-MORE connected phase starts\n")); + if(conn->bits.proxy) { + infof(data, "Connection to proxy confirmed\n"); + result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected); + } + } + else { + if(result && (ftpc->count1 == 0)) { + *completep = -1; /* go back to DOING please */ + /* this is a EPSV connect failing, try PASV instead */ + return ftp_epsv_disable(conn); + } + return result; + } + } + + if(ftpc->state) { + /* already in a state so skip the intial commands. + They are only done to kickstart the do_more state */ + result = ftp_multi_statemach(conn, &complete); + + *completep = (int)complete; + + /* if we got an error or if we don't wait for a data connection return + immediately */ + if(result || (ftpc->wait_data_conn != TRUE)) + return result; + + if(ftpc->wait_data_conn) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ + *completep = 0; + } + + if(ftp->transfer <= FTPTRANSFER_INFO) { + /* a transfer is about to take place, or if not a file name was given + so we'll do a SIZE on it later and then we need the right TYPE first */ + + if(ftpc->wait_data_conn == TRUE) { + bool serv_conned; + + result = ReceivedServerConnect(conn, &serv_conned); + if(result) + return result; /* Failed to accept data connection */ + + if(serv_conned) { + /* It looks data connection is established */ + result = AcceptServerConnect(conn); + ftpc->wait_data_conn = FALSE; + if(!result) + result = InitiateTransfer(conn); + + if(result) + return result; + + *completep = 1; /* this state is now complete when the server has + connected back to us */ + } + } + else if(data->set.upload) { + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE); + if(result) + return result; + + result = ftp_multi_statemach(conn, &complete); + *completep = (int)complete; + } + else { + /* download */ + ftp->downloadsize = -1; /* unknown as of yet */ + + result = ftp_range(conn); + if(result) + ; + else if(data->set.ftp_list_only || !ftpc->file) { + /* The specified path ends with a slash, and therefore we think this + is a directory that is requested, use LIST. But before that we + need to set ASCII transfer mode. */ + + /* But only if a body transfer was requested. */ + if(ftp->transfer == FTPTRANSFER_BODY) { + result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE); + if(result) + return result; + } + /* otherwise just fall through */ + } + else { + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE); + if(result) + return result; + } + + result = ftp_multi_statemach(conn, &complete); + *completep = (int)complete; + } + return result; + } + + if(!result && (ftp->transfer != FTPTRANSFER_BODY)) + /* no data to transfer. FIX: it feels like a kludge to have this here + too! */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + + if(!ftpc->wait_data_conn) { + /* no waiting for the data connection so this is now complete */ + *completep = 1; + DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result)); + } + + return result; +} + + + +/*********************************************************************** + * + * ftp_perform() + * + * This is the actual DO function for FTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode ftp_perform(struct connectdata *conn, + bool *connected, /* connect status after PASV / PORT */ + bool *dophase_done) +{ + /* this is FTP and no proxy */ + CURLcode result=CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* requested no body means no transfer... */ + struct FTP *ftp = conn->data->req.protop; + ftp->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + result = ftp_state_quote(conn, TRUE, FTP_QUOTE); + if(result) + return result; + + /* run the state-machine */ + result = ftp_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[SECONDARYSOCKET]; + + infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected); + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete1\n")); + + return result; +} + +static void wc_data_dtor(void *ptr) +{ + struct ftp_wc_tmpdata *tmp = ptr; + if(tmp) + Curl_ftp_parselist_data_free(&tmp->parser); + free(tmp); +} + +static CURLcode init_wc_data(struct connectdata *conn) +{ + char *last_slash; + char *path = conn->data->state.path; + struct WildcardData *wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + struct ftp_wc_tmpdata *ftp_tmp; + + last_slash = strrchr(conn->data->state.path, '/'); + if(last_slash) { + last_slash++; + if(last_slash[0] == '\0') { + wildcard->state = CURLWC_CLEAN; + result = ftp_parse_url_path(conn); + return result; + } + else { + wildcard->pattern = strdup(last_slash); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + last_slash[0] = '\0'; /* cut file from path */ + } + } + else { /* there is only 'wildcard pattern' or nothing */ + if(path[0]) { + wildcard->pattern = strdup(path); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + path[0] = '\0'; + } + else { /* only list */ + wildcard->state = CURLWC_CLEAN; + result = ftp_parse_url_path(conn); + return result; + } + } + + /* program continues only if URL is not ending with slash, allocate needed + resources for wildcard transfer */ + + /* allocate ftp protocol specific temporary wildcard data */ + ftp_tmp = calloc(1, sizeof(struct ftp_wc_tmpdata)); + if(!ftp_tmp) { + Curl_safefree(wildcard->pattern); + return CURLE_OUT_OF_MEMORY; + } + + /* INITIALIZE parselist structure */ + ftp_tmp->parser = Curl_ftp_parselist_data_alloc(); + if(!ftp_tmp->parser) { + Curl_safefree(wildcard->pattern); + free(ftp_tmp); + return CURLE_OUT_OF_MEMORY; + } + + wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */ + wildcard->tmp_dtor = wc_data_dtor; + + /* wildcard does not support NOCWD option (assert it?) */ + if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD) + conn->data->set.ftp_filemethod = FTPFILE_MULTICWD; + + /* try to parse ftp url */ + result = ftp_parse_url_path(conn); + if(result) { + Curl_safefree(wildcard->pattern); + wildcard->tmp_dtor(wildcard->tmp); + wildcard->tmp_dtor = ZERO_NULL; + wildcard->tmp = NULL; + return result; + } + + wildcard->path = strdup(conn->data->state.path); + if(!wildcard->path) { + Curl_safefree(wildcard->pattern); + wildcard->tmp_dtor(wildcard->tmp); + wildcard->tmp_dtor = ZERO_NULL; + wildcard->tmp = NULL; + return CURLE_OUT_OF_MEMORY; + } + + /* backup old write_function */ + ftp_tmp->backup.write_function = conn->data->set.fwrite_func; + /* parsing write function */ + conn->data->set.fwrite_func = Curl_ftp_parselist; + /* backup old file descriptor */ + ftp_tmp->backup.file_descriptor = conn->data->set.out; + /* let the writefunc callback know what curl pointer is working with */ + conn->data->set.out = conn; + + infof(conn->data, "Wildcard - Parsing started\n"); + return CURLE_OK; +} + +/* This is called recursively */ +static CURLcode wc_statemach(struct connectdata *conn) +{ + struct WildcardData * const wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + + switch (wildcard->state) { + case CURLWC_INIT: + result = init_wc_data(conn); + if(wildcard->state == CURLWC_CLEAN) + /* only listing! */ + break; + else + wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; + break; + + case CURLWC_MATCHING: { + /* In this state is LIST response successfully parsed, so lets restore + previous WRITEFUNCTION callback and WRITEDATA pointer */ + struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp; + conn->data->set.fwrite_func = ftp_tmp->backup.write_function; + conn->data->set.out = ftp_tmp->backup.file_descriptor; + ftp_tmp->backup.write_function = ZERO_NULL; + ftp_tmp->backup.file_descriptor = NULL; + wildcard->state = CURLWC_DOWNLOADING; + + if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) { + /* error found in LIST parsing */ + wildcard->state = CURLWC_CLEAN; + return wc_statemach(conn); + } + else if(wildcard->filelist->size == 0) { + /* no corresponding file */ + wildcard->state = CURLWC_CLEAN; + return CURLE_REMOTE_FILE_NOT_FOUND; + } + return wc_statemach(conn); + } + + case CURLWC_DOWNLOADING: { + /* filelist has at least one file, lets get first one */ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct curl_fileinfo *finfo = wildcard->filelist->head->ptr; + + char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); + if(!tmp_path) + return CURLE_OUT_OF_MEMORY; + + /* switch default "state.pathbuffer" and tmp_path, good to see + ftp_parse_url_path function to understand this trick */ + Curl_safefree(conn->data->state.pathbuffer); + conn->data->state.pathbuffer = tmp_path; + conn->data->state.path = tmp_path; + + infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); + if(conn->data->set.chunk_bgn) { + long userresponse = conn->data->set.chunk_bgn( + finfo, wildcard->customptr, (int)wildcard->filelist->size); + switch(userresponse) { + case CURL_CHUNK_BGN_FUNC_SKIP: + infof(conn->data, "Wildcard - \"%s\" skipped by user\n", + finfo->filename); + wildcard->state = CURLWC_SKIP; + return wc_statemach(conn); + case CURL_CHUNK_BGN_FUNC_FAIL: + return CURLE_CHUNK_FAILED; + } + } + + if(finfo->filetype != CURLFILETYPE_FILE) { + wildcard->state = CURLWC_SKIP; + return wc_statemach(conn); + } + + if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) + ftpc->known_filesize = finfo->size; + + result = ftp_parse_url_path(conn); + if(result) + return result; + + /* we don't need the Curl_fileinfo of first file anymore */ + Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); + + if(wildcard->filelist->size == 0) { /* remains only one file to down. */ + wildcard->state = CURLWC_CLEAN; + /* after that will be ftp_do called once again and no transfer + will be done because of CURLWC_CLEAN state */ + return CURLE_OK; + } + } break; + + case CURLWC_SKIP: { + if(conn->data->set.chunk_end) + conn->data->set.chunk_end(conn->data->wildcard.customptr); + Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); + wildcard->state = (wildcard->filelist->size == 0) ? + CURLWC_CLEAN : CURLWC_DOWNLOADING; + return wc_statemach(conn); + } + + case CURLWC_CLEAN: { + struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp; + result = CURLE_OK; + if(ftp_tmp) + result = Curl_ftp_parselist_geterror(ftp_tmp->parser); + + wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; + } break; + + case CURLWC_DONE: + case CURLWC_ERROR: + break; + } + + return result; +} + +/*********************************************************************** + * + * ftp_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (ftp_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode ftp_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + *done = FALSE; /* default to false */ + ftpc->wait_data_conn = FALSE; /* default to no such wait */ + + if(conn->data->set.wildcardmatch) { + result = wc_statemach(conn); + if(conn->data->wildcard.state == CURLWC_SKIP || + conn->data->wildcard.state == CURLWC_DONE) { + /* do not call ftp_regular_transfer */ + return CURLE_OK; + } + if(result) /* error, loop or skipping the file */ + return result; + } + else { /* no wildcard FSM needed */ + result = ftp_parse_url_path(conn); + if(result) + return result; + } + + result = ftp_regular_transfer(conn, done); + + return result; +} + + +CURL_STATIC CURLcode Curl_ftpsendf(struct connectdata *conn, + const char *fmt, ...) +{ + ssize_t bytes_written; +#define SBUF_SIZE 1024 + char s[SBUF_SIZE]; + size_t write_len; + char *sptr=s; + CURLcode result = CURLE_OK; +#ifdef HAVE_GSSAPI + enum protection_level data_sec = conn->data_prot; +#endif + + va_list ap; + va_start(ap, fmt); + write_len = vsnprintf(s, SBUF_SIZE-3, fmt, ap); + va_end(ap); + + strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */ + write_len +=2; + + bytes_written=0; + + result = Curl_convert_to_network(conn->data, s, write_len); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + + for(;;) { +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CMD; +#endif + result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, + &bytes_written); +#ifdef HAVE_GSSAPI + DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); + conn->data_prot = data_sec; +#endif + + if(result) + break; + + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, + sptr, (size_t)bytes_written, conn); + + if(bytes_written != (ssize_t)write_len) { + write_len -= bytes_written; + sptr += bytes_written; + } + else + break; + } + + return result; +} + +/*********************************************************************** + * + * ftp_quit() + * + * This should be called before calling sclose() on an ftp control connection + * (not data connections). We should then wait for the response from the + * server before returning. The calling code should then try to close the + * connection. + * + */ +static CURLcode ftp_quit(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->proto.ftpc.ctl_valid) { + result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT"); + if(result) { + failf(conn->data, "Failure sending QUIT command: %s", + curl_easy_strerror(result)); + conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "QUIT command failed"); /* mark for connection closure */ + state(conn, FTP_STOP); + return result; + } + + state(conn, FTP_QUIT); + + result = ftp_block_statemach(conn); + } + + return result; +} + +/*********************************************************************** + * + * ftp_disconnect() + * + * Disconnect from an FTP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct ftp_conn *ftpc= &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. + + ftp_quit() will check the state of ftp->ctl_valid. If it's ok it + will try to send the QUIT command, otherwise it will just return. + */ + if(dead_connection) + ftpc->ctl_valid = FALSE; + + /* The FTP session may or may not have been allocated/setup at this point! */ + (void)ftp_quit(conn); /* ignore errors on the QUIT */ + + if(ftpc->entrypath) { + struct SessionHandle *data = conn->data; + if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) { + data->state.most_recent_ftp_entrypath = NULL; + } + free(ftpc->entrypath); + ftpc->entrypath = NULL; + } + + freedirs(ftpc); + free(ftpc->prevpath); + ftpc->prevpath = NULL; + free(ftpc->server_os); + ftpc->server_os = NULL; + + Curl_pp_disconnect(pp); + +#ifdef HAVE_GSSAPI + Curl_sec_end(conn); +#endif + + return CURLE_OK; +} + +/*********************************************************************** + * + * ftp_parse_url_path() + * + * Parse the URL path into separate path components. + * + */ +static +CURLcode ftp_parse_url_path(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + /* the ftp struct is already inited in ftp_connect() */ + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + const char *slash_pos; /* position of the first '/' char in curpos */ + const char *path_to_use = data->state.path; + const char *cur_pos; + const char *filename = NULL; + + cur_pos = path_to_use; /* current position in path. point at the begin + of next path component */ + + ftpc->ctl_valid = FALSE; + ftpc->cwdfail = FALSE; + + switch(data->set.ftp_filemethod) { + case FTPFILE_NOCWD: + /* fastest, but less standard-compliant */ + + /* + The best time to check whether the path is a file or directory is right + here. so: + + the first condition in the if() right here, is there just in case + someone decides to set path to NULL one day + */ + if(data->state.path && + data->state.path[0] && + (data->state.path[strlen(data->state.path) - 1] != '/') ) + filename = data->state.path; /* this is a full file path */ + /* + ftpc->file is not used anywhere other than for operations on a file. + In other words, never for directory operations. + So we can safely leave filename as NULL here and use it as a + argument in dir/file decisions. + */ + break; + + case FTPFILE_SINGLECWD: + /* get the last slash */ + if(!path_to_use[0]) { + /* no dir, no file */ + ftpc->dirdepth = 0; + break; + } + slash_pos=strrchr(cur_pos, '/'); + if(slash_pos || !*cur_pos) { + size_t dirlen = slash_pos-cur_pos; + + ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + if(!dirlen) + dirlen++; + + ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/", + slash_pos ? curlx_uztosi(dirlen) : 1, + NULL); + if(!ftpc->dirs[0]) { + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + ftpc->dirdepth = 1; /* we consider it to be a single dir */ + filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */ + } + else + filename = cur_pos; /* this is a file name only */ + break; + + default: /* allow pretty much anything */ + case FTPFILE_MULTICWD: + ftpc->dirdepth = 0; + ftpc->diralloc = 5; /* default dir depth to allocate */ + ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + /* we have a special case for listing the root dir only */ + if(strequal(path_to_use, "/")) { + cur_pos++; /* make it point to the zero byte */ + ftpc->dirs[0] = strdup("/"); + ftpc->dirdepth++; + } + else { + /* parse the URL path into separate path components */ + while((slash_pos = strchr(cur_pos, '/')) != NULL) { + /* 1 or 0 pointer offset to indicate absolute directory */ + ssize_t absolute_dir = ((cur_pos - data->state.path > 0) && + (ftpc->dirdepth == 0))?1:0; + + /* seek out the next path component */ + if(slash_pos-cur_pos) { + /* we skip empty path components, like "x//y" since the FTP command + CWD requires a parameter and a non-existent parameter a) doesn't + work on many servers and b) has no effect on the others. */ + int len = curlx_sztosi(slash_pos - cur_pos + absolute_dir); + ftpc->dirs[ftpc->dirdepth] = + curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL); + if(!ftpc->dirs[ftpc->dirdepth]) { /* run out of memory ... */ + failf(data, "no memory"); + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + if(isBadFtpString(ftpc->dirs[ftpc->dirdepth])) { + free(ftpc->dirs[ftpc->dirdepth]); + freedirs(ftpc); + return CURLE_URL_MALFORMAT; + } + } + else { + cur_pos = slash_pos + 1; /* jump to the rest of the string */ + if(!ftpc->dirdepth) { + /* path starts with a slash, add that as a directory */ + ftpc->dirs[ftpc->dirdepth] = strdup("/"); + if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */ + failf(data, "no memory"); + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + } + continue; + } + + cur_pos = slash_pos + 1; /* jump to the rest of the string */ + if(++ftpc->dirdepth >= ftpc->diralloc) { + /* enlarge array */ + char **bigger; + ftpc->diralloc *= 2; /* double the size each time */ + bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0])); + if(!bigger) { + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + ftpc->dirs = bigger; + } + } + } + filename = cur_pos; /* the rest is the file name */ + break; + } /* switch */ + + if(filename && *filename) { + ftpc->file = curl_easy_unescape(conn->data, filename, 0, NULL); + if(NULL == ftpc->file) { + freedirs(ftpc); + failf(data, "no memory"); + return CURLE_OUT_OF_MEMORY; + } + if(isBadFtpString(ftpc->file)) { + freedirs(ftpc); + return CURLE_URL_MALFORMAT; + } + } + else + ftpc->file=NULL; /* instead of point to a zero byte, we make it a NULL + pointer */ + + if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) { + /* We need a file name when uploading. Return error! */ + failf(data, "Uploading to a URL without a file name!"); + return CURLE_URL_MALFORMAT; + } + + ftpc->cwddone = FALSE; /* default to not done */ + + if(ftpc->prevpath) { + /* prevpath is "raw" so we convert the input path before we compare the + strings */ + int dlen; + char *path = curl_easy_unescape(conn->data, data->state.path, 0, &dlen); + if(!path) { + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + + dlen -= ftpc->file?curlx_uztosi(strlen(ftpc->file)):0; + if((dlen == curlx_uztosi(strlen(ftpc->prevpath))) && + strnequal(path, ftpc->prevpath, dlen)) { + infof(data, "Request has same path as previous transfer\n"); + ftpc->cwddone = TRUE; + } + free(path); + } + + return CURLE_OK; +} + +/* call this when the DO phase has completed */ +static CURLcode ftp_dophase_done(struct connectdata *conn, + bool connected) +{ + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(connected) { + int completed; + CURLcode result = ftp_do_more(conn, &completed); + + if(result) { + if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { + /* close the second socket if it was created already */ + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; + } + return result; + } + } + + if(ftp->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + else if(!connected) + /* since we didn't connect now, we want do_more to get called */ + conn->bits.do_more = TRUE; + + ftpc->ctl_valid = TRUE; /* seems good */ + + return CURLE_OK; +} + +/* called from multi.c while DOing */ +static CURLcode ftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = ftp_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = ftp_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete2\n")); + } + return result; +} + +/*********************************************************************** + * + * ftp_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + * + * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the + * ftp_done() function without finding any major problem. + */ +static +CURLcode ftp_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result=CURLE_OK; + bool connected=FALSE; + struct SessionHandle *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + data->req.size = -1; /* make sure this is unknown at this point */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + ftpc->ctl_valid = TRUE; /* starts good */ + + result = ftp_perform(conn, + &connected, /* have we connected after PASV/PORT */ + dophase_done); /* all commands in the DO-phase done? */ + + if(!result) { + + if(!*dophase_done) + /* the DO phase has not completed yet */ + return CURLE_OK; + + result = ftp_dophase_done(conn, connected); + + if(result) + return result; + } + else + freedirs(ftpc); + + return result; +} + +static CURLcode ftp_setup_connection(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + char *type; + char command; + struct FTP *ftp; + + if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { + /* Unless we have asked to tunnel ftp operations through the proxy, we + switch and use HTTP operations only */ +#ifndef CURL_DISABLE_HTTP + if(conn->handler == &Curl_handler_ftp) + conn->handler = &Curl_handler_ftp_proxy; + else { +#ifdef USE_SSL + conn->handler = &Curl_handler_ftps_proxy; +#else + failf(data, "FTPS not supported!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + /* set it up as a HTTP connection instead */ + return conn->handler->setup_connection(conn); +#else + failf(data, "FTP over http proxy requires HTTP support built-in!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + + conn->data->req.protop = ftp = malloc(sizeof(struct FTP)); + if(NULL == ftp) + return CURLE_OUT_OF_MEMORY; + + data->state.path++; /* don't include the initial slash */ + data->state.slash_removed = TRUE; /* we've skipped the slash */ + + /* FTP URLs support an extension like ";type=" that + * we'll try to get now! */ + type = strstr(data->state.path, ";type="); + + if(!type) + type = strstr(conn->host.rawalloc, ";type="); + + if(type) { + *type = 0; /* it was in the middle of the hostname */ + command = Curl_raw_toupper(type[6]); + conn->bits.type_set = TRUE; + + switch (command) { + case 'A': /* ASCII mode */ + data->set.prefer_ascii = TRUE; + break; + + case 'D': /* directory mode */ + data->set.ftp_list_only = TRUE; + break; + + case 'I': /* binary mode */ + default: + /* switch off ASCII */ + data->set.prefer_ascii = FALSE; + break; + } + } + + /* get some initial data into the ftp struct */ + ftp->bytecountp = &conn->data->req.bytecount; + ftp->transfer = FTPTRANSFER_BODY; + ftp->downloadsize = 0; + + /* No need to duplicate user+password, the connectdata struct won't change + during a session, but we re-init them here since on subsequent inits + since the conn struct may have changed or been replaced. + */ + ftp->user = conn->user; + ftp->passwd = conn->passwd; + if(isBadFtpString(ftp->user)) + return CURLE_URL_MALFORMAT; + if(isBadFtpString(ftp->passwd)) + return CURLE_URL_MALFORMAT; + + conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_FTP */ diff --git a/libcurl/src/lib/ftp.h b/libcurl/src/lib/ftp.h new file mode 100644 index 0000000..942d104 --- /dev/null +++ b/libcurl/src/lib/ftp.h @@ -0,0 +1,159 @@ +#ifndef HEADER_CURL_FTP_H +#define HEADER_CURL_FTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" + +#ifndef CURL_DISABLE_FTP +extern const struct Curl_handler Curl_handler_ftp; + +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_ftps; +#endif + +CURL_STATIC CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...); +CURL_STATIC CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn, + int *ftpcode); +#endif /* CURL_DISABLE_FTP */ + +/**************************************************************************** + * FTP unique setup + ***************************************************************************/ +typedef enum { + FTP_STOP, /* do nothing state, stops the state machine */ + FTP_WAIT220, /* waiting for the initial 220 response immediately after + a connect */ + FTP_AUTH, + FTP_USER, + FTP_PASS, + FTP_ACCT, + FTP_PBSZ, + FTP_PROT, + FTP_CCC, + FTP_PWD, + FTP_SYST, + FTP_NAMEFMT, + FTP_QUOTE, /* waiting for a response to a command sent in a quote list */ + FTP_RETR_PREQUOTE, + FTP_STOR_PREQUOTE, + FTP_POSTQUOTE, + FTP_CWD, /* change dir */ + FTP_MKD, /* if the dir didn't exist */ + FTP_MDTM, /* to figure out the datestamp */ + FTP_TYPE, /* to set type when doing a head-like request */ + FTP_LIST_TYPE, /* set type when about to do a dir list */ + FTP_RETR_TYPE, /* set type when about to RETR a file */ + FTP_STOR_TYPE, /* set type when about to STOR a file */ + FTP_SIZE, /* get the remote file's size for head-like request */ + FTP_RETR_SIZE, /* get the remote file's size for RETR */ + FTP_STOR_SIZE, /* get the size for STOR */ + FTP_REST, /* when used to check if the server supports it in head-like */ + FTP_RETR_REST, /* when asking for "resume" in for RETR */ + FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */ + FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */ + FTP_PASV, /* generic state for PASV and EPSV, check count1 */ + FTP_LIST, /* generic state for LIST, NLST or a custom list command */ + FTP_RETR, + FTP_STOR, /* generic state for STOR and APPE */ + FTP_QUIT, + FTP_LAST /* never used */ +} ftpstate; + +struct ftp_parselist_data; /* defined later in ftplistparser.c */ + +struct ftp_wc_tmpdata { + struct ftp_parselist_data *parser; + + struct { + curl_write_callback write_function; + FILE *file_descriptor; + } backup; +}; + +typedef enum { + FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */ + FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */ + FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the + file */ +} curl_ftpfile; + +/* This FTP struct is used in the SessionHandle. All FTP data that is + connection-oriented must be in FTP_conn to properly deal with the fact that + perhaps the SessionHandle is changed between the times the connection is + used. */ +struct FTP { + curl_off_t *bytecountp; + char *user; /* user name string */ + char *passwd; /* password string */ + + /* transfer a file/body or not, done as a typedefed enum just to make + debuggers display the full symbol and not just the numerical value */ + curl_pp_transfer transfer; + curl_off_t downloadsize; +}; + + +/* ftp_conn is used for struct connection-oriented data in the connectdata + struct */ +struct ftp_conn { + struct pingpong pp; + char *entrypath; /* the PWD reply when we logged on */ + char **dirs; /* realloc()ed array for path components */ + int dirdepth; /* number of entries used in the 'dirs' array */ + int diralloc; /* number of entries allocated for the 'dirs' array */ + char *file; /* decoded file */ + bool dont_check; /* Set to TRUE to prevent the final (post-transfer) + file size and 226/250 status check. It should still + read the line, just ignore the result. */ + bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If + the connection has timed out or been closed, this + should be FALSE when it gets to Curl_ftp_quit() */ + bool cwddone; /* if it has been determined that the proper CWD combo + already has been done */ + bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent + caching the current directory */ + bool wait_data_conn; /* this is set TRUE if data connection is waited */ + char *prevpath; /* conn->path from the previous transfer */ + char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a + and others (A/I or zero) */ + int count1; /* general purpose counter for the state machine */ + int count2; /* general purpose counter for the state machine */ + int count3; /* general purpose counter for the state machine */ + ftpstate state; /* always use ftp.c:state() to change state! */ + ftpstate state_saved; /* transfer type saved to be reloaded after + data connection is established */ + curl_off_t retr_size_saved; /* Size of retrieved file saved */ + char * server_os; /* The target server operating system. */ + curl_off_t known_filesize; /* file size is different from -1, if wildcard + LIST parsing was done and wc_statemach set + it */ + /* newhost is the (allocated) IP addr or host name to connect the data + connection to */ + char *newhost; /* this is the pair to connect the DATA... */ + unsigned short newport; /* connection to */ + +}; + +#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */ + +#endif /* HEADER_CURL_FTP_H */ diff --git a/libcurl/src/lib/ftplistparser.c b/libcurl/src/lib/ftplistparser.c new file mode 100644 index 0000000..f5a6553 --- /dev/null +++ b/libcurl/src/lib/ftplistparser.c @@ -0,0 +1,1048 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/** + * Now implemented: + * + * 1) Unix version 1 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog + * 2) Unix version 2 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog + * 3) Unix version 3 + * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog + * 4) Unix symlink + * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000 + * 5) DOS style + * 01-29-97 11:32PM prog + */ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#include + +#include "urldata.h" +#include "fileinfo.h" +#include "llist.h" +#include "strtoofft.h" +#include "rawstr.h" +#include "ftp.h" +#include "ftplistparser.h" +#include "curl_fnmatch.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* allocs buffer which will contain one line of LIST command response */ +#define FTP_BUFFER_ALLOCSIZE 160 + +typedef enum { + PL_UNIX_TOTALSIZE = 0, + PL_UNIX_FILETYPE, + PL_UNIX_PERMISSION, + PL_UNIX_HLINKS, + PL_UNIX_USER, + PL_UNIX_GROUP, + PL_UNIX_SIZE, + PL_UNIX_TIME, + PL_UNIX_FILENAME, + PL_UNIX_SYMLINK +} pl_unix_mainstate; + +typedef union { + enum { + PL_UNIX_TOTALSIZE_INIT = 0, + PL_UNIX_TOTALSIZE_READING + } total_dirsize; + + enum { + PL_UNIX_HLINKS_PRESPACE = 0, + PL_UNIX_HLINKS_NUMBER + } hlinks; + + enum { + PL_UNIX_USER_PRESPACE = 0, + PL_UNIX_USER_PARSING + } user; + + enum { + PL_UNIX_GROUP_PRESPACE = 0, + PL_UNIX_GROUP_NAME + } group; + + enum { + PL_UNIX_SIZE_PRESPACE = 0, + PL_UNIX_SIZE_NUMBER + } size; + + enum { + PL_UNIX_TIME_PREPART1 = 0, + PL_UNIX_TIME_PART1, + PL_UNIX_TIME_PREPART2, + PL_UNIX_TIME_PART2, + PL_UNIX_TIME_PREPART3, + PL_UNIX_TIME_PART3 + } time; + + enum { + PL_UNIX_FILENAME_PRESPACE = 0, + PL_UNIX_FILENAME_NAME, + PL_UNIX_FILENAME_WINDOWSEOL + } filename; + + enum { + PL_UNIX_SYMLINK_PRESPACE = 0, + PL_UNIX_SYMLINK_NAME, + PL_UNIX_SYMLINK_PRETARGET1, + PL_UNIX_SYMLINK_PRETARGET2, + PL_UNIX_SYMLINK_PRETARGET3, + PL_UNIX_SYMLINK_PRETARGET4, + PL_UNIX_SYMLINK_TARGET, + PL_UNIX_SYMLINK_WINDOWSEOL + } symlink; +} pl_unix_substate; + +typedef enum { + PL_WINNT_DATE = 0, + PL_WINNT_TIME, + PL_WINNT_DIRORSIZE, + PL_WINNT_FILENAME +} pl_winNT_mainstate; + +typedef union { + enum { + PL_WINNT_TIME_PRESPACE = 0, + PL_WINNT_TIME_TIME + } time; + enum { + PL_WINNT_DIRORSIZE_PRESPACE = 0, + PL_WINNT_DIRORSIZE_CONTENT + } dirorsize; + enum { + PL_WINNT_FILENAME_PRESPACE = 0, + PL_WINNT_FILENAME_CONTENT, + PL_WINNT_FILENAME_WINEOL + } filename; +} pl_winNT_substate; + +/* This struct is used in wildcard downloading - for parsing LIST response */ +struct ftp_parselist_data { + enum { + OS_TYPE_UNKNOWN = 0, + OS_TYPE_UNIX, + OS_TYPE_WIN_NT + } os_type; + + union { + struct { + pl_unix_mainstate main; + pl_unix_substate sub; + } UNIX; + + struct { + pl_winNT_mainstate main; + pl_winNT_substate sub; + } NT; + } state; + + CURLcode error; + struct curl_fileinfo *file_data; + unsigned int item_length; + size_t item_offset; + struct { + size_t filename; + size_t user; + size_t group; + size_t time; + size_t perm; + size_t symlink_target; + } offsets; +}; + +CURL_STATIC struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) +{ + return calloc(1, sizeof(struct ftp_parselist_data)); +} + + +CURL_STATIC void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data) +{ + free(*pl_data); + *pl_data = NULL; +} + + +CURL_STATIC CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data) +{ + return pl_data->error; +} + + +#define FTP_LP_MALFORMATED_PERM 0x01000000 + +static int ftp_pl_get_permission(const char *str) +{ + int permissions = 0; + /* USER */ + if(str[0] == 'r') + permissions |= 1 << 8; + else if(str[0] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[1] == 'w') + permissions |= 1 << 7; + else if(str[1] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + + if(str[2] == 'x') + permissions |= 1 << 6; + else if(str[2] == 's') { + permissions |= 1 << 6; + permissions |= 1 << 11; + } + else if(str[2] == 'S') + permissions |= 1 << 11; + else if(str[2] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + /* GROUP */ + if(str[3] == 'r') + permissions |= 1 << 5; + else if(str[3] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[4] == 'w') + permissions |= 1 << 4; + else if(str[4] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[5] == 'x') + permissions |= 1 << 3; + else if(str[5] == 's') { + permissions |= 1 << 3; + permissions |= 1 << 10; + } + else if(str[5] == 'S') + permissions |= 1 << 10; + else if(str[5] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + /* others */ + if(str[6] == 'r') + permissions |= 1 << 2; + else if(str[6] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[7] == 'w') + permissions |= 1 << 1; + else if(str[7] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[8] == 'x') + permissions |= 1; + else if(str[8] == 't') { + permissions |= 1; + permissions |= 1 << 9; + } + else if(str[8] == 'T') + permissions |= 1 << 9; + else if(str[8] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + + return permissions; +} + +static void PL_ERROR(struct connectdata *conn, CURLcode err) +{ + struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp; + struct ftp_parselist_data *parser = tmpdata->parser; + if(parser->file_data) + Curl_fileinfo_dtor(NULL, parser->file_data); + parser->file_data = NULL; + parser->error = err; +} + +static bool ftp_pl_gettime(struct ftp_parselist_data *parser, char *string) +{ + (void)parser; + (void)string; + /* TODO + * There could be possible parse timestamp from server. Leaving unimplemented + * for now. + * If you want implement this, please add CURLFINFOFLAG_KNOWN_TIME flag to + * parser->file_data->flags + * + * Ftp servers are giving usually these formats: + * Apr 11 1998 (unknown time.. set it to 00:00:00?) + * Apr 11 12:21 (unknown year -> set it to NOW() time?) + * 08-05-09 02:49PM (ms-dos format) + * 20100421092538 -> for MLST/MLSD response + */ + + return FALSE; +} + +static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, + struct curl_fileinfo *finfo) +{ + curl_fnmatch_callback compare; + struct WildcardData *wc = &conn->data->wildcard; + struct ftp_wc_tmpdata *tmpdata = wc->tmp; + struct curl_llist *llist = wc->filelist; + struct ftp_parselist_data *parser = tmpdata->parser; + bool add = TRUE; + + /* move finfo pointers to b_data */ + char *str = finfo->b_data; + finfo->filename = str + parser->offsets.filename; + finfo->strings.group = parser->offsets.group ? + str + parser->offsets.group : NULL; + finfo->strings.perm = parser->offsets.perm ? + str + parser->offsets.perm : NULL; + finfo->strings.target = parser->offsets.symlink_target ? + str + parser->offsets.symlink_target : NULL; + finfo->strings.time = str + parser->offsets.time; + finfo->strings.user = parser->offsets.user ? + str + parser->offsets.user : NULL; + + /* get correct fnmatch callback */ + compare = conn->data->set.fnmatch; + if(!compare) + compare = Curl_fnmatch; + + /* filter pattern-corresponding filenames */ + if(compare(conn->data->set.fnmatch_data, wc->pattern, + finfo->filename) == 0) { + /* discard symlink which is containing multiple " -> " */ + if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target && + (strstr(finfo->strings.target, " -> "))) { + add = FALSE; + } + } + else { + add = FALSE; + } + + if(add) { + if(!Curl_llist_insert_next(llist, llist->tail, finfo)) { + Curl_fileinfo_dtor(NULL, finfo); + tmpdata->parser->file_data = NULL; + return CURLE_OUT_OF_MEMORY; + } + } + else { + Curl_fileinfo_dtor(NULL, finfo); + } + + tmpdata->parser->file_data = NULL; + return CURLE_OK; +} + +CURL_STATIC size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, + void *connptr) +{ + size_t bufflen = size*nmemb; + struct connectdata *conn = (struct connectdata *)connptr; + struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp; + struct ftp_parselist_data *parser = tmpdata->parser; + struct curl_fileinfo *finfo; + unsigned long i = 0; + CURLcode result; + + if(parser->error) { /* error in previous call */ + /* scenario: + * 1. call => OK.. + * 2. call => OUT_OF_MEMORY (or other error) + * 3. (last) call => is skipped RIGHT HERE and the error is hadled later + * in wc_statemach() + */ + return bufflen; + } + + if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) { + /* considering info about FILE response format */ + parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ? + OS_TYPE_WIN_NT : OS_TYPE_UNIX; + } + + while(i < bufflen) { /* FSM */ + + char c = buffer[i]; + if(!parser->file_data) { /* tmp file data is not allocated yet */ + parser->file_data = Curl_fileinfo_alloc(); + if(!parser->file_data) { + parser->error = CURLE_OUT_OF_MEMORY; + return bufflen; + } + parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE); + if(!parser->file_data->b_data) { + PL_ERROR(conn, CURLE_OUT_OF_MEMORY); + return bufflen; + } + parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE; + parser->item_offset = 0; + parser->item_length = 0; + } + + finfo = parser->file_data; + finfo->b_data[finfo->b_used++] = c; + + if(finfo->b_used >= finfo->b_size - 1) { + /* if it is important, extend buffer space for file data */ + char *tmp = realloc(finfo->b_data, + finfo->b_size + FTP_BUFFER_ALLOCSIZE); + if(tmp) { + finfo->b_size += FTP_BUFFER_ALLOCSIZE; + finfo->b_data = tmp; + } + else { + Curl_fileinfo_dtor(NULL, parser->file_data); + parser->file_data = NULL; + parser->error = CURLE_OUT_OF_MEMORY; + PL_ERROR(conn, CURLE_OUT_OF_MEMORY); + return bufflen; + } + } + + switch (parser->os_type) { + case OS_TYPE_UNIX: + switch (parser->state.UNIX.main) { + case PL_UNIX_TOTALSIZE: + switch(parser->state.UNIX.sub.total_dirsize) { + case PL_UNIX_TOTALSIZE_INIT: + if(c == 't') { + parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING; + parser->item_length++; + } + else { + parser->state.UNIX.main = PL_UNIX_FILETYPE; + /* start FSM again not considering size of directory */ + finfo->b_used = 0; + i--; + } + break; + case PL_UNIX_TOTALSIZE_READING: + parser->item_length++; + if(c == '\r') { + parser->item_length--; + finfo->b_used--; + } + else if(c == '\n') { + finfo->b_data[parser->item_length - 1] = 0; + if(strncmp("total ", finfo->b_data, 6) == 0) { + char *endptr = finfo->b_data+6; + /* here we can deal with directory size, pass the leading white + spaces and then the digits */ + while(ISSPACE(*endptr)) + endptr++; + while(ISDIGIT(*endptr)) + endptr++; + if(*endptr != 0) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + else { + parser->state.UNIX.main = PL_UNIX_FILETYPE; + finfo->b_used = 0; + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + } + break; + case PL_UNIX_FILETYPE: + switch (c) { + case '-': + finfo->filetype = CURLFILETYPE_FILE; + break; + case 'd': + finfo->filetype = CURLFILETYPE_DIRECTORY; + break; + case 'l': + finfo->filetype = CURLFILETYPE_SYMLINK; + break; + case 'p': + finfo->filetype = CURLFILETYPE_NAMEDPIPE; + break; + case 's': + finfo->filetype = CURLFILETYPE_SOCKET; + break; + case 'c': + finfo->filetype = CURLFILETYPE_DEVICE_CHAR; + break; + case 'b': + finfo->filetype = CURLFILETYPE_DEVICE_BLOCK; + break; + case 'D': + finfo->filetype = CURLFILETYPE_DOOR; + break; + default: + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + parser->state.UNIX.main = PL_UNIX_PERMISSION; + parser->item_length = 0; + parser->item_offset = 1; + break; + case PL_UNIX_PERMISSION: + parser->item_length++; + if(parser->item_length <= 9) { + if(!strchr("rwx-tTsS", c)) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + else if(parser->item_length == 10) { + unsigned int perm; + if(c != ' ') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + finfo->b_data[10] = 0; /* terminate permissions */ + perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset); + if(perm & FTP_LP_MALFORMATED_PERM) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM; + parser->file_data->perm = perm; + parser->offsets.perm = parser->item_offset; + + parser->item_length = 0; + parser->state.UNIX.main = PL_UNIX_HLINKS; + parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE; + } + break; + case PL_UNIX_HLINKS: + switch(parser->state.UNIX.sub.hlinks) { + case PL_UNIX_HLINKS_PRESPACE: + if(c != ' ') { + if(c >= '0' && c <= '9') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_HLINKS_NUMBER: + parser->item_length ++; + if(c == ' ') { + char *p; + long int hlinks; + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10); + if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) { + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; + parser->file_data->hardlinks = hlinks; + } + parser->item_length = 0; + parser->item_offset = 0; + parser->state.UNIX.main = PL_UNIX_USER; + parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE; + } + else if(c < '0' || c > '9') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_UNIX_USER: + switch(parser->state.UNIX.sub.user) { + case PL_UNIX_USER_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING; + } + break; + case PL_UNIX_USER_PARSING: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.user = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_GROUP; + parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE; + parser->item_offset = 0; + parser->item_length = 0; + } + break; + } + break; + case PL_UNIX_GROUP: + switch(parser->state.UNIX.sub.group) { + case PL_UNIX_GROUP_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME; + } + break; + case PL_UNIX_GROUP_NAME: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.group = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_SIZE; + parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE; + parser->item_offset = 0; + parser->item_length = 0; + } + break; + } + break; + case PL_UNIX_SIZE: + switch(parser->state.UNIX.sub.size) { + case PL_UNIX_SIZE_PRESPACE: + if(c != ' ') { + if(c >= '0' && c <= '9') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_SIZE_NUMBER: + parser->item_length++; + if(c == ' ') { + char *p; + curl_off_t fsize; + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10); + if(p[0] == '\0' && fsize != CURL_OFF_T_MAX && + fsize != CURL_OFF_T_MIN) { + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->file_data->size = fsize; + } + parser->item_length = 0; + parser->item_offset = 0; + parser->state.UNIX.main = PL_UNIX_TIME; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1; + } + else if(!ISDIGIT(c)) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_UNIX_TIME: + switch(parser->state.UNIX.sub.time) { + case PL_UNIX_TIME_PREPART1: + if(c != ' ') { + if(ISALNUM(c)) { + parser->item_offset = finfo->b_used -1; + parser->item_length = 1; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_TIME_PART1: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2; + } + else if(!ISALNUM(c) && c != '.') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_UNIX_TIME_PREPART2: + parser->item_length++; + if(c != ' ') { + if(ISALNUM(c)) { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_TIME_PART2: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3; + } + else if(!ISALNUM(c) && c != '.') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_UNIX_TIME_PREPART3: + parser->item_length++; + if(c != ' ') { + if(ISALNUM(c)) { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_TIME_PART3: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length -1] = 0; + parser->offsets.time = parser->item_offset; + if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) { + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME; + } + if(finfo->filetype == CURLFILETYPE_SYMLINK) { + parser->state.UNIX.main = PL_UNIX_SYMLINK; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE; + } + else { + parser->state.UNIX.main = PL_UNIX_FILENAME; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE; + } + } + else if(!ISALNUM(c) && c != '.' && c != ':') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_UNIX_FILENAME: + switch(parser->state.UNIX.sub.filename) { + case PL_UNIX_FILENAME_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME; + } + break; + case PL_UNIX_FILENAME_NAME: + parser->item_length++; + if(c == '\r') { + parser->item_length--; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL; + } + else if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.filename = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_FILETYPE; + result = ftp_pl_insert_finfo(conn, finfo); + if(result) { + PL_ERROR(conn, result); + return bufflen; + } + } + break; + case PL_UNIX_FILENAME_WINDOWSEOL: + if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length] = 0; + parser->offsets.filename = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_FILETYPE; + result = ftp_pl_insert_finfo(conn, finfo); + if(result) { + PL_ERROR(conn, result); + return bufflen; + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_UNIX_SYMLINK: + switch(parser->state.UNIX.sub.symlink) { + case PL_UNIX_SYMLINK_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_NAME: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1; + } + else if(c == '\r' || c == '\n') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_UNIX_SYMLINK_PRETARGET1: + parser->item_length++; + if(c == '-') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2; + } + else if(c == '\r' || c == '\n') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET2: + parser->item_length++; + if(c == '>') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3; + } + else if(c == '\r' || c == '\n') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET3: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4; + /* now place where is symlink following */ + finfo->b_data[parser->item_offset + parser->item_length - 4] = 0; + parser->offsets.filename = parser->item_offset; + parser->item_length = 0; + parser->item_offset = 0; + } + else if(c == '\r' || c == '\n') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET4: + if(c != '\r' && c != '\n') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET; + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_UNIX_SYMLINK_TARGET: + parser->item_length ++; + if(c == '\r') { + parser->item_length --; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL; + } + else if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.symlink_target = parser->item_offset; + result = ftp_pl_insert_finfo(conn, finfo); + if(result) { + PL_ERROR(conn, result); + return bufflen; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + } + break; + case PL_UNIX_SYMLINK_WINDOWSEOL: + if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.symlink_target = parser->item_offset; + result = ftp_pl_insert_finfo(conn, finfo); + if(result) { + PL_ERROR(conn, result); + return bufflen; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + } + break; + case OS_TYPE_WIN_NT: + switch(parser->state.NT.main) { + case PL_WINNT_DATE: + parser->item_length++; + if(parser->item_length < 9) { + if(!strchr("0123456789-", c)) { /* only simple control */ + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + else if(parser->item_length == 9) { + if(c == ' ') { + parser->state.NT.main = PL_WINNT_TIME; + parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_WINNT_TIME: + parser->item_length++; + switch(parser->state.NT.sub.time) { + case PL_WINNT_TIME_PRESPACE: + if(!ISSPACE(c)) { + parser->state.NT.sub.time = PL_WINNT_TIME_TIME; + } + break; + case PL_WINNT_TIME_TIME: + if(c == ' ') { + parser->offsets.time = parser->item_offset; + finfo->b_data[parser->item_offset + parser->item_length -1] = 0; + parser->state.NT.main = PL_WINNT_DIRORSIZE; + parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE; + parser->item_length = 0; + } + else if(!strchr("APM0123456789:", c)) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_WINNT_DIRORSIZE: + switch(parser->state.NT.sub.dirorsize) { + case PL_WINNT_DIRORSIZE_PRESPACE: + if(c == ' ') { + + } + else { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT; + } + break; + case PL_WINNT_DIRORSIZE_CONTENT: + parser->item_length ++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + if(strcmp("", finfo->b_data + parser->item_offset) == 0) { + finfo->filetype = CURLFILETYPE_DIRECTORY; + finfo->size = 0; + } + else { + char *endptr; + finfo->size = curlx_strtoofft(finfo->b_data + + parser->item_offset, + &endptr, 10); + if(!*endptr) { + if(finfo->size == CURL_OFF_T_MAX || + finfo->size == CURL_OFF_T_MIN) { + if(errno == ERANGE) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + /* correct file type */ + parser->file_data->filetype = CURLFILETYPE_FILE; + } + + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->item_length = 0; + parser->state.NT.main = PL_WINNT_FILENAME; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + break; + } + break; + case PL_WINNT_FILENAME: + switch (parser->state.NT.sub.filename) { + case PL_WINNT_FILENAME_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used -1; + parser->item_length = 1; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT; + } + break; + case PL_WINNT_FILENAME_CONTENT: + parser->item_length++; + if(c == '\r') { + parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL; + finfo->b_data[finfo->b_used - 1] = 0; + } + else if(c == '\n') { + parser->offsets.filename = parser->item_offset; + finfo->b_data[finfo->b_used - 1] = 0; + parser->offsets.filename = parser->item_offset; + result = ftp_pl_insert_finfo(conn, finfo); + if(result) { + PL_ERROR(conn, result); + return bufflen; + } + parser->state.NT.main = PL_WINNT_DATE; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + break; + case PL_WINNT_FILENAME_WINEOL: + if(c == '\n') { + parser->offsets.filename = parser->item_offset; + result = ftp_pl_insert_finfo(conn, finfo); + if(result) { + PL_ERROR(conn, result); + return bufflen; + } + parser->state.NT.main = PL_WINNT_DATE; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + } + break; + default: + return bufflen + 1; + } + + i++; + } + + return bufflen; +} + +#endif /* CURL_DISABLE_FTP */ diff --git a/libcurl/src/lib/ftplistparser.h b/libcurl/src/lib/ftplistparser.h new file mode 100644 index 0000000..be3afdb --- /dev/null +++ b/libcurl/src/lib/ftplistparser.h @@ -0,0 +1,41 @@ +#ifndef HEADER_CURL_FTPLISTPARSER_H +#define HEADER_CURL_FTPLISTPARSER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +/* WRITEFUNCTION callback for parsing LIST responses */ +CURL_STATIC size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, + void *connptr); + +struct ftp_parselist_data; /* defined inside ftplibparser.c */ + +CURL_STATIC CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data); + +CURL_STATIC struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void); + +CURL_STATIC void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data); + +#endif /* CURL_DISABLE_FTP */ +#endif /* HEADER_CURL_FTPLISTPARSER_H */ diff --git a/libcurl/src/lib/getenv.c b/libcurl/src/lib/getenv.c new file mode 100644 index 0000000..2e31d6f --- /dev/null +++ b/libcurl/src/lib/getenv.c @@ -0,0 +1,53 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "curl_memory.h" + +#include "memdebug.h" + +static +char *GetEnv(const char *variable) +{ +#if defined(_WIN32_WCE) || defined(_DURANGO) || defined(CURL_WINRT) + return NULL; +#else +#ifdef WIN32 + char env[MAX_PATH]; /* MAX_PATH is from windef.h */ + char *temp = getenv(variable); + env[0] = '\0'; + if(temp != NULL) + ExpandEnvironmentStringsA(temp, env, sizeof(env)); + return (env[0] != '\0')?strdup(env):NULL; +#else + char *env = getenv(variable); + return (env && env[0])?strdup(env):NULL; +#endif +#endif +} + +char *curl_getenv(const char *v) +{ + return GetEnv(v); +} diff --git a/libcurl/src/lib/getinfo.c b/libcurl/src/lib/getinfo.c new file mode 100644 index 0000000..577247b --- /dev/null +++ b/libcurl/src/lib/getinfo.c @@ -0,0 +1,382 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "getinfo.h" + +#include "vtls/vtls.h" +#include "connect.h" /* Curl_getconnectinfo() */ +#include "progress.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * This is supposed to be called in the beginning of a perform() session + * and should reset all session-info variables + */ +CURL_STATIC CURLcode Curl_initinfo(struct SessionHandle *data) +{ + struct Progress *pro = &data->progress; + struct PureInfo *info = &data->info; + + pro->t_nslookup = 0; + pro->t_connect = 0; + pro->t_appconnect = 0; + pro->t_pretransfer = 0; + pro->t_starttransfer = 0; + pro->timespent = 0; + pro->t_redirect = 0; + + info->httpcode = 0; + info->httpproxycode = 0; + info->httpversion = 0; + info->filetime = -1; /* -1 is an illegal time and thus means unknown */ + info->timecond = FALSE; + + free(info->contenttype); + info->contenttype = NULL; + + info->header_size = 0; + info->request_size = 0; + info->numconnects = 0; + + info->conn_primary_ip[0] = '\0'; + info->conn_local_ip[0] = '\0'; + info->conn_primary_port = 0; + info->conn_local_port = 0; + + return CURLE_OK; +} + +static CURLcode getinfo_char(struct SessionHandle *data, CURLINFO info, + char **param_charp) +{ + switch(info) { + case CURLINFO_EFFECTIVE_URL: + *param_charp = data->change.url?data->change.url:(char *)""; + break; + case CURLINFO_CONTENT_TYPE: + *param_charp = data->info.contenttype; + break; + case CURLINFO_PRIVATE: + *param_charp = (char *) data->set.private_data; + break; + case CURLINFO_FTP_ENTRY_PATH: + /* Return the entrypath string from the most recent connection. + This pointer was copied from the connectdata structure by FTP. + The actual string may be free()ed by subsequent libcurl calls so + it must be copied to a safer area before the next libcurl call. + Callers must never free it themselves. */ + *param_charp = data->state.most_recent_ftp_entrypath; + break; + case CURLINFO_REDIRECT_URL: + /* Return the URL this request would have been redirected to if that + option had been enabled! */ + *param_charp = data->info.wouldredirect; + break; + case CURLINFO_PRIMARY_IP: + /* Return the ip address of the most recent (primary) connection */ + *param_charp = data->info.conn_primary_ip; + break; + case CURLINFO_LOCAL_IP: + /* Return the source/local ip address of the most recent (primary) + connection */ + *param_charp = data->info.conn_local_ip; + break; + case CURLINFO_RTSP_SESSION_ID: + *param_charp = data->set.str[STRING_RTSP_SESSION_ID]; + break; + + default: + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + return CURLE_OK; +} + +static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info, + long *param_longp) +{ + curl_socket_t sockfd; + + union { + unsigned long *to_ulong; + long *to_long; + } lptr; + + switch(info) { + case CURLINFO_RESPONSE_CODE: + *param_longp = data->info.httpcode; + break; + case CURLINFO_HTTP_CONNECTCODE: + *param_longp = data->info.httpproxycode; + break; + case CURLINFO_FILETIME: + *param_longp = data->info.filetime; + break; + case CURLINFO_HEADER_SIZE: + *param_longp = data->info.header_size; + break; + case CURLINFO_REQUEST_SIZE: + *param_longp = data->info.request_size; + break; + case CURLINFO_SSL_VERIFYRESULT: + *param_longp = data->set.ssl.certverifyresult; + break; + case CURLINFO_REDIRECT_COUNT: + *param_longp = data->set.followlocation; + break; + case CURLINFO_HTTPAUTH_AVAIL: + lptr.to_long = param_longp; + *lptr.to_ulong = data->info.httpauthavail; + break; + case CURLINFO_PROXYAUTH_AVAIL: + lptr.to_long = param_longp; + *lptr.to_ulong = data->info.proxyauthavail; + break; + case CURLINFO_OS_ERRNO: + *param_longp = data->state.os_errno; + break; + case CURLINFO_NUM_CONNECTS: + *param_longp = data->info.numconnects; + break; + case CURLINFO_LASTSOCKET: + sockfd = Curl_getconnectinfo(data, NULL); + + /* note: this is not a good conversion for systems with 64 bit sockets and + 32 bit longs */ + if(sockfd != CURL_SOCKET_BAD) + *param_longp = (long)sockfd; + else + /* this interface is documented to return -1 in case of badness, which + may not be the same as the CURL_SOCKET_BAD value */ + *param_longp = -1; + break; + case CURLINFO_PRIMARY_PORT: + /* Return the (remote) port of the most recent (primary) connection */ + *param_longp = data->info.conn_primary_port; + break; + case CURLINFO_LOCAL_PORT: + /* Return the local port of the most recent (primary) connection */ + *param_longp = data->info.conn_local_port; + break; + case CURLINFO_CONDITION_UNMET: + /* return if the condition prevented the document to get transferred */ + *param_longp = data->info.timecond ? 1L : 0L; + break; + case CURLINFO_RTSP_CLIENT_CSEQ: + *param_longp = data->state.rtsp_next_client_CSeq; + break; + case CURLINFO_RTSP_SERVER_CSEQ: + *param_longp = data->state.rtsp_next_server_CSeq; + break; + case CURLINFO_RTSP_CSEQ_RECV: + *param_longp = data->state.rtsp_CSeq_recv; + break; + + default: + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + return CURLE_OK; +} + +static CURLcode getinfo_double(struct SessionHandle *data, CURLINFO info, + double *param_doublep) +{ + switch(info) { + case CURLINFO_TOTAL_TIME: + *param_doublep = data->progress.timespent; + break; + case CURLINFO_NAMELOOKUP_TIME: + *param_doublep = data->progress.t_nslookup; + break; + case CURLINFO_CONNECT_TIME: + *param_doublep = data->progress.t_connect; + break; + case CURLINFO_APPCONNECT_TIME: + *param_doublep = data->progress.t_appconnect; + break; + case CURLINFO_PRETRANSFER_TIME: + *param_doublep = data->progress.t_pretransfer; + break; + case CURLINFO_STARTTRANSFER_TIME: + *param_doublep = data->progress.t_starttransfer; + break; + case CURLINFO_SIZE_UPLOAD: + *param_doublep = (double)data->progress.uploaded; + break; + case CURLINFO_SIZE_DOWNLOAD: + *param_doublep = (double)data->progress.downloaded; + break; + case CURLINFO_SPEED_DOWNLOAD: + *param_doublep = (double)data->progress.dlspeed; + break; + case CURLINFO_SPEED_UPLOAD: + *param_doublep = (double)data->progress.ulspeed; + break; + case CURLINFO_CONTENT_LENGTH_DOWNLOAD: + *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)? + (double)data->progress.size_dl:-1; + break; + case CURLINFO_CONTENT_LENGTH_UPLOAD: + *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)? + (double)data->progress.size_ul:-1; + break; + case CURLINFO_REDIRECT_TIME: + *param_doublep = data->progress.t_redirect; + break; + + default: + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + return CURLE_OK; +} + +static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info, + struct curl_slist **param_slistp) +{ + union { + struct curl_certinfo *to_certinfo; + struct curl_slist *to_slist; + } ptr; + + switch(info) { + case CURLINFO_SSL_ENGINES: + *param_slistp = Curl_ssl_engines_list(data); + break; + case CURLINFO_COOKIELIST: + *param_slistp = Curl_cookie_list(data); + break; + case CURLINFO_CERTINFO: + /* Return the a pointer to the certinfo struct. Not really an slist + pointer but we can pretend it is here */ + ptr.to_certinfo = &data->info.certs; + *param_slistp = ptr.to_slist; + break; + case CURLINFO_TLS_SESSION: + { + struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **) + param_slistp; + struct curl_tlssessioninfo *tsi = &data->tsi; + struct connectdata *conn = data->easy_conn; + unsigned int sockindex = 0; + void *internals = NULL; + + *tsip = tsi; + tsi->backend = CURLSSLBACKEND_NONE; + tsi->internals = NULL; + + if(!conn) + break; + + /* Find the active ("in use") SSL connection, if any */ + while((sockindex < sizeof(conn->ssl) / sizeof(conn->ssl[0])) && + (!conn->ssl[sockindex].use)) + sockindex++; + + if(sockindex == sizeof(conn->ssl) / sizeof(conn->ssl[0])) + break; /* no SSL session found */ + + /* Return the TLS session information from the relevant backend */ +#ifdef USE_OPENSSL + internals = conn->ssl[sockindex].ctx; +#endif +#ifdef USE_GNUTLS + internals = conn->ssl[sockindex].session; +#endif +#ifdef USE_NSS + internals = conn->ssl[sockindex].handle; +#endif +#ifdef USE_GSKIT + internals = conn->ssl[sockindex].handle; +#endif + if(internals) { + tsi->backend = Curl_ssl_backend(); + tsi->internals = internals; + } + /* 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 + backend as CURLSSLBACKEND_NONE in those cases, which should be + interpreted as "not supported" */ + } + break; + default: + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) +{ + va_list arg; + long *param_longp = NULL; + double *param_doublep = NULL; + char **param_charp = NULL; + struct curl_slist **param_slistp = NULL; + int type; + /* default return code is to error out! */ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + + if(!data) + return result; + + va_start(arg, info); + + type = CURLINFO_TYPEMASK & (int)info; + switch(type) { + case CURLINFO_STRING: + param_charp = va_arg(arg, char **); + if(param_charp) + result = getinfo_char(data, info, param_charp); + break; + case CURLINFO_LONG: + param_longp = va_arg(arg, long *); + if(param_longp) + result = getinfo_long(data, info, param_longp); + break; + case CURLINFO_DOUBLE: + param_doublep = va_arg(arg, double *); + if(param_doublep) + result = getinfo_double(data, info, param_doublep); + break; + case CURLINFO_SLIST: + param_slistp = va_arg(arg, struct curl_slist **); + if(param_slistp) + result = getinfo_slist(data, info, param_slistp); + break; + default: + break; + } + + va_end(arg); + + return result; +} diff --git a/libcurl/src/lib/getinfo.h b/libcurl/src/lib/getinfo.h new file mode 100644 index 0000000..1cecdf3 --- /dev/null +++ b/libcurl/src/lib/getinfo.h @@ -0,0 +1,27 @@ +#ifndef HEADER_CURL_GETINFO_H +#define HEADER_CURL_GETINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +CURL_STATIC CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...); +CURL_STATIC CURLcode Curl_initinfo(struct SessionHandle *data); + +#endif /* HEADER_CURL_GETINFO_H */ diff --git a/libcurl/src/lib/gopher.c b/libcurl/src/lib/gopher.c new file mode 100644 index 0000000..954cad8 --- /dev/null +++ b/libcurl/src/lib/gopher.c @@ -0,0 +1,165 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_GOPHER + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" + +#include "progress.h" +#include "strequal.h" +#include "gopher.h" +#include "rawstr.h" +#include "select.h" +#include "url.h" +#include "warnless.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static CURLcode gopher_do(struct connectdata *conn, bool *done); + +/* + * Gopher protocol handler. + * This is also a nice simple template to build off for simple + * connect-command-download protocols. + */ + +const struct Curl_handler Curl_handler_gopher = { + "GOPHER", /* scheme */ + ZERO_NULL, /* setup_connection */ + gopher_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_GOPHER, /* defport */ + CURLPROTO_GOPHER, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +static CURLcode gopher_do(struct connectdata *conn, bool *done) +{ + CURLcode result=CURLE_OK; + struct SessionHandle *data=conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + + curl_off_t *bytecount = &data->req.bytecount; + char *path = data->state.path; + char *sel; + char *sel_org = NULL; + ssize_t amount, k; + + *done = TRUE; /* unconditionally */ + + /* Create selector. Degenerate cases: / and /1 => convert to "" */ + if(strlen(path) <= 2) + sel = (char *)""; + else { + char *newp; + size_t j, i; + int len; + + /* Otherwise, drop / and the first character (i.e., item type) ... */ + newp = path; + newp+=2; + + /* ... then turn ? into TAB for search servers, Veronica, etc. ... */ + j = strlen(newp); + for(i=0; i, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_GOPHER +extern const struct Curl_handler Curl_handler_gopher; +#endif + +#endif /* HEADER_CURL_GOPHER_H */ diff --git a/libcurl/src/lib/hash.c b/libcurl/src/lib/hash.c new file mode 100644 index 0000000..6218cdb --- /dev/null +++ b/libcurl/src/lib/hash.c @@ -0,0 +1,396 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "hash.h" +#include "llist.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +static void +hash_element_dtor(void *user, void *element) +{ + struct curl_hash *h = (struct curl_hash *) user; + struct curl_hash_element *e = (struct curl_hash_element *) element; + + Curl_safefree(e->key); + + if(e->ptr) { + h->dtor(e->ptr); + e->ptr = NULL; + } + + e->key_len = 0; + + free(e); +} + +/* return 1 on error, 0 is fine */ +CURL_STATIC int +Curl_hash_init(struct curl_hash *h, + int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor) +{ + int i; + + if(!slots || !hfunc || !comparator ||!dtor) { + return 1; /* failure */ + } + + h->hash_func = hfunc; + h->comp_func = comparator; + h->dtor = dtor; + h->size = 0; + h->slots = slots; + + h->table = malloc(slots * sizeof(struct curl_llist *)); + if(h->table) { + for(i = 0; i < slots; ++i) { + h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor); + if(!h->table[i]) { + while(i--) { + Curl_llist_destroy(h->table[i], NULL); + h->table[i] = NULL; + } + free(h->table); + h->table = NULL; + h->slots = 0; + return 1; /* failure */ + } + } + return 0; /* fine */ + } + else { + h->slots = 0; + return 1; /* failure */ + } +} + +CURL_STATIC struct curl_hash * +Curl_hash_alloc(int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor) +{ + struct curl_hash *h; + + if(!slots || !hfunc || !comparator ||!dtor) { + return NULL; /* failure */ + } + + h = malloc(sizeof(struct curl_hash)); + if(h) { + if(Curl_hash_init(h, slots, hfunc, comparator, dtor)) { + /* failure */ + free(h); + h = NULL; + } + } + + return h; +} + + + +static struct curl_hash_element * +mk_hash_element(const void *key, size_t key_len, const void *p) +{ + struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element)); + + if(he) { + void *dupkey = malloc(key_len); + if(dupkey) { + /* copy the key */ + memcpy(dupkey, key, key_len); + + he->key = dupkey; + he->key_len = key_len; + he->ptr = (void *) p; + } + else { + /* failed to duplicate the key, free memory and fail */ + free(he); + he = NULL; + } + } + return he; +} + +#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)] + +/* Insert the data in the hash. If there already was a match in the hash, + * that data is replaced. + * + * @unittest: 1305 + */ +CURL_STATIC void * +Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p) +{ + struct curl_hash_element *he; + struct curl_llist_element *le; + struct curl_llist *l = FETCH_LIST (h, key, key_len); + + for(le = l->head; le; le = le->next) { + he = (struct curl_hash_element *) le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + Curl_llist_remove(l, le, (void *)h); + --h->size; + break; + } + } + + he = mk_hash_element(key, key_len, p); + if(he) { + if(Curl_llist_insert_next(l, l->tail, he)) { + ++h->size; + return p; /* return the new entry */ + } + /* + * Couldn't insert it, destroy the 'he' element and the key again. We + * don't call hash_element_dtor() since that would also call the + * "destructor" for the actual data 'p'. When we fail, we shall not touch + * that data. + */ + free(he->key); + free(he); + } + + return NULL; /* failure */ +} + +/* remove the identified hash entry, returns non-zero on failure */ +CURL_STATIC int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len) +{ + struct curl_llist_element *le; + struct curl_hash_element *he; + struct curl_llist *l = FETCH_LIST(h, key, key_len); + + for(le = l->head; le; le = le->next) { + he = le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + Curl_llist_remove(l, le, (void *) h); + --h->size; + return 0; + } + } + return 1; +} + +CURL_STATIC void * +Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len) +{ + struct curl_llist_element *le; + struct curl_hash_element *he; + struct curl_llist *l; + + if(h) { + l = FETCH_LIST(h, key, key_len); + for(le = l->head; le; le = le->next) { + he = le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + return he->ptr; + } + } + } + + return NULL; +} + +#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST) +CURL_STATIC void +Curl_hash_apply(curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)) +{ + struct curl_llist_element *le; + int i; + + for(i = 0; i < h->slots; ++i) { + for(le = (h->table[i])->head; + le; + le = le->next) { + curl_hash_element *el = le->ptr; + cb(user, el->ptr); + } + } +} +#endif + +CURL_STATIC void +Curl_hash_clean(struct curl_hash *h) +{ + int i; + + for(i = 0; i < h->slots; ++i) { + Curl_llist_destroy(h->table[i], (void *) h); + h->table[i] = NULL; + } + + Curl_safefree(h->table); + h->size = 0; + h->slots = 0; +} + +CURL_STATIC void +Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, + int (*comp)(void *, void *)) +{ + struct curl_llist_element *le; + struct curl_llist_element *lnext; + struct curl_llist *list; + int i; + + if(!h) + return; + + for(i = 0; i < h->slots; ++i) { + list = h->table[i]; + le = list->head; /* get first list entry */ + while(le) { + struct curl_hash_element *he = le->ptr; + lnext = le->next; + /* ask the callback function if we shall remove this entry or not */ + if(comp(user, he->ptr)) { + Curl_llist_remove(list, le, (void *) h); + --h->size; /* one less entry in the hash now */ + } + le = lnext; + } + } +} + +CURL_STATIC void +Curl_hash_destroy(struct curl_hash *h) +{ + if(!h) + return; + + Curl_hash_clean(h); + + free(h); +} + +CURL_STATIC size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num) +{ + const char* key_str = (const char *) key; + const char *end = key_str + key_length; + unsigned long h = 5381; + + while(key_str < end) { + h += h << 5; + h ^= (unsigned long) *key_str++; + } + + return (h % slots_num); +} + +CURL_STATIC size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, size_t key2_len) +{ + char *key1 = (char *)k1; + char *key2 = (char *)k2; + + if(key1_len == key2_len && + *key1 == *key2 && + memcmp(key1, key2, key1_len) == 0) { + return 1; + } + + return 0; +} + +CURL_STATIC void Curl_hash_start_iterate(struct curl_hash *hash, + struct curl_hash_iterator *iter) +{ + iter->hash = hash; + iter->slot_index = 0; + iter->current_element = NULL; +} + +CURL_STATIC struct curl_hash_element * +Curl_hash_next_element(struct curl_hash_iterator *iter) +{ + int i; + struct curl_hash *h = iter->hash; + + /* Get the next element in the current list, if any */ + if(iter->current_element) + iter->current_element = iter->current_element->next; + + /* If we have reached the end of the list, find the next one */ + if(!iter->current_element) { + for(i = iter->slot_index;i < h->slots;i++) { + if(h->table[i]->head) { + iter->current_element = h->table[i]->head; + iter->slot_index = i+1; + break; + } + } + } + + if(iter->current_element) { + struct curl_hash_element *he = iter->current_element->ptr; + return he; + } + else { + iter->current_element = NULL; + return NULL; + } +} + +#if 0 /* useful function for debugging hashes and their contents */ +CURL_STATIC void Curl_hash_print(struct curl_hash *h, + void (*func)(void *)) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + int last_index = -1; + + if(!h) + return; + + fprintf(stderr, "=Hash dump=\n"); + + Curl_hash_start_iterate(h, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + if(iter.slot_index != last_index) { + fprintf(stderr, "index %d:", iter.slot_index); + if(last_index >= 0) { + fprintf(stderr, "\n"); + } + last_index = iter.slot_index; + } + + if(func) + func(he->ptr); + else + fprintf(stderr, " [%p]", (void *)he->ptr); + + he = Curl_hash_next_element(&iter); + } + fprintf(stderr, "\n"); +} +#endif diff --git a/libcurl/src/lib/hash.h b/libcurl/src/lib/hash.h new file mode 100644 index 0000000..02c304a --- /dev/null +++ b/libcurl/src/lib/hash.h @@ -0,0 +1,106 @@ +#ifndef HEADER_CURL_HASH_H +#define HEADER_CURL_HASH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "llist.h" + +/* Hash function prototype */ +typedef size_t (*hash_function) (void* key, + size_t key_length, + size_t slots_num); + +/* + Comparator function prototype. Compares two keys. +*/ +typedef size_t (*comp_function) (void* key1, + size_t key1_len, + void*key2, + size_t key2_len); + +typedef void (*curl_hash_dtor)(void *); + +struct curl_hash { + struct curl_llist **table; + + /* Hash function to be used for this hash table */ + hash_function hash_func; + + /* Comparator function to compare keys */ + comp_function comp_func; + curl_hash_dtor dtor; + int slots; + size_t size; +}; + +struct curl_hash_element { + void *ptr; + char *key; + size_t key_len; +}; + +struct curl_hash_iterator { + struct curl_hash *hash; + int slot_index; + struct curl_llist_element *current_element; +}; + +CURL_STATIC int Curl_hash_init(struct curl_hash *h, + int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor); + +CURL_STATIC struct curl_hash *Curl_hash_alloc(int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor); + +CURL_STATIC void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p); +CURL_STATIC int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len); +CURL_STATIC void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len); +CURL_STATIC void Curl_hash_apply(struct curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)); +CURL_STATIC int Curl_hash_count(struct curl_hash *h); +CURL_STATIC void Curl_hash_clean(struct curl_hash *h); +CURL_STATIC void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, + int (*comp)(void *, void *)); +CURL_STATIC void Curl_hash_destroy(struct curl_hash *h); + +CURL_STATIC size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num); +CURL_STATIC size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, + size_t key2_len); + +CURL_STATIC void Curl_hash_start_iterate(struct curl_hash *hash, + struct curl_hash_iterator *iter); +CURL_STATIC struct curl_hash_element * +Curl_hash_next_element(struct curl_hash_iterator *iter); + +CURL_STATIC void Curl_hash_print(struct curl_hash *h, + void (*func)(void *)); + + +#endif /* HEADER_CURL_HASH_H */ diff --git a/libcurl/src/lib/hmac.c b/libcurl/src/lib/hmac.c new file mode 100644 index 0000000..4aa2e23 --- /dev/null +++ b/libcurl/src/lib/hmac.c @@ -0,0 +1,129 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2104 Keyed-Hashing for Message Authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +#include "curl_hmac.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Generic HMAC algorithm. + * + * This module computes HMAC digests based on any hash function. Parameters + * and computing procedures are set-up dynamically at HMAC computation + * context initialisation. + */ + +static const unsigned char hmac_ipad = 0x36; +static const unsigned char hmac_opad = 0x5C; + + + +CURL_STATIC HMAC_context * +Curl_HMAC_init(const HMAC_params * hashparams, + const unsigned char * key, + unsigned int keylen) +{ + size_t i; + HMAC_context * ctxt; + unsigned char * hkey; + unsigned char b; + + /* Create HMAC context. */ + i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize + + hashparams->hmac_resultlen; + ctxt = malloc(i); + + if(!ctxt) + return ctxt; + + ctxt->hmac_hash = hashparams; + ctxt->hmac_hashctxt1 = (void *) (ctxt + 1); + ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 + + hashparams->hmac_ctxtsize); + + /* If the key is too long, replace it by its hash digest. */ + if(keylen > hashparams->hmac_maxkeylen) { + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen); + hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize; + (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1); + key = hkey; + keylen = hashparams->hmac_resultlen; + } + + /* Prime the two hash contexts with the modified key. */ + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2); + + for(i = 0; i < keylen; i++) { + b = (unsigned char)(*key ^ hmac_ipad); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1); + b = (unsigned char)(*key++ ^ hmac_opad); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1); + } + + for(; i < hashparams->hmac_maxkeylen; i++) { + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1); + } + + /* Done, return pointer to HMAC context. */ + return ctxt; +} + +CURL_STATIC int Curl_HMAC_update(HMAC_context * ctxt, + const unsigned char * data, + unsigned int len) +{ + /* Update first hash calculation. */ + (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len); + return 0; +} + + +CURL_STATIC int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result) +{ + const HMAC_params * hashparams = ctxt->hmac_hash; + + /* Do not get result if called with a null parameter: only release + storage. */ + + if(!result) + result = (unsigned char *) ctxt->hmac_hashctxt2 + + ctxt->hmac_hash->hmac_ctxtsize; + + (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, + result, hashparams->hmac_resultlen); + (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2); + free((char *) ctxt); + return 0; +} + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libcurl/src/lib/hostasyn.c b/libcurl/src/lib/hostasyn.c new file mode 100644 index 0000000..92a8296 --- /dev/null +++ b/libcurl/src/lib/hostasyn.c @@ -0,0 +1,153 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/*********************************************************************** + * Only for builds using asynchronous name resolves + **********************************************************************/ +#ifdef CURLRES_ASYNCH + +/* + * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread() + * or getaddrinfo_thread() when we got the name resolved (or not!). + * + * If the status argument is CURL_ASYNC_SUCCESS, this function takes + * ownership of the Curl_addrinfo passed, storing the resolved data + * in the DNS cache. + * + * The storage operation locks and unlocks the DNS cache. + */ +CURL_STATIC CURLcode Curl_addrinfo_callback(struct connectdata *conn, + int status, + struct Curl_addrinfo *ai) +{ + struct Curl_dns_entry *dns = NULL; + CURLcode result = CURLE_OK; + + conn->async.status = status; + + if(CURL_ASYNC_SUCCESS == status) { + if(ai) { + struct SessionHandle *data = conn->data; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = Curl_cache_addr(data, ai, + conn->async.hostname, + conn->async.port); + if(!dns) { + /* failed to store, cleanup and return error */ + Curl_freeaddrinfo(ai); + result = CURLE_OUT_OF_MEMORY; + } + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + } + else { + result = CURLE_OUT_OF_MEMORY; + } + } + + conn->async.dns = dns; + + /* Set async.done TRUE last in this function since it may be used multi- + threaded and once this is TRUE the other thread may read fields from the + async struct */ + conn->async.done = TRUE; + + /* IPv4: The input hostent struct will be freed by ares when we return from + this function */ + return result; +} + +/* Call this function after Curl_connect() has returned async=TRUE and + then a successful name resolve has been received. + + Note: this function disconnects and frees the conn data in case of + resolve failure */ +CURL_STATIC CURLcode Curl_async_resolved(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result; + + if(conn->async.dns) { + conn->dns_entry = conn->async.dns; + conn->async.dns = NULL; + } + + result = Curl_setup_conn(conn, protocol_done); + + if(result) + /* We're not allowed to return failure with memory left allocated + in the connectdata struct, free those here */ + Curl_disconnect(conn, FALSE); /* close the connection */ + + return result; +} + +/* + * Curl_getaddrinfo() is the generic low-level name resolve API within this + * source file. There are several versions of this function - for different + * name resolve layers (selected at build-time). They all take this same set + * of arguments + */ +CURL_STATIC Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + return Curl_resolver_getaddrinfo(conn, hostname, port, waitp); +} + +#endif /* CURLRES_ASYNCH */ diff --git a/libcurl/src/lib/hostcheck.c b/libcurl/src/lib/hostcheck.c new file mode 100644 index 0000000..1bc330d --- /dev/null +++ b/libcurl/src/lib/hostcheck.c @@ -0,0 +1,147 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT) +/* these backends use functions from this file */ + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#include "hostcheck.h" +#include "rawstr.h" +#include "inet_pton.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Match a hostname against a wildcard pattern. + * E.g. + * "foo.host.com" matches "*.host.com". + * + * We use the matching rule described in RFC6125, section 6.4.3. + * http://tools.ietf.org/html/rfc6125#section-6.4.3 + * + * In addition: ignore trailing dots in the host names and wildcards, so that + * the names are used normalized. This is what the browsers do. + * + * Do not allow wildcard matching on IP numbers. There are apparently + * certificates being used with an IP address in the CN field, thus making no + * apparent distinction between a name and an IP. We need to detect the use of + * an IP address and not wildcard match on such names. + * + * NOTE: hostmatch() gets called with copied buffers so that it can modify the + * contents at will. + */ + +static int hostmatch(char *hostname, char *pattern) +{ + const char *pattern_label_end, *pattern_wildcard, *hostname_label_end; + int wildcard_enabled; + size_t prefixlen, suffixlen; + struct in_addr ignored; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 si6; +#endif + + /* normalize pattern and hostname by stripping off trailing dots */ + size_t len = strlen(hostname); + if(hostname[len-1]=='.') + hostname[len-1]=0; + len = strlen(pattern); + if(pattern[len-1]=='.') + pattern[len-1]=0; + + pattern_wildcard = strchr(pattern, '*'); + if(pattern_wildcard == NULL) + return Curl_raw_equal(pattern, hostname) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; + + /* detect IP address as hostname and fail the match if so */ + if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0) + return CURL_HOST_NOMATCH; +#ifdef ENABLE_IPV6 + else if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0) + return CURL_HOST_NOMATCH; +#endif + + /* We require at least 2 dots in pattern to avoid too wide wildcard + match. */ + wildcard_enabled = 1; + pattern_label_end = strchr(pattern, '.'); + if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL || + pattern_wildcard > pattern_label_end || + Curl_raw_nequal(pattern, "xn--", 4)) { + wildcard_enabled = 0; + } + if(!wildcard_enabled) + return Curl_raw_equal(pattern, hostname) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; + + hostname_label_end = strchr(hostname, '.'); + if(hostname_label_end == NULL || + !Curl_raw_equal(pattern_label_end, hostname_label_end)) + return CURL_HOST_NOMATCH; + + /* The wildcard must match at least one character, so the left-most + label of the hostname is at least as large as the left-most label + of the pattern. */ + if(hostname_label_end - hostname < pattern_label_end - pattern) + return CURL_HOST_NOMATCH; + + prefixlen = pattern_wildcard - pattern; + suffixlen = pattern_label_end - (pattern_wildcard+1); + return Curl_raw_nequal(pattern, hostname, prefixlen) && + Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen, + suffixlen) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; +} + +CURL_STATIC int Curl_cert_hostcheck(const char *match_pattern, const char *hostname) +{ + char *matchp; + char *hostp; + int res = 0; + if(!match_pattern || !*match_pattern || + !hostname || !*hostname) /* sanity check */ + ; + else { + matchp = strdup(match_pattern); + if(matchp) { + hostp = strdup(hostname); + if(hostp) { + if(hostmatch(hostp, matchp) == CURL_HOST_MATCH) + res= 1; + free(hostp); + } + free(matchp); + } + } + + return res; +} + +#endif /* OPENSSL or AXTLS or GSKIT */ diff --git a/libcurl/src/lib/hostcheck.h b/libcurl/src/lib/hostcheck.h new file mode 100644 index 0000000..596ca4d --- /dev/null +++ b/libcurl/src/lib/hostcheck.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_HOSTCHECK_H +#define HEADER_CURL_HOSTCHECK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#define CURL_HOST_NOMATCH 0 +#define CURL_HOST_MATCH 1 +CURL_STATIC int Curl_cert_hostcheck(const char *match_pattern, const char *hostname); + +#endif /* HEADER_CURL_HOSTCHECK_H */ + diff --git a/libcurl/src/lib/hostip.c b/libcurl/src/lib/hostip.c new file mode 100644 index 0000000..b58eedd --- /dev/null +++ b/libcurl/src/lib/hostip.c @@ -0,0 +1,879 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_SETJMP_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_ntop.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#if defined(CURLRES_SYNCH) && \ + defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP) +/* alarm-based timeouts can only be used with all the dependencies satisfied */ +#define USE_ALARM_TIMEOUT +#endif + +/* + * hostip.c explained + * ================== + * + * The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c + * source file are these: + * + * CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use + * that. The host may not be able to resolve IPv6, but we don't really have to + * take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4 + * defined. + * + * CURLRES_ARES - is defined if libcurl is built to use c-ares for + * asynchronous name resolves. This can be Windows or *nix. + * + * CURLRES_THREADED - is defined if libcurl is built to run under (native) + * Windows, and then the name resolve will be done in a new thread, and the + * supported API will be the same as for ares-builds. + * + * If any of the two previous are defined, CURLRES_ASYNCH is defined too. If + * libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is + * defined. + * + * The host*.c sources files are split up like this: + * + * hostip.c - method-independent resolver functions and utility functions + * hostasyn.c - functions for asynchronous name resolves + * hostsyn.c - functions for synchronous name resolves + * hostip4.c - IPv4 specific functions + * hostip6.c - IPv6 specific functions + * + * The two asynchronous name resolver backends are implemented in: + * asyn-ares.c - functions for ares-using name resolves + * asyn-thread.c - functions for threaded name resolves + + * The hostip.h is the united header file for all this. It defines the + * CURLRES_* defines based on the config*.h and curl_setup.h defines. + */ + +/* These two symbols are for the global DNS cache */ +static struct curl_hash hostname_cache; +static int host_cache_initialized; + +static void freednsentry(void *freethis); + +/* + * Curl_global_host_cache_init() initializes and sets up a global DNS cache. + * Global DNS cache is general badness. Do not use. This will be removed in + * a future version. Use the share interface instead! + * + * Returns a struct curl_hash pointer on success, NULL on failure. + */ +CURL_STATIC struct curl_hash *Curl_global_host_cache_init(void) +{ + int rc = 0; + if(!host_cache_initialized) { + rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str, + Curl_str_key_compare, freednsentry); + if(!rc) + host_cache_initialized = 1; + } + return rc?NULL:&hostname_cache; +} + +/* + * Destroy and cleanup the global DNS cache + */ +CURL_STATIC void Curl_global_host_cache_dtor(void) +{ + if(host_cache_initialized) { + Curl_hash_clean(&hostname_cache); + host_cache_initialized = 0; + } +} + +/* + * Return # of adresses in a Curl_addrinfo struct + */ +CURL_STATIC int Curl_num_addresses(const Curl_addrinfo *addr) +{ + int i = 0; + while(addr) { + addr = addr->ai_next; + i++; + } + return i; +} + +/* + * Curl_printable_address() returns a printable version of the 1st address + * given in the 'ai' argument. The result will be stored in the buf that is + * bufsize bytes big. + * + * If the conversion fails, it returns NULL. + */ +CURL_STATIC const char * +Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize) +{ + const struct sockaddr_in *sa4; + const struct in_addr *ipaddr4; +#ifdef ENABLE_IPV6 + const struct sockaddr_in6 *sa6; + const struct in6_addr *ipaddr6; +#endif + + switch (ai->ai_family) { + case AF_INET: + sa4 = (const void *)ai->ai_addr; + ipaddr4 = &sa4->sin_addr; + return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, + bufsize); +#ifdef ENABLE_IPV6 + case AF_INET6: + sa6 = (const void *)ai->ai_addr; + ipaddr6 = &sa6->sin6_addr; + return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, + bufsize); +#endif + default: + break; + } + return NULL; +} + +/* + * Return a hostcache id string for the provided host + port, to be used by + * the DNS caching. + */ +static char * +create_hostcache_id(const char *name, int port) +{ + /* create and return the new allocated entry */ + char *id = aprintf("%s:%d", name, port); + char *ptr = id; + if(ptr) { + /* lower case the name part */ + while(*ptr && (*ptr != ':')) { + *ptr = (char)TOLOWER(*ptr); + ptr++; + } + } + return id; +} + +struct hostcache_prune_data { + long cache_timeout; + time_t now; +}; + +/* + * This function is set as a callback to be called for every entry in the DNS + * cache when we want to prune old unused entries. + * + * Returning non-zero means remove the entry, return 0 to keep it in the + * cache. + */ +static int +hostcache_timestamp_remove(void *datap, void *hc) +{ + struct hostcache_prune_data *data = + (struct hostcache_prune_data *) datap; + struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc; + + return (0 != c->timestamp) + && (data->now - c->timestamp >= data->cache_timeout); +} + +/* + * Prune the DNS cache. This assumes that a lock has already been taken. + */ +static void +hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now) +{ + struct hostcache_prune_data user; + + user.cache_timeout = cache_timeout; + user.now = now; + + Curl_hash_clean_with_criterium(hostcache, + (void *) &user, + hostcache_timestamp_remove); +} + +/* + * Library-wide function for pruning the DNS cache. This function takes and + * returns the appropriate locks. + */ +CURL_STATIC void Curl_hostcache_prune(struct SessionHandle *data) +{ + time_t now; + + if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache) + /* cache forever means never prune, and NULL hostcache means + we can't do it */ + return; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + time(&now); + + /* Remove outdated and unused entries from the hostcache */ + hostcache_prune(data->dns.hostcache, + data->set.dns_cache_timeout, + now); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + +#ifdef HAVE_SIGSETJMP +/* Beware this is a global and unique instance. This is used to store the + return address that we can jump back to from inside a signal handler. This + is not thread-safe stuff. */ +sigjmp_buf curl_jmpenv; +#endif + +/* lookup address, returns entry if found and not stale */ +static struct Curl_dns_entry * +fetch_addr(struct connectdata *conn, + const char *hostname, + int port) +{ + 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); + + if(dns && (data->set.dns_cache_timeout != -1)) { + /* See whether the returned entry is stale. Done before we release lock */ + struct hostcache_prune_data user; + + time(&user.now); + user.cache_timeout = data->set.dns_cache_timeout; + + if(hostcache_timestamp_remove(&user, dns)) { + infof(data, "Hostname in DNS cache was stale, zapped\n"); + dns = NULL; /* the memory deallocation is being handled by the hash */ + Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1); + } + } + + /* free the allocated entry_id again */ + free(entry_id); + + return dns; +} + +/* + * 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. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +CURL_STATIC struct Curl_dns_entry * +Curl_fetch_addr(struct connectdata *conn, + const char *hostname, + int port) +{ + struct SessionHandle *data = conn->data; + struct Curl_dns_entry *dns = NULL; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = fetch_addr(conn, hostname, port); + + if(dns) dns->inuse++; /* we use it! */ + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + return dns; +} + +/* + * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. + * + * When calling Curl_resolv() has resulted in a response with a returned + * address, we call this function to store the information in the dns + * cache etc + * + * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. + */ +CURL_STATIC struct Curl_dns_entry * +Curl_cache_addr(struct SessionHandle *data, + Curl_addrinfo *addr, + const char *hostname, + int port) +{ + char *entry_id; + size_t entry_len; + struct Curl_dns_entry *dns; + struct Curl_dns_entry *dns2; + + /* 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 NULL; + entry_len = strlen(entry_id); + + /* Create a new cache entry */ + dns = calloc(1, sizeof(struct Curl_dns_entry)); + if(!dns) { + free(entry_id); + return NULL; + } + + dns->inuse = 1; /* the cache has the first reference */ + dns->addr = addr; /* this is the address(es) */ + time(&dns->timestamp); + if(dns->timestamp == 0) + dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */ + + /* Store the resolved data in our DNS cache. */ + dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1, + (void *)dns); + if(!dns2) { + free(dns); + free(entry_id); + return NULL; + } + + dns = dns2; + dns->inuse++; /* mark entry as in-use */ + + /* free the allocated entry_id */ + free(entry_id); + + return dns; +} + +/* + * Curl_resolv() is the main name resolve function within libcurl. It resolves + * a name and returns a pointer to the entry in the 'entry' argument (if one + * is provided). This function might return immediately if we're using asynch + * resolves. See the return codes. + * + * The cache entry we return will get its 'inuse' counter increased when this + * function is used. You MUST call Curl_resolv_unlock() later (when you're + * done using this struct) to decrease the counter again. + * + * In debug mode, we specifically test for an interface name "LocalHost" + * and resolve "localhost" instead as a means to permit test cases + * to connect to a local test server with any host name. + * + * Return codes: + * + * CURLRESOLV_ERROR (-1) = error, no pointer + * CURLRESOLV_RESOLVED (0) = OK, pointer provided + * CURLRESOLV_PENDING (1) = waiting for response, no pointer + */ + +CURL_STATIC int Curl_resolv(struct connectdata *conn, + const char *hostname, + int port, + struct Curl_dns_entry **entry) +{ + struct Curl_dns_entry *dns = NULL; + struct SessionHandle *data = conn->data; + CURLcode result; + int rc = CURLRESOLV_ERROR; /* default to failure */ + + *entry = NULL; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = fetch_addr(conn, hostname, port); + + if(dns) { + infof(data, "Hostname %s was found in DNS cache\n", hostname); + dns->inuse++; /* we use it! */ + rc = CURLRESOLV_RESOLVED; + } + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) { + /* The entry was not in the cache. Resolve it to IP address */ + + Curl_addrinfo *addr; + int respwait; + + /* Check what IP specifics the app has requested and if we can provide it. + * If not, bail out. */ + if(!Curl_ipvalid(conn)) + return CURLRESOLV_ERROR; + + /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a + non-zero value indicating that we need to wait for the response to the + resolve call */ + addr = Curl_getaddrinfo(conn, +#ifdef DEBUGBUILD + (data->set.str[STRING_DEVICE] + && !strcmp(data->set.str[STRING_DEVICE], + "LocalHost"))?"localhost": +#endif + hostname, port, &respwait); + + if(!addr) { + if(respwait) { + /* the response to our resolve call will come asynchronously at + a later time, good or bad */ + /* First, check that we haven't received the info by now */ + result = Curl_resolver_is_resolved(conn, &dns); + if(result) /* error detected */ + return CURLRESOLV_ERROR; + if(dns) + rc = CURLRESOLV_RESOLVED; /* pointer provided */ + else + rc = CURLRESOLV_PENDING; /* no info yet */ + } + } + else { + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* we got a response, store it in the cache */ + dns = Curl_cache_addr(data, addr, hostname, port); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) + /* returned failure, bail out nicely */ + Curl_freeaddrinfo(addr); + else + rc = CURLRESOLV_RESOLVED; + } + } + + *entry = dns; + + return rc; +} + +#ifdef USE_ALARM_TIMEOUT +/* + * This signal handler jumps back into the main libcurl code and continues + * execution. This effectively causes the remainder of the application to run + * within a signal handler which is nonportable and could lead to problems. + */ +static +RETSIGTYPE alarmfunc(int sig) +{ + /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ + (void)sig; + siglongjmp(curl_jmpenv, 1); + return; +} +#endif /* USE_ALARM_TIMEOUT */ + +/* + * Curl_resolv_timeout() is the same as Curl_resolv() but specifies a + * timeout. This function might return immediately if we're using asynch + * resolves. See the return codes. + * + * The cache entry we return will get its 'inuse' counter increased when this + * function is used. You MUST call Curl_resolv_unlock() later (when you're + * done using this struct) to decrease the counter again. + * + * If built with a synchronous resolver and use of signals is not + * disabled by the application, then a nonzero timeout will cause a + * timeout after the specified number of milliseconds. Otherwise, timeout + * is ignored. + * + * Return codes: + * + * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired + * CURLRESOLV_ERROR (-1) = error, no pointer + * CURLRESOLV_RESOLVED (0) = OK, pointer provided + * CURLRESOLV_PENDING (1) = waiting for response, no pointer + */ + +CURL_STATIC int Curl_resolv_timeout(struct connectdata *conn, + const char *hostname, + int port, + struct Curl_dns_entry **entry, + long timeoutms) +{ +#ifdef USE_ALARM_TIMEOUT +#ifdef HAVE_SIGACTION + struct sigaction keep_sigact; /* store the old struct here */ + volatile bool keep_copysig = FALSE; /* wether old sigact has been saved */ + struct sigaction sigact; +#else +#ifdef HAVE_SIGNAL + void (*keep_sigact)(int); /* store the old handler here */ +#endif /* HAVE_SIGNAL */ +#endif /* HAVE_SIGACTION */ + volatile long timeout; + volatile unsigned int prev_alarm = 0; + struct SessionHandle *data = conn->data; +#endif /* USE_ALARM_TIMEOUT */ + int rc; + + *entry = NULL; + + if(timeoutms < 0) + /* got an already expired timeout */ + return CURLRESOLV_TIMEDOUT; + +#ifdef USE_ALARM_TIMEOUT + if(data->set.no_signal) + /* Ignore the timeout when signals are disabled */ + timeout = 0; + else + timeout = timeoutms; + + if(!timeout) + /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */ + return Curl_resolv(conn, hostname, port, entry); + + if(timeout < 1000) + /* The alarm() function only provides integer second resolution, so if + we want to wait less than one second we must bail out already now. */ + return CURLRESOLV_TIMEDOUT; + + /* This allows us to time-out from the name resolver, as the timeout + will generate a signal and we will siglongjmp() from that here. + This technique has problems (see alarmfunc). + This should be the last thing we do before calling Curl_resolv(), + as otherwise we'd have to worry about variables that get modified + before we invoke Curl_resolv() (and thus use "volatile"). */ + if(sigsetjmp(curl_jmpenv, 1)) { + /* this is coming from a siglongjmp() after an alarm signal */ + failf(data, "name lookup timed out"); + rc = CURLRESOLV_ERROR; + goto clean_up; + } + else { + /************************************************************* + * Set signal handler to catch SIGALRM + * Store the old value to be able to set it back later! + *************************************************************/ +#ifdef HAVE_SIGACTION + sigaction(SIGALRM, NULL, &sigact); + keep_sigact = sigact; + keep_copysig = TRUE; /* yes, we have a copy */ + sigact.sa_handler = alarmfunc; +#ifdef SA_RESTART + /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ + sigact.sa_flags &= ~SA_RESTART; +#endif + /* now set the new struct */ + sigaction(SIGALRM, &sigact, NULL); +#else /* HAVE_SIGACTION */ + /* no sigaction(), revert to the much lamer signal() */ +#ifdef HAVE_SIGNAL + keep_sigact = signal(SIGALRM, alarmfunc); +#endif +#endif /* HAVE_SIGACTION */ + + /* alarm() makes a signal get sent when the timeout fires off, and that + will abort system calls */ + prev_alarm = alarm(curlx_sltoui(timeout/1000L)); + } + +#else +#ifndef CURLRES_ASYNCH + if(timeoutms) + infof(conn->data, "timeout on name lookup is not supported\n"); +#else + (void)timeoutms; /* timeoutms not used with an async resolver */ +#endif +#endif /* USE_ALARM_TIMEOUT */ + + /* Perform the actual name resolution. This might be interrupted by an + * alarm if it takes too long. + */ + rc = Curl_resolv(conn, hostname, port, entry); + +#ifdef USE_ALARM_TIMEOUT +clean_up: + + if(!prev_alarm) + /* deactivate a possibly active alarm before uninstalling the handler */ + alarm(0); + +#ifdef HAVE_SIGACTION + if(keep_copysig) { + /* we got a struct as it looked before, now put that one back nice + and clean */ + sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */ + } +#else +#ifdef HAVE_SIGNAL + /* restore the previous SIGALRM handler */ + signal(SIGALRM, keep_sigact); +#endif +#endif /* HAVE_SIGACTION */ + + /* switch back the alarm() to either zero or to what it was before minus + the time we spent until now! */ + if(prev_alarm) { + /* there was an alarm() set before us, now put it back */ + unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created); + + /* the alarm period is counted in even number of seconds */ + unsigned long alarm_set = prev_alarm - elapsed_ms/1000; + + if(!alarm_set || + ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) { + /* if the alarm time-left reached zero or turned "negative" (counted + with unsigned values), we should fire off a SIGALRM here, but we + won't, and zero would be to switch it off so we never set it to + less than 1! */ + alarm(1); + rc = CURLRESOLV_TIMEDOUT; + failf(data, "Previous alarm fired off!"); + } + else + alarm((unsigned int)alarm_set); + } +#endif /* USE_ALARM_TIMEOUT */ + + return rc; +} + +/* + * Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been + * made, the struct may be destroyed due to pruning. It is important that only + * one unlock is made for each Curl_resolv() call. + * + * May be called with 'data' == NULL for global cache. + */ +CURL_STATIC void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns) +{ + if(data && data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + freednsentry(dns); + + if(data && data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + +/* + * File-internal: release cache dns entry reference, free if inuse drops to 0 + */ +static void freednsentry(void *freethis) +{ + struct Curl_dns_entry *dns = (struct Curl_dns_entry *) freethis; + DEBUGASSERT(dns && (dns->inuse>0)); + + dns->inuse--; + if(dns->inuse == 0) { + Curl_freeaddrinfo(dns->addr); + free(dns); + } +} + +/* + * Curl_mk_dnscache() creates a new DNS cache and returns the handle for it. + */ +CURL_STATIC struct curl_hash *Curl_mk_dnscache(void) +{ + return Curl_hash_alloc(7, Curl_hash_str, Curl_str_key_compare, freednsentry); +} + +/* + * Curl_hostcache_clean() + * + * This _can_ be called with 'data' == NULL but then of course no locking + * can be done! + */ + +CURL_STATIC void Curl_hostcache_clean(struct SessionHandle *data, + struct curl_hash *hash) +{ + if(data && data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + Curl_hash_clean(hash); + + if(data && data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + + +CURL_STATIC CURLcode Curl_loadhostpairs(struct SessionHandle *data) +{ + struct curl_slist *hostp; + char hostname[256]; + char address[256]; + int port; + + for(hostp = data->change.resolve; hostp; hostp = hostp->next ) { + if(!hostp->data) + continue; + if(hostp->data[0] == '-') { + char *entry_id; + size_t entry_len; + + if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { + infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n", + hostp->data); + continue; + } + + /* 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 CURLE_OUT_OF_MEMORY; + } + + entry_len = strlen(entry_id); + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* delete entry, ignore if it didn't exist */ + Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + /* free the allocated entry_id again */ + free(entry_id); + } + else { + struct Curl_dns_entry *dns; + Curl_addrinfo *addr; + char *entry_id; + size_t entry_len; + + if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port, + address)) { + infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n", + hostp->data); + continue; + } + + addr = Curl_str2addr(address, port); + if(!addr) { + infof(data, "Address in '%s' found illegal!\n", hostp->data); + continue; + } + + /* 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) { + Curl_freeaddrinfo(addr); + return CURLE_OUT_OF_MEMORY; + } + + entry_len = strlen(entry_id); + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* 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); + + if(!dns) { + /* if not in the cache already, put this host in the cache */ + dns = Curl_cache_addr(data, addr, hostname, port); + if(dns) { + dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */ + /* release the returned reference; the cache itself will keep the + * entry alive: */ + dns->inuse--; + } + } + else + /* this is a duplicate, free it again */ + Curl_freeaddrinfo(addr); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) { + Curl_freeaddrinfo(addr); + return CURLE_OUT_OF_MEMORY; + } + infof(data, "Added %s:%d:%s to DNS cache\n", + hostname, port, address); + } + } + data->change.resolve = NULL; /* dealt with now */ + + return CURLE_OK; +} diff --git a/libcurl/src/lib/hostip.h b/libcurl/src/lib/hostip.h new file mode 100644 index 0000000..2102c18 --- /dev/null +++ b/libcurl/src/lib/hostip.h @@ -0,0 +1,250 @@ +#ifndef HEADER_CURL_HOSTIP_H +#define HEADER_CURL_HOSTIP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "hash.h" +#include "curl_addrinfo.h" +#include "asyn.h" + +#ifdef HAVE_SETJMP_H +#include +#endif + +#ifdef NETWARE +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +/* Allocate enough memory to hold the full name information structs and + * everything. OSF1 is known to require at least 8872 bytes. The buffer + * required for storing all possible aliases and IP numbers is according to + * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes! + */ +#define CURL_HOSTENT_SIZE 9000 + +#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this + many seconds for a name resolve */ + +#define CURL_ASYNC_SUCCESS CURLE_OK + +struct addrinfo; +struct hostent; +struct SessionHandle; +struct connectdata; + +/* + * Curl_global_host_cache_init() initializes and sets up a global DNS cache. + * Global DNS cache is general badness. Do not use. This will be removed in + * a future version. Use the share interface instead! + * + * Returns a struct curl_hash pointer on success, NULL on failure. + */ +CURL_STATIC struct curl_hash *Curl_global_host_cache_init(void); +CURL_STATIC void Curl_global_host_cache_dtor(void); + +struct Curl_dns_entry { + Curl_addrinfo *addr; + /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */ + time_t timestamp; + /* use-counter, use Curl_resolv_unlock to release reference */ + long inuse; +}; + +/* + * Curl_resolv() returns an entry with the info for the specified host + * and port. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +/* return codes */ +#define CURLRESOLV_TIMEDOUT -2 +#define CURLRESOLV_ERROR -1 +#define CURLRESOLV_RESOLVED 0 +#define CURLRESOLV_PENDING 1 +CURL_STATIC int Curl_resolv(struct connectdata *conn, const char *hostname, + int port, struct Curl_dns_entry **dnsentry); +CURL_STATIC int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, + int port, struct Curl_dns_entry **dnsentry, + long timeoutms); + +#ifdef CURLRES_IPV6 +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +CURL_STATIC bool Curl_ipv6works(void); +#else +#define Curl_ipv6works() FALSE +#endif + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +CURL_STATIC bool Curl_ipvalid(struct connectdata *conn); + + +/* + * Curl_getaddrinfo() is the generic low-level name resolve API within this + * source file. There are several versions of this function - for different + * name resolve layers (selected at build-time). They all take this same set + * of arguments + */ +CURL_STATIC Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + + +/* unlock a previously resolved dns entry */ +CURL_STATIC void Curl_resolv_unlock(struct SessionHandle *data, + struct Curl_dns_entry *dns); + +/* for debugging purposes only: */ +CURL_STATIC void Curl_scan_cache_used(void *user, void *ptr); + +/* make a new dns cache and return the handle */ +CURL_STATIC struct curl_hash *Curl_mk_dnscache(void); + +/* prune old entries from the DNS cache */ +CURL_STATIC void Curl_hostcache_prune(struct SessionHandle *data); + +/* Return # of adresses in a Curl_addrinfo struct */ +CURL_STATIC int Curl_num_addresses (const Curl_addrinfo *addr); + +#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) +int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, + GETNAMEINFO_TYPE_ARG2 salen, + char *host, GETNAMEINFO_TYPE_ARG46 hostlen, + char *serv, GETNAMEINFO_TYPE_ARG46 servlen, + GETNAMEINFO_TYPE_ARG7 flags, + int line, const char *source); +#endif + +/* IPv4 threadsafe resolve function used for synch and asynch builds */ +CURL_STATIC Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port); + +CURL_STATIC CURLcode Curl_async_resolved(struct connectdata *conn, + bool *protocol_connect); + +#ifndef CURLRES_ASYNCH +#define Curl_async_resolved(x,y) CURLE_OK +#endif + +/* + * Curl_addrinfo_callback() is used when we build with any asynch specialty. + * Handles end of async request processing. Inserts ai into hostcache when + * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async + * request completed whether successful or failed. + */ +CURL_STATIC CURLcode Curl_addrinfo_callback(struct connectdata *conn, + int status, + Curl_addrinfo *ai); + +/* + * Curl_printable_address() returns a printable version of the 1st address + * given in the 'ip' argument. The result will be stored in the buf that is + * bufsize bytes big. + */ +CURL_STATIC const char *Curl_printable_address(const Curl_addrinfo *ip, + 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. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +CURL_STATIC struct Curl_dns_entry * +Curl_fetch_addr(struct connectdata *conn, + const char *hostname, + int port); +/* + * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. + * + * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. + */ +CURL_STATIC struct Curl_dns_entry * +Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr, + const char *hostname, int port); + +#ifndef INADDR_NONE +#define CURL_INADDR_NONE (in_addr_t) ~0 +#else +#define CURL_INADDR_NONE INADDR_NONE +#endif + +#ifdef HAVE_SIGSETJMP +/* Forward-declaration of variable defined in hostip.c. Beware this + * is a global and unique instance. This is used to store the return + * address that we can jump back to from inside a signal handler. + * This is not thread-safe stuff. + */ +extern sigjmp_buf curl_jmpenv; +#endif + +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURL_STATIC CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers); + +/* + * Function provided by the resolver backend to set + * outgoing interface to use for DNS requests + */ +CURL_STATIC CURLcode Curl_set_dns_interface(struct SessionHandle *data, + const char *interf); + +/* + * Function provided by the resolver backend to set + * local IPv4 address to use as source address for DNS requests + */ +CURL_STATIC CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data, + const char *local_ip4); + +/* + * Function provided by the resolver backend to set + * local IPv6 address to use as source address for DNS requests + */ +CURL_STATIC CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data, + const char *local_ip6); + +/* + * Clean off entries from the cache + */ +CURL_STATIC void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash); + +/* + * Destroy the hostcache of this handle. + */ +CURL_STATIC void Curl_hostcache_destroy(struct SessionHandle *data); + +/* + * Populate the cache with specified entries from CURLOPT_RESOLVE. + */ +CURL_STATIC CURLcode Curl_loadhostpairs(struct SessionHandle *data); + +#endif /* HEADER_CURL_HOSTIP_H */ diff --git a/libcurl/src/lib/hostip4.c b/libcurl/src/lib/hostip4.c new file mode 100644 index 0000000..fe6d749 --- /dev/null +++ b/libcurl/src/lib/hostip4.c @@ -0,0 +1,307 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_pton.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/*********************************************************************** + * Only for plain IPv4 builds + **********************************************************************/ +#ifdef CURLRES_IPV4 /* plain IPv4 code coming up */ +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +CURL_STATIC bool Curl_ipvalid(struct connectdata *conn) +{ + if(conn->ip_version == CURL_IPRESOLVE_V6) + /* An IPv6 address was requested and we can't get/use one */ + return FALSE; + + return TRUE; /* OK, proceed */ +} + +#ifdef CURLRES_SYNCH + +/* + * Curl_getaddrinfo() - the IPv4 synchronous version. + * + * The original code to this function was from the Dancer source code, written + * by Bjorn Reese, it has since been patched and modified considerably. + * + * gethostbyname_r() is the thread-safe version of the gethostbyname() + * function. When we build for plain IPv4, we attempt to use this + * function. There are _three_ different gethostbyname_r() versions, and we + * detect which one this platform supports in the configure script and set up + * the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or + * HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME + * has the corresponding rules. This is primarily on *nix. Note that some unix + * flavours have thread-safe versions of the plain gethostbyname() etc. + * + */ +CURL_STATIC Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + Curl_addrinfo *ai = NULL; + +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)conn; +#endif + + *waitp = 0; /* synchronous response only */ + + ai = Curl_ipv4_resolve_r(hostname, port); + if(!ai) + infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname); + + return ai; +} +#endif /* CURLRES_SYNCH */ +#endif /* CURLRES_IPV4 */ + +#if defined(CURLRES_IPV4) && !defined(CURLRES_ARES) + +/* + * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function. + * + * This is used for both synchronous and asynchronous resolver builds, + * implying that only threadsafe code and function calls may be used. + * + */ +Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, + int port) +{ +#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3) + int res; +#endif + Curl_addrinfo *ai = NULL; + struct hostent *h = NULL; + struct in_addr in; + struct hostent *buf = NULL; + + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + +#if defined(HAVE_GETADDRINFO_THREADSAFE) + else { + struct addrinfo hints; + char sbuf[12]; + char *sbufptr = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + if(port) { + snprintf(sbuf, sizeof(sbuf), "%d", port); + sbufptr = sbuf; + } + + (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai); + +#elif defined(HAVE_GETHOSTBYNAME_R) + /* + * gethostbyname_r() is the preferred resolve function for many platforms. + * Since there are three different versions of it, the following code is + * somewhat #ifdef-ridden. + */ + else { + int h_errnop; + + buf = calloc(1, CURL_HOSTENT_SIZE); + if(!buf) + return NULL; /* major failure */ + /* + * The clearing of the buffer is a workaround for a gethostbyname_r bug in + * qnx nto and it is also _required_ for some of these functions on some + * platforms. + */ + +#if defined(HAVE_GETHOSTBYNAME_R_5) + /* Solaris, IRIX and more */ + h = gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h_errnop); + + /* If the buffer is too small, it returns NULL and sets errno to + * ERANGE. The errno is thread safe if this is compiled with + * -D_REENTRANT as then the 'errno' variable is a macro defined to get + * used properly for threads. + */ + + if(h) { + ; + } + else +#elif defined(HAVE_GETHOSTBYNAME_R_6) + /* Linux */ + + (void)gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h, /* DIFFERENCE */ + &h_errnop); + /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a + * sudden this function returns EAGAIN if the given buffer size is too + * small. Previous versions are known to return ERANGE for the same + * problem. + * + * This wouldn't be such a big problem if older versions wouldn't + * sometimes return EAGAIN on a common failure case. Alas, we can't + * assume that EAGAIN *or* ERANGE means ERANGE for any given version of + * glibc. + * + * For now, we do that and thus we may call the function repeatedly and + * fail for older glibc versions that return EAGAIN, until we run out of + * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). + * + * If anyone has a better fix, please tell us! + * + * ------------------------------------------------------------------- + * + * On October 23rd 2003, Dan C dug up more details on the mysteries of + * gethostbyname_r() in glibc: + * + * In glibc 2.2.5 the interface is different (this has also been + * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't + * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 + * (shipped/upgraded by Redhat 7.2) don't show this behavior! + * + * In this "buggy" version, the return code is -1 on error and 'errno' + * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a + * thread-safe variable. + */ + + if(!h) /* failure */ +#elif defined(HAVE_GETHOSTBYNAME_R_3) + /* AIX, Digital Unix/Tru64, HPUX 10, more? */ + + /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of + * the plain fact that it does not return unique full buffers on each + * call, but instead several of the pointers in the hostent structs will + * point to the same actual data! This have the unfortunate down-side that + * our caching system breaks down horribly. Luckily for us though, AIX 4.3 + * and more recent versions have a "completely thread-safe"[*] libc where + * all the data is stored in thread-specific memory areas making calls to + * the plain old gethostbyname() work fine even for multi-threaded + * programs. + * + * This AIX 4.3 or later detection is all made in the configure script. + * + * Troels Walsted Hansen helped us work this out on March 3rd, 2003. + * + * [*] = much later we've found out that it isn't at all "completely + * thread-safe", but at least the gethostbyname() function is. + */ + + if(CURL_HOSTENT_SIZE >= + (sizeof(struct hostent)+sizeof(struct hostent_data))) { + + /* August 22nd, 2000: Albert Chin-A-Young brought an updated version + * that should work! September 20: Richard Prescott worked on the buffer + * size dilemma. + */ + + res = gethostbyname_r(hostname, + (struct hostent *)buf, + (struct hostent_data *)((char *)buf + + sizeof(struct hostent))); + h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */ + } + else + res = -1; /* failure, too smallish buffer size */ + + if(!res) { /* success */ + + h = buf; /* result expected in h */ + + /* This is the worst kind of the different gethostbyname_r() interfaces. + * Since we don't know how big buffer this particular lookup required, + * we can't realloc down the huge alloc without doing closer analysis of + * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every + * name lookup. Fixing this would require an extra malloc() and then + * calling Curl_addrinfo_copy() that subsequent realloc()s down the new + * memory area to the actually used amount. + */ + } + else +#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */ + { + h = NULL; /* set return code to NULL */ + free(buf); + } +#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ + /* + * Here is code for platforms that don't have a thread safe + * getaddrinfo() nor gethostbyname_r() function or for which + * gethostbyname() is the preferred one. + */ + else { + h = gethostbyname((void*)hostname); +#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ + } + + if(h) { + ai = Curl_he2ai(h, port); + + if(buf) /* used a *_r() function */ + free(buf); + } + + return ai; +} +#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */ diff --git a/libcurl/src/lib/hostip6.c b/libcurl/src/lib/hostip6.c new file mode 100644 index 0000000..862bfae --- /dev/null +++ b/libcurl/src/lib/hostip6.c @@ -0,0 +1,221 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_pton.h" +#include "connect.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/*********************************************************************** + * Only for IPv6-enabled builds + **********************************************************************/ +#ifdef CURLRES_IPV6 + + +#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) +/* These are strictly for memory tracing and are using the same style as the + * family otherwise present in memdebug.c. I put these ones here since they + * require a bunch of structs I didn't want to include in memdebug.c + */ + +/* + * For CURLRES_ARS, this should be written using ares_gethostbyaddr() + * (ignoring the fact c-ares doesn't return 'serv'). + */ + +int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, + GETNAMEINFO_TYPE_ARG2 salen, + char *host, GETNAMEINFO_TYPE_ARG46 hostlen, + char *serv, GETNAMEINFO_TYPE_ARG46 servlen, + GETNAMEINFO_TYPE_ARG7 flags, + int line, const char *source) +{ + int res = (getnameinfo)(sa, salen, + host, hostlen, + serv, servlen, + flags); + if(0 == res) + /* success */ + curl_memlog("GETNAME %s:%d getnameinfo()\n", + source, line); + else + curl_memlog("GETNAME %s:%d getnameinfo() failed = %d\n", + source, line, res); + return res; +} +#endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */ + +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +CURL_STATIC bool Curl_ipv6works(void) +{ + /* the nature of most system is that IPv6 status doesn't come and go + during a program's lifetime so we only probe the first time and then we + have the info kept for fast re-use */ + static int ipv6_works = -1; + if(-1 == ipv6_works) { + /* probe to see if we have a working IPv6 stack */ + curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); + if(s == CURL_SOCKET_BAD) + /* an IPv6 address was requested but we can't get/use one */ + ipv6_works = 0; + else { + ipv6_works = 1; + Curl_closesocket(NULL, s); + } + } + return (ipv6_works>0)?TRUE:FALSE; +} + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +CURL_STATIC bool Curl_ipvalid(struct connectdata *conn) +{ + if(conn->ip_version == CURL_IPRESOLVE_V6) + return Curl_ipv6works(); + return TRUE; +} + +#if defined(CURLRES_SYNCH) + +#ifdef DEBUG_ADDRINFO +static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai) +{ + printf("dump_addrinfo:\n"); + for(; ai; ai = ai->ai_next) { + char buf[INET6_ADDRSTRLEN]; + + printf(" fam %2d, CNAME %s, ", + ai->ai_family, ai->ai_canonname ? ai->ai_canonname : ""); + if(Curl_printable_address(ai, buf, sizeof(buf))) + printf("%s\n", buf); + else + printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO)); + } +} +#else +#define dump_addrinfo(x,y) Curl_nop_stmt +#endif + +/* + * Curl_getaddrinfo() when built IPv6-enabled (non-threading and + * non-ares version). + * + * Returns name information about the given hostname and port number. If + * successful, the 'addrinfo' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + */ +CURL_STATIC Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct addrinfo hints; + Curl_addrinfo *res; + int error; + char sbuf[12]; + char *sbufptr = NULL; + char addrbuf[128]; + int pf; + struct SessionHandle *data = conn->data; + + *waitp = 0; /* synchronous response only */ + + /* + * Check if a limited name resolve has been requested. + */ + switch(conn->ip_version) { + case CURL_IPRESOLVE_V4: + pf = PF_INET; + break; + case CURL_IPRESOLVE_V6: + pf = PF_INET6; + break; + default: + pf = PF_UNSPEC; + break; + } + + if((pf != PF_INET) && !Curl_ipv6works()) + /* The stack seems to be a non-IPv6 one */ + pf = PF_INET; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = pf; + hints.ai_socktype = conn->socktype; + + if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) || + (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) { + /* the given address is numerical only, prevent a reverse lookup */ + hints.ai_flags = AI_NUMERICHOST; + } + + if(port) { + snprintf(sbuf, sizeof(sbuf), "%d", port); + sbufptr=sbuf; + } + error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res); + if(error) { + infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port); + return NULL; + } + + dump_addrinfo(conn, res); + + return res; +} +#endif /* CURLRES_SYNCH */ +#endif /* CURLRES_IPV6 */ + diff --git a/libcurl/src/lib/hostsyn.c b/libcurl/src/lib/hostsyn.c new file mode 100644 index 0000000..ecf4c0a --- /dev/null +++ b/libcurl/src/lib/hostsyn.c @@ -0,0 +1,107 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/*********************************************************************** + * Only for builds using synchronous name resolves + **********************************************************************/ +#ifdef CURLRES_SYNCH + +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURL_STATIC CURLcode Curl_set_dns_servers(struct SessionHandle *data, + char *servers) +{ + (void)data; + (void)servers; + return CURLE_NOT_BUILT_IN; + +} + +/* + * Function provided by the resolver backend to set + * outgoing interface to use for DNS requests + */ +CURL_STATIC CURLcode Curl_set_dns_interface(struct SessionHandle *data, + const char *interf) +{ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +} + +/* + * Function provided by the resolver backend to set + * local IPv4 address to use as source address for DNS requests + */ +CURL_STATIC CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data, + const char *local_ip4) +{ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +} + +/* + * Function provided by the resolver backend to set + * local IPv6 address to use as source address for DNS requests + */ +CURL_STATIC CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data, + const char *local_ip6) +{ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +} + +#endif /* truly sync */ diff --git a/libcurl/src/lib/http.c b/libcurl/src/lib/http.c new file mode 100644 index 0000000..753949c --- /dev/null +++ b/libcurl/src/lib/http.c @@ -0,0 +1,3717 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "formdata.h" +#include "progress.h" +#include "curl_base64.h" +#include "cookie.h" +#include "strequal.h" +#include "vtls/vtls.h" +#include "http_digest.h" +#include "curl_ntlm.h" +#include "curl_ntlm_wb.h" +#include "http_negotiate.h" +#include "url.h" +#include "share.h" +#include "hostip.h" +#include "http.h" +#include "select.h" +#include "parsedate.h" /* for the week day and month names */ +#include "strtoofft.h" +#include "multiif.h" +#include "rawstr.h" +#include "content_encoding.h" +#include "http_proxy.h" +#include "warnless.h" +#include "non-ascii.h" +#include "bundles.h" +#include "pipeline.h" +#include "http2.h" +#include "connect.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static int http_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +static int http_should_fail(struct connectdata *conn); + +#ifdef USE_SSL +static CURLcode https_connecting(struct connectdata *conn, bool *done); +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +#else +#define https_connecting(x,y) CURLE_COULDNT_CONNECT +#endif + +/* + * HTTP handler interface. + */ +CURL_STATIC_VAR const struct Curl_handler Curl_handler_http = { + "HTTP", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + Curl_http_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_CREDSPERREQUEST /* flags */ +}; + +#ifdef USE_SSL +/* + * HTTPS handler interface. + */ +const struct Curl_handler Curl_handler_https = { + "HTTPS", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + Curl_http_connect, /* connect_it */ + https_connecting, /* connecting */ + ZERO_NULL, /* doing */ + https_getsock, /* proto_getsock */ + http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_HTTPS, /* defport */ + CURLPROTO_HTTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */ +}; +#endif + + +CURL_STATIC CURLcode Curl_http_setup_conn(struct connectdata *conn) +{ + /* allocate the HTTP-specific struct for the SessionHandle, only to survive + during this request */ + DEBUGASSERT(conn->data->req.protop == NULL); + + conn->data->req.protop = calloc(1, sizeof(struct HTTP)); + if(!conn->data->req.protop) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +/* + * checkheaders() checks the linked list of custom HTTP headers for a + * particular header (prefix). + * + * Returns a pointer to the first matching header or NULL if none matched. + */ +CURL_STATIC char *Curl_checkheaders(const struct connectdata *conn, + const char *thisheader) +{ + struct curl_slist *head; + size_t thislen = strlen(thisheader); + struct SessionHandle *data = conn->data; + + for(head = data->set.headers;head; head=head->next) { + if(Curl_raw_nequal(head->data, thisheader, thislen)) + return head->data; + } + return NULL; +} + +/* + * checkProxyHeaders() checks the linked list of custom proxy headers + * if proxy headers are not available, then it will lookup into http header + * link list + * + * It takes a connectdata struct as input instead of the SessionHandle simply + * to know if this is a proxy request or not, as it then might check a + * different header list. + * + */ +CURL_STATIC char *Curl_checkProxyheaders(const struct connectdata *conn, + const char *thisheader) +{ + struct curl_slist *head; + size_t thislen = strlen(thisheader); + struct SessionHandle *data = conn->data; + + for(head = (conn->bits.proxy && data->set.sep_headers)? + data->set.proxyheaders:data->set.headers; + head; head=head->next) { + if(Curl_raw_nequal(head->data, thisheader, thislen)) + return head->data; + } + return NULL; +} + +/* + * Strip off leading and trailing whitespace from the value in the + * given HTTP header line and return a strdupped copy. Returns NULL in + * case of allocation failure. Returns an empty string if the header value + * consists entirely of whitespace. + */ +CURL_STATIC char *Curl_copy_header_value(const char *header) +{ + const char *start; + const char *end; + char *value; + size_t len; + + DEBUGASSERT(header); + + /* Find the end of the header name */ + while(*header && (*header != ':')) + ++header; + + if(*header) + /* Skip over colon */ + ++header; + + /* Find the first non-space letter */ + start = header; + while(*start && ISSPACE(*start)) + start++; + + /* data is in the host encoding so + use '\r' and '\n' instead of 0x0d and 0x0a */ + end = strchr(start, '\r'); + if(!end) + end = strchr(start, '\n'); + if(!end) + end = strchr(start, '\0'); + if(!end) + return NULL; + + /* skip all trailing space letters */ + while((end > start) && ISSPACE(*end)) + end--; + + /* get length of the type */ + len = end - start + 1; + + value = malloc(len + 1); + if(!value) + return NULL; + + memcpy(value, start, len); + value[len] = 0; /* zero terminate */ + + return value; +} + +/* + * http_output_basic() sets up an Authorization: header (or the proxy version) + * for HTTP Basic authentication. + * + * Returns CURLcode. + */ +static CURLcode http_output_basic(struct connectdata *conn, bool proxy) +{ + size_t size = 0; + char *authorization = NULL; + struct SessionHandle *data = conn->data; + char **userp; + const char *user; + const char *pwd; + CURLcode result; + + if(proxy) { + userp = &conn->allocptr.proxyuserpwd; + user = conn->proxyuser; + pwd = conn->proxypasswd; + } + else { + userp = &conn->allocptr.userpwd; + user = conn->user; + pwd = conn->passwd; + } + + snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd); + + result = Curl_base64_encode(data, + data->state.buffer, strlen(data->state.buffer), + &authorization, &size); + if(result) + return result; + + if(!authorization) + return CURLE_REMOTE_ACCESS_DENIED; + + free(*userp); + *userp = aprintf("%sAuthorization: Basic %s\r\n", + proxy?"Proxy-":"", + authorization); + free(authorization); + if(!*userp) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +/* pickoneauth() selects the most favourable authentication method from the + * ones available and the ones we want. + * + * return TRUE if one was picked + */ +static bool pickoneauth(struct auth *pick) +{ + bool picked; + /* only deal with authentication we want */ + unsigned long avail = pick->avail & pick->want; + picked = TRUE; + + /* 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. */ + if(avail & CURLAUTH_NEGOTIATE) + pick->picked = CURLAUTH_NEGOTIATE; + else if(avail & CURLAUTH_DIGEST) + pick->picked = CURLAUTH_DIGEST; + else if(avail & CURLAUTH_NTLM) + pick->picked = CURLAUTH_NTLM; + else if(avail & CURLAUTH_NTLM_WB) + pick->picked = CURLAUTH_NTLM_WB; + else if(avail & CURLAUTH_BASIC) + pick->picked = CURLAUTH_BASIC; + else { + pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */ + picked = FALSE; + } + pick->avail = CURLAUTH_NONE; /* clear it here */ + + return picked; +} + +/* + * Curl_http_perhapsrewind() + * + * If we are doing POST or PUT { + * If we have more data to send { + * If we are doing NTLM { + * Keep sending since we must not disconnect + * } + * else { + * If there is more than just a little data left to send, close + * the current connection by force. + * } + * } + * If we have sent any data { + * If we don't have track of all the data { + * call app to tell it to rewind + * } + * else { + * rewind internally so that the operation can restart fine + * } + * } + * } + */ +static CURLcode http_perhapsrewind(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + struct HTTP *http = data->req.protop; + curl_off_t bytessent; + curl_off_t expectsend = -1; /* default is unknown */ + + if(!http) + /* If this is still NULL, we have not reach very far and we can safely + skip this rewinding stuff */ + return CURLE_OK; + + switch(data->set.httpreq) { + case HTTPREQ_GET: + case HTTPREQ_HEAD: + return CURLE_OK; + default: + break; + } + + bytessent = http->writebytecount; + + if(conn->bits.authneg) { + /* This is a state where we are known to be negotiating and we don't send + any data then. */ + expectsend = 0; + } + else if(!conn->bits.protoconnstart) { + /* HTTP CONNECT in progress: there is no body */ + expectsend = 0; + } + else { + /* figure out how much data we are expected to send */ + switch(data->set.httpreq) { + case HTTPREQ_POST: + if(data->set.postfieldsize != -1) + expectsend = data->set.postfieldsize; + else if(data->set.postfields) + expectsend = (curl_off_t)strlen(data->set.postfields); + break; + case HTTPREQ_PUT: + if(data->state.infilesize != -1) + expectsend = data->state.infilesize; + break; + case HTTPREQ_POST_FORM: + expectsend = http->postsize; + break; + default: + break; + } + } + + conn->bits.rewindaftersend = FALSE; /* default */ + + if((expectsend == -1) || (expectsend > bytessent)) { +#if defined(USE_NTLM) + /* There is still data left to send */ + if((data->state.authproxy.picked == CURLAUTH_NTLM) || + (data->state.authhost.picked == CURLAUTH_NTLM) || + (data->state.authproxy.picked == CURLAUTH_NTLM_WB) || + (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { + if(((expectsend - bytessent) < 2000) || + (conn->ntlm.state != NTLMSTATE_NONE) || + (conn->proxyntlm.state != NTLMSTATE_NONE)) { + /* The NTLM-negotiation has started *OR* there is just a little (<2K) + data left to send, keep on sending. */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return CURLE_OK; + } + + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; + + infof(data, "NTLM send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + (curl_off_t)(expectsend - bytessent)); + } +#endif + + /* This is not NTLM or many bytes left to send: close */ + connclose(conn, "Mid-auth HTTP and much data left to send"); + data->req.size = 0; /* don't download any more than 0 bytes */ + + /* There still is data left to send, but this connection is marked for + closure so we can safely do the rewind right now */ + } + + if(bytessent) + /* we rewind now at once since if we already sent something */ + return Curl_readrewind(conn); + + return CURLE_OK; +} + +/* + * Curl_http_auth_act() gets called when all HTTP headers have been received + * and it checks what authentication methods that are available and decides + * which one (if any) to use. It will set 'newurl' if an auth method was + * picked. + */ + +CURL_STATIC CURLcode Curl_http_auth_act(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + bool pickhost = FALSE; + bool pickproxy = FALSE; + CURLcode result = CURLE_OK; + + if(100 <= data->req.httpcode && 199 >= data->req.httpcode) + /* this is a transient response code, ignore */ + return CURLE_OK; + + if(data->state.authproblem) + return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; + + if(conn->bits.user_passwd && + ((data->req.httpcode == 401) || + (conn->bits.authneg && data->req.httpcode < 300))) { + pickhost = pickoneauth(&data->state.authhost); + if(!pickhost) + data->state.authproblem = TRUE; + } + if(conn->bits.proxy_user_passwd && + ((data->req.httpcode == 407) || + (conn->bits.authneg && data->req.httpcode < 300))) { + pickproxy = pickoneauth(&data->state.authproxy); + if(!pickproxy) + data->state.authproblem = TRUE; + } + + if(pickhost || pickproxy) { + /* In case this is GSS auth, the newurl field is already allocated so + we must make sure to free it before allocating a new one. As figured + out in bug #2284386 */ + Curl_safefree(data->req.newurl); + data->req.newurl = strdup(data->change.url); /* clone URL */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + + if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD) && + !conn->bits.rewindaftersend) { + result = http_perhapsrewind(conn); + if(result) + return result; + } + } + + else if((data->req.httpcode < 300) && + (!data->state.authhost.done) && + conn->bits.authneg) { + /* no (known) authentication available, + authentication is not "done" yet and + no authentication seems to be required and + we didn't try HEAD or GET */ + if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { + data->req.newurl = strdup(data->change.url); /* clone URL */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authhost.done = TRUE; + } + } + if(http_should_fail(conn)) { + failf (data, "The requested URL returned error: %d", + data->req.httpcode); + result = CURLE_HTTP_RETURNED_ERROR; + } + + return result; +} + + +/* + * Output the correct authentication header depending on the auth type + * and whether or not it is to a proxy. + */ +static CURLcode +output_auth_headers(struct connectdata *conn, + struct auth *authstatus, + const char *request, + const char *path, + bool proxy) +{ + const char *auth = NULL; + CURLcode result = CURLE_OK; +#if defined(USE_SPNEGO) || !defined(CURL_DISABLE_VERBOSE_STRINGS) + struct SessionHandle *data = conn->data; +#endif +#ifdef USE_SPNEGO + struct negotiatedata *negdata = proxy? + &data->state.proxyneg:&data->state.negotiate; +#endif + +#ifdef CURL_DISABLE_CRYPTO_AUTH + (void)request; + (void)path; +#endif + +#ifdef USE_SPNEGO + negdata->state = GSS_AUTHNONE; + if((authstatus->picked == CURLAUTH_NEGOTIATE) && + negdata->context && !GSS_ERROR(negdata->status)) { + auth="Negotiate"; + result = Curl_output_negotiate(conn, proxy); + if(result) + return result; + authstatus->done = TRUE; + negdata->state = GSS_AUTHSENT; + } + else +#endif +#ifdef USE_NTLM + if(authstatus->picked == CURLAUTH_NTLM) { + auth="NTLM"; + result = Curl_output_ntlm(conn, proxy); + if(result) + return result; + } + else +#endif +#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) + if(authstatus->picked == CURLAUTH_NTLM_WB) { + auth="NTLM_WB"; + result = Curl_output_ntlm_wb(conn, proxy); + if(result) + return result; + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(authstatus->picked == CURLAUTH_DIGEST) { + auth="Digest"; + result = Curl_output_digest(conn, + proxy, + (const unsigned char *)request, + (const unsigned char *)path); + if(result) + return result; + } + else +#endif + if(authstatus->picked == CURLAUTH_BASIC) { + /* Basic */ + if((proxy && conn->bits.proxy_user_passwd && + !Curl_checkProxyheaders(conn, "Proxy-authorization:")) || + (!proxy && conn->bits.user_passwd && + !Curl_checkheaders(conn, "Authorization:"))) { + auth="Basic"; + result = http_output_basic(conn, proxy); + if(result) + return result; + } + /* NOTE: this function should set 'done' TRUE, as the other auth + functions work that way */ + authstatus->done = TRUE; + } + + if(auth) { + infof(data, "%s auth using %s with user '%s'\n", + proxy?"Proxy":"Server", auth, + proxy?(conn->proxyuser?conn->proxyuser:""): + (conn->user?conn->user:"")); + authstatus->multi = (!authstatus->done) ? TRUE : FALSE; + } + else + authstatus->multi = FALSE; + + return CURLE_OK; +} + +/** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication + * method. conn->data->state.authdone is set to TRUE when authentication is + * done. + * + * @param conn all information about the current connection + * @param request pointer to the request keyword + * @param path pointer to the requested path + * @param proxytunnel boolean if this is the request setting up a "proxy + * tunnel" + * + * @returns CURLcode + */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel) /* TRUE if this is the request setting + up the proxy tunnel */ +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct auth *authhost; + struct auth *authproxy; + + DEBUGASSERT(data); + + authhost = &data->state.authhost; + authproxy = &data->state.authproxy; + + if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || + conn->bits.user_passwd) + /* continue please */; + else { + authhost->done = TRUE; + authproxy->done = TRUE; + return CURLE_OK; /* no authentication with no user or password */ + } + + if(authhost->want && !authhost->picked) + /* The app has selected one or more methods, but none has been picked + so far by a server round-trip. Then we set the picked one to the + want one, and if this is one single bit it'll be used instantly. */ + authhost->picked = authhost->want; + + if(authproxy->want && !authproxy->picked) + /* The app has selected one or more methods, but none has been picked so + far by a proxy round-trip. Then we set the picked one to the want one, + and if this is one single bit it'll be used instantly. */ + authproxy->picked = authproxy->want; + +#ifndef CURL_DISABLE_PROXY + /* Send proxy authentication header if needed */ + if(conn->bits.httpproxy && + (conn->bits.tunnel_proxy == proxytunnel)) { + result = output_auth_headers(conn, authproxy, request, path, TRUE); + if(result) + return result; + } + else +#else + (void)proxytunnel; +#endif /* CURL_DISABLE_PROXY */ + /* we have no proxy so let's pretend we're done authenticating + with it */ + authproxy->done = TRUE; + + /* To prevent the user+password to get sent to other than the original + host due to a location-follow, we do some weirdo checks here */ + if(!data->state.this_is_a_follow || + conn->bits.netrc || + !data->state.first_host || + data->set.http_disable_hostname_check_before_authentication || + Curl_raw_equal(data->state.first_host, conn->host.name)) { + result = output_auth_headers(conn, authhost, request, path, FALSE); + } + else + authhost->done = TRUE; + + return result; +} + + +/* + * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: + * headers. They are dealt with both in the transfer.c main loop and in the + * proxy CONNECT loop. + */ + +CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, + const char *auth) /* the first non-space */ +{ + /* + * This resource requires authentication + */ + struct SessionHandle *data = conn->data; + +#ifdef USE_SPNEGO + struct negotiatedata *negdata = proxy? + &data->state.proxyneg:&data->state.negotiate; +#endif + unsigned long *availp; + struct auth *authp; + + if(proxy) { + availp = &data->info.proxyauthavail; + authp = &data->state.authproxy; + } + else { + availp = &data->info.httpauthavail; + authp = &data->state.authhost; + } + + /* + * Here we check if we want the specific single authentication (using ==) and + * if we do, we initiate usage of it. + * + * If the provided authentication is wanted as one out of several accepted + * types (using &), we OR this authentication type to the authavail + * variable. + * + * Note: + * + * ->picked is first set to the 'want' value (one or more bits) before the + * request is sent, and then it is again set _after_ all response 401/407 + * headers have been received but then only to a single preferred method + * (bit). + * + */ + + while(*auth) { +#ifdef USE_SPNEGO + if(checkprefix("Negotiate", auth)) { + *availp |= CURLAUTH_NEGOTIATE; + authp->avail |= CURLAUTH_NEGOTIATE; + + if(authp->picked == CURLAUTH_NEGOTIATE) { + if(negdata->state == GSS_AUTHSENT || negdata->state == GSS_AUTHNONE) { + CURLcode result = Curl_input_negotiate(conn, proxy, auth); + if(!result) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->change.url); + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authproblem = FALSE; + /* we received a GSS auth token and we dealt with it fine */ + negdata->state = GSS_AUTHRECV; + } + else + data->state.authproblem = TRUE; + } + } + } + else +#endif +#ifdef USE_NTLM + /* NTLM support requires the SSL crypto libs */ + if(checkprefix("NTLM", auth)) { + *availp |= CURLAUTH_NTLM; + authp->avail |= CURLAUTH_NTLM; + if(authp->picked == CURLAUTH_NTLM || + authp->picked == CURLAUTH_NTLM_WB) { + /* NTLM authentication is picked and activated */ + CURLcode result = Curl_input_ntlm(conn, proxy, auth); + if(!result) { + data->state.authproblem = FALSE; +#ifdef NTLM_WB_ENABLED + if(authp->picked == CURLAUTH_NTLM_WB) { + *availp &= ~CURLAUTH_NTLM; + authp->avail &= ~CURLAUTH_NTLM; + *availp |= CURLAUTH_NTLM_WB; + authp->avail |= CURLAUTH_NTLM_WB; + + /* Get the challenge-message which will be passed to + * ntlm_auth for generating the type 3 message later */ + while(*auth && ISSPACE(*auth)) + auth++; + if(checkprefix("NTLM", auth)) { + auth += strlen("NTLM"); + while(*auth && ISSPACE(*auth)) + auth++; + if(*auth) + if((conn->challenge_header = strdup(auth)) == NULL) + return CURLE_OUT_OF_MEMORY; + } + } +#endif + } + else { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(checkprefix("Digest", auth)) { + if((authp->avail & CURLAUTH_DIGEST) != 0) { + infof(data, "Ignoring duplicate digest auth header.\n"); + } + else { + CURLcode result; + *availp |= CURLAUTH_DIGEST; + authp->avail |= CURLAUTH_DIGEST; + + /* We call this function on input Digest headers even if Digest + * authentication isn't activated yet, as we need to store the + * incoming data from this header in case we are gonna use + * Digest. */ + result = Curl_input_digest(conn, proxy, auth); + if(result) { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + } + else +#endif + if(checkprefix("Basic", auth)) { + *availp |= CURLAUTH_BASIC; + authp->avail |= CURLAUTH_BASIC; + if(authp->picked == CURLAUTH_BASIC) { + /* We asked for Basic authentication but got a 40X back + anyway, which basically means our name+password isn't + valid. */ + authp->avail = CURLAUTH_NONE; + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + + /* there may be multiple methods on one line, so keep reading */ + while(*auth && *auth != ',') /* read up to the next comma */ + auth++; + if(*auth == ',') /* if we're on a comma, skip it */ + auth++; + while(*auth && ISSPACE(*auth)) + auth++; + } + return CURLE_OK; +} + +/** + * http_should_fail() determines whether an HTTP response has gotten us + * into an error state or not. + * + * @param conn all information about the current connection + * + * @retval 0 communications should continue + * + * @retval 1 communications should not continue + */ +static int http_should_fail(struct connectdata *conn) +{ + struct SessionHandle *data; + int httpcode; + + DEBUGASSERT(conn); + data = conn->data; + DEBUGASSERT(data); + + httpcode = data->req.httpcode; + + /* + ** If we haven't been asked to fail on error, + ** don't fail. + */ + if(!data->set.http_fail_on_error) + return 0; + + /* + ** Any code < 400 is never terminal. + */ + if(httpcode < 400) + return 0; + + /* + ** Any code >= 400 that's not 401 or 407 is always + ** a terminal error + */ + if((httpcode != 401) && + (httpcode != 407)) + return 1; + + /* + ** All we have left to deal with is 401 and 407 + */ + DEBUGASSERT((httpcode == 401) || (httpcode == 407)); + + /* + ** Examine the current authentication state to see if this + ** is an error. The idea is for this function to get + ** called after processing all the headers in a response + ** message. So, if we've been to asked to authenticate a + ** particular stage, and we've done it, we're OK. But, if + ** we're already completely authenticated, it's not OK to + ** get another 401 or 407. + ** + ** It is possible for authentication to go stale such that + ** the client needs to reauthenticate. Once that info is + ** available, use it here. + */ + + /* + ** Either we're not authenticating, or we're supposed to + ** be authenticating something else. This is an error. + */ + if((httpcode == 401) && !conn->bits.user_passwd) + return TRUE; + if((httpcode == 407) && !conn->bits.proxy_user_passwd) + return TRUE; + + return data->state.authproblem; +} + +/* + * readmoredata() is a "fread() emulation" to provide POST and/or request + * data. It is used when a huge POST is to be made and the entire chunk wasn't + * sent in the first send(). This function will then be called from the + * transfer.c loop when more data is to be sent to the peer. + * + * Returns the amount of bytes it filled the buffer with. + */ +static size_t readmoredata(char *buffer, + size_t size, + size_t nitems, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct HTTP *http = conn->data->req.protop; + size_t fullsize = size * nitems; + + if(0 == http->postsize) + /* nothing to return */ + return 0; + + /* make sure that a HTTP request is never sent away chunked! */ + conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; + + if(http->postsize <= (curl_off_t)fullsize) { + memcpy(buffer, http->postdata, (size_t)http->postsize); + fullsize = (size_t)http->postsize; + + if(http->backup.postsize) { + /* move backup data into focus and continue on that */ + http->postdata = http->backup.postdata; + http->postsize = http->backup.postsize; + conn->fread_func = http->backup.fread_func; + conn->fread_in = http->backup.fread_in; + + http->sending++; /* move one step up */ + + http->backup.postsize=0; + } + else + http->postsize = 0; + + return fullsize; + } + + memcpy(buffer, http->postdata, fullsize); + http->postdata += fullsize; + http->postsize -= fullsize; + + return fullsize; +} + +/* ------------------------------------------------------------------------- */ +/* add_buffer functions */ + +/* + * Curl_add_buffer_init() sets up and returns a fine buffer struct + */ +CURL_STATIC Curl_send_buffer *Curl_add_buffer_init(void) +{ + return calloc(1, sizeof(Curl_send_buffer)); +} + +/* + * Curl_add_buffer_send() sends a header buffer and frees all associated + * memory. Body data may be appended to the header data if desired. + * + * Returns CURLcode + */ +CURL_STATIC CURLcode Curl_add_buffer_send(Curl_send_buffer *in, + struct connectdata *conn, + + /* add the number of sent bytes to this + counter */ + long *bytes_written, + + /* how much of the buffer contains body data */ + size_t included_body_bytes, + int socketindex) + +{ + ssize_t amount; + CURLcode result; + char *ptr; + size_t size; + struct HTTP *http = conn->data->req.protop; + size_t sendsize; + curl_socket_t sockfd; + size_t headersize; + + DEBUGASSERT(socketindex <= SECONDARYSOCKET); + + sockfd = conn->sock[socketindex]; + + /* The looping below is required since we use non-blocking sockets, but due + to the circumstances we will just loop and try again and again etc */ + + ptr = in->buffer; + size = in->size_used; + + headersize = size - included_body_bytes; /* the initial part that isn't body + is header */ + + DEBUGASSERT(size > included_body_bytes); + + result = Curl_convert_to_network(conn->data, ptr, headersize); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) { + /* conversion failed, free memory and return to the caller */ + free(in->buffer); + free(in); + return result; + } + + + if(conn->handler->flags & PROTOPT_SSL) { + /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk + when we speak HTTPS, as if only a fraction of it is sent now, this data + needs to fit into the normal read-callback buffer later on and that + buffer is using this size. + */ + + sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size; + + /* OpenSSL is very picky and we must send the SAME buffer pointer to the + library when we attempt to re-send this buffer. Sending the same data + is not enough, we must use the exact same address. For this reason, we + must copy the data to the uploadbuffer first, since that is the buffer + we will be using if this send is retried later. + */ + memcpy(conn->data->state.uploadbuffer, ptr, sendsize); + ptr = conn->data->state.uploadbuffer; + } + else + sendsize = size; + + result = Curl_write(conn, sockfd, ptr, sendsize, &amount); + + if(!result) { + /* + * Note that we may not send the entire chunk at once, and we have a set + * number of data bytes at the end of the big buffer (out of which we may + * only send away a part). + */ + /* how much of the header that was sent */ + size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount; + size_t bodylen = amount - headlen; + + if(conn->data->set.verbose) { + /* this data _may_ contain binary stuff */ + Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn); + if(bodylen) { + /* there was body data sent beyond the initial header part, pass that + on to the debug callback too */ + Curl_debug(conn->data, CURLINFO_DATA_OUT, + ptr+headlen, bodylen, conn); + } + } + if(bodylen) + /* since we sent a piece of the body here, up the byte counter for it + accordingly */ + http->writebytecount += bodylen; + + /* 'amount' can never be a very large value here so typecasting it so a + signed 31 bit value should not cause problems even if ssize_t is + 64bit */ + *bytes_written += (long)amount; + + if(http) { + if((size_t)amount != size) { + /* The whole request could not be sent in one system call. We must + queue it up and send it later when we get the chance. We must not + loop here and wait until it might work again. */ + + size -= amount; + + ptr = in->buffer + amount; + + /* backup the currently set pointers */ + http->backup.fread_func = conn->fread_func; + http->backup.fread_in = conn->fread_in; + http->backup.postdata = http->postdata; + http->backup.postsize = http->postsize; + + /* set the new pointers for the request-sending */ + conn->fread_func = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; + http->postdata = ptr; + http->postsize = (curl_off_t)size; + + http->send_buffer = in; + http->sending = HTTPSEND_REQUEST; + + return CURLE_OK; + } + http->sending = HTTPSEND_BODY; + /* the full buffer was sent, clean up and return */ + } + else { + if((size_t)amount != size) + /* We have no continue-send mechanism now, fail. This can only happen + when this function is used from the CONNECT sending function. We + currently (stupidly) assume that the whole request is always sent + away in the first single chunk. + + This needs FIXing. + */ + return CURLE_SEND_ERROR; + else + conn->writechannel_inuse = FALSE; + } + } + free(in->buffer); + free(in); + + return result; +} + + +/* + * add_bufferf() add the formatted input to the buffer. + */ +CURL_STATIC CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...) +{ + char *s; + va_list ap; + va_start(ap, fmt); + s = vaprintf(fmt, ap); /* this allocs a new string to append */ + va_end(ap); + + if(s) { + CURLcode result = Curl_add_buffer(in, s, strlen(s)); + free(s); + return result; + } + /* If we failed, we cleanup the whole buffer and return error */ + free(in->buffer); + free(in); + return CURLE_OUT_OF_MEMORY; +} + +/* + * add_buffer() appends a memory chunk to the existing buffer + */ +CURL_STATIC CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) +{ + char *new_rb; + size_t new_size; + + if(~size < in->size_used) { + /* If resulting used size of send buffer would wrap size_t, cleanup + the whole buffer and return error. Otherwise the required buffer + size will fit into a single allocatable memory chunk */ + Curl_safefree(in->buffer); + free(in); + return CURLE_OUT_OF_MEMORY; + } + + if(!in->buffer || + ((in->size_used + size) > (in->size_max - 1))) { + + /* If current buffer size isn't enough to hold the result, use a + buffer size that doubles the required size. If this new size + would wrap size_t, then just use the largest possible one */ + + if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) || + (~(size*2) < (in->size_used*2))) + new_size = (size_t)-1; + else + new_size = (in->size_used+size)*2; + + if(in->buffer) + /* we have a buffer, enlarge the existing one */ + new_rb = realloc(in->buffer, new_size); + else + /* create a new buffer */ + new_rb = malloc(new_size); + + if(!new_rb) { + /* If we failed, we cleanup the whole buffer and return error */ + Curl_safefree(in->buffer); + free(in); + return CURLE_OUT_OF_MEMORY; + } + + in->buffer = new_rb; + in->size_max = new_size; + } + memcpy(&in->buffer[in->size_used], inptr, size); + + in->size_used += size; + + return CURLE_OK; +} + +/* end of the add_buffer functions */ +/* ------------------------------------------------------------------------- */ + + + +/* + * Curl_compareheader() + * + * Returns TRUE if 'headerline' contains the 'header' with given 'content'. + * Pass headers WITH the colon. + */ +bool +Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const char *content) /* content string to find */ +{ + /* RFC2616, section 4.2 says: "Each header field consists of a name followed + * by a colon (":") and the field value. Field names are case-insensitive. + * The field value MAY be preceded by any amount of LWS, though a single SP + * is preferred." */ + + size_t hlen = strlen(header); + size_t clen; + size_t len; + const char *start; + const char *end; + + if(!Curl_raw_nequal(headerline, header, hlen)) + return FALSE; /* doesn't start with header */ + + /* pass the header */ + start = &headerline[hlen]; + + /* pass all white spaces */ + while(*start && ISSPACE(*start)) + start++; + + /* find the end of the header line */ + end = strchr(start, '\r'); /* lines end with CRLF */ + if(!end) { + /* in case there's a non-standard compliant line here */ + end = strchr(start, '\n'); + + if(!end) + /* hm, there's no line ending here, use the zero byte! */ + end = strchr(start, '\0'); + } + + len = end-start; /* length of the content part of the input line */ + clen = strlen(content); /* length of the word to find */ + + /* find the content string in the rest of the line */ + for(;len>=clen;len--, start++) { + if(Curl_raw_nequal(start, content, clen)) + return TRUE; /* match! */ + } + + return FALSE; /* no match */ +} + +/* + * Curl_http_connect() performs HTTP stuff to do at connect-time, called from + * the generic Curl_connect(). + */ +CURL_STATIC CURLcode Curl_http_connect(struct connectdata *conn, bool *done) +{ + CURLcode result; + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "HTTP default"); + + /* the CONNECT procedure might not have been completed */ + result = Curl_proxy_connect(conn); + if(result) + return result; + + if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) + /* nothing else to do except wait right now - we're not done here. */ + return CURLE_OK; + + if(conn->given->flags & PROTOPT_SSL) { + /* perform SSL initialization */ + result = https_connecting(conn, done); + if(result) + return result; + } + else + *done = TRUE; + + return CURLE_OK; +} + +/* this returns the socket to wait for in the DO and DOING state for the multi + interface and then we're always _sending_ a request and thus we wait for + the single socket to become writable only */ +static int http_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + /* write mode */ + (void)numsocks; /* unused, we trust it to be at least 1 */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); +} + +#ifdef USE_SSL +static CURLcode https_connecting(struct connectdata *conn, bool *done) +{ + CURLcode result; + DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL)); + + /* perform SSL initialization for this socket */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); + if(result) + connclose(conn, "Failed HTTPS connection"); + + return result; +} +#endif + +#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ + defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) +/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only. + It should be made to query the generic SSL layer instead. */ +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn->handler->flags & PROTOPT_SSL) { + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + + if(!numsocks) + return GETSOCK_BLANK; + + if(connssl->connecting_state == ssl_connect_2_writing) { + /* write mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); + } + else if(connssl->connecting_state == ssl_connect_2_reading) { + /* read mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0); + } + } + return CURLE_OK; +} +#else +#ifdef USE_SSL +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +#endif /* USE_SSL */ +#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */ + +/* + * Curl_http_done() gets called from Curl_done() after a single HTTP request + * has been performed. + */ + +CURL_STATIC CURLcode Curl_http_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct SessionHandle *data = conn->data; + struct HTTP *http =data->req.protop; + + Curl_unencode_cleanup(conn); + +#ifdef USE_SPNEGO + if(data->state.proxyneg.state == GSS_AUTHSENT || + data->state.negotiate.state == GSS_AUTHSENT) { + /* add forbid re-use if http-code != 401/407 as a WA only needed for + * 401/407 that signal auth failure (empty) otherwise state will be RECV + * with current code */ + if((data->req.httpcode != 401) && (data->req.httpcode != 407)) + connclose(conn, "Negotiate transfer completed"); + Curl_cleanup_negotiate(data); + } +#endif + + /* set the proper values (possibly modified on POST) */ + conn->fread_func = data->set.fread_func; /* restore */ + conn->fread_in = data->set.in; /* restore */ + conn->seek_func = data->set.seek_func; /* restore */ + conn->seek_client = data->set.seek_client; /* restore */ + + if(http == NULL) + return CURLE_OK; + + if(http->send_buffer) { + Curl_send_buffer *buff = http->send_buffer; + + free(buff->buffer); + free(buff); + http->send_buffer = NULL; /* clear the pointer */ + } + + if(HTTPREQ_POST_FORM == data->set.httpreq) { + data->req.bytecount = http->readbytecount + http->writebytecount; + + Curl_formclean(&http->sendit); /* Now free that whole lot */ + if(http->form.fp) { + /* a file being uploaded was left opened, close it! */ + fclose(http->form.fp); + http->form.fp = NULL; + } + } + else if(HTTPREQ_PUT == data->set.httpreq) + data->req.bytecount = http->readbytecount + http->writebytecount; + + if(status) + return status; + + if(!premature && /* this check is pointless when DONE is called before the + entire operation is complete */ + !conn->bits.retry && + !data->set.connect_only && + ((http->readbytecount + + data->req.headerbytecount - + data->req.deductheadercount)) <= 0) { + /* If this connection isn't simply closed to be retried, AND nothing was + read from the HTTP server (that counts), this can't be right so we + return an error here */ + failf(data, "Empty reply from server"); + return CURLE_GOT_NOTHING; + } + + return CURLE_OK; +} + + +/* + * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons + * to avoid it include: + * + * - if the user specifically requested HTTP 1.0 + * - if the server we are connected to only supports 1.0 + * - if any server previously contacted to handle this request only supports + * 1.0. + */ +static bool use_http_1_1plus(const struct SessionHandle *data, + const struct connectdata *conn) +{ + return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) || + ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && + ((conn->httpversion == 11) || + ((conn->httpversion != 10) && + (data->state.httpversion != 10))))) ? TRUE : FALSE; +} + +/* check and possibly add an Expect: header */ +static CURLcode expect100(struct SessionHandle *data, + struct connectdata *conn, + Curl_send_buffer *req_buffer) +{ + CURLcode result = CURLE_OK; + const char *ptr; + data->state.expect100header = FALSE; /* default to false unless it is set + to TRUE below */ + if(use_http_1_1plus(data, conn) && + (conn->httpversion != 20)) { + /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an + Expect: 100-continue to the headers which actually speeds up post + operations (as there is one packet coming back from the web server) */ + ptr = Curl_checkheaders(conn, "Expect:"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else { + result = Curl_add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + if(!result) + data->state.expect100header = TRUE; + } + } + return result; +} + +enum proxy_use { + HEADER_SERVER, /* direct to server */ + HEADER_PROXY, /* regular request to proxy */ + HEADER_CONNECT /* sending CONNECT to a proxy */ +}; + +CURL_STATIC CURLcode Curl_add_custom_headers(struct connectdata *conn, + bool is_connect, + Curl_send_buffer *req_buffer) +{ + char *ptr; + struct curl_slist *h[2]; + struct curl_slist *headers; + int numlists=1; /* by default */ + struct SessionHandle *data = conn->data; + int i; + + enum proxy_use proxy; + + if(is_connect) + proxy = HEADER_CONNECT; + else + proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy? + HEADER_PROXY:HEADER_SERVER; + + switch(proxy) { + case HEADER_SERVER: + h[0] = data->set.headers; + break; + case HEADER_PROXY: + h[0] = data->set.headers; + if(data->set.sep_headers) { + h[1] = data->set.proxyheaders; + numlists++; + } + break; + case HEADER_CONNECT: + if(data->set.sep_headers) + h[0] = data->set.proxyheaders; + else + h[0] = data->set.headers; + break; + } + + /* loop through one or two lists */ + for(i=0; i < numlists; i++) { + headers = h[i]; + + while(headers) { + ptr = strchr(headers->data, ':'); + if(ptr) { + /* we require a colon for this to be a true header */ + + ptr++; /* pass the colon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr) { + /* only send this if the contents was non-blank */ + + if(conn->allocptr.host && + /* a Host: header was sent already, don't pass on any custom Host: + header as that will produce *two* in the same request! */ + checkprefix("Host:", headers->data)) + ; + else if(data->set.httpreq == HTTPREQ_POST_FORM && + /* this header (extended by formdata.c) is sent later */ + checkprefix("Content-Type:", headers->data)) + ; + else if(conn->bits.authneg && + /* while doing auth neg, don't allow the custom length since + we will force length zero then */ + checkprefix("Content-Length", headers->data)) + ; + else if(conn->allocptr.te && + /* when asking for Transfer-Encoding, don't pass on a custom + Connection: */ + checkprefix("Connection", headers->data)) + ; + else { + CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", + headers->data); + if(result) + return result; + } + } + } + else { + ptr = strchr(headers->data, ';'); + if(ptr) { + + ptr++; /* pass the semicolon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr) { + /* this may be used for something else in the future */ + } + else { + if(*(--ptr) == ';') { + CURLcode result; + + /* send no-value custom header if terminated by semicolon */ + *ptr = ':'; + result = Curl_add_bufferf(req_buffer, "%s\r\n", + headers->data); + if(result) + return result; + } + } + } + } + headers = headers->next; + } + } + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_add_timecondition(struct SessionHandle *data, + Curl_send_buffer *req_buffer) +{ + const struct tm *tm; + char *buf = data->state.buffer; + struct tm keeptime; + CURLcode result = Curl_gmtime(data->set.timevalue, &keeptime); + if(result) { + failf(data, "Invalid TIMEVALUE"); + return result; + } + tm = &keeptime; + + /* The If-Modified-Since header family should have their times set in + * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be + * represented in Greenwich Mean Time (GMT), without exception. For the + * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal + * Time)." (see page 20 of RFC2616). + */ + + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + snprintf(buf, BUFSIZE-1, + "%s, %02d %s %4d %02d:%02d:%02d GMT", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + result = Curl_add_bufferf(req_buffer, + "If-Modified-Since: %s\r\n", buf); + break; + case CURL_TIMECOND_IFUNMODSINCE: + result = Curl_add_bufferf(req_buffer, + "If-Unmodified-Since: %s\r\n", buf); + break; + case CURL_TIMECOND_LASTMOD: + result = Curl_add_bufferf(req_buffer, + "Last-Modified: %s\r\n", buf); + break; + } + + return result; +} + +/* + * Curl_http() gets called from the generic Curl_do() function when a HTTP + * request is to be performed. This creates and sends a properly constructed + * HTTP request. + */ +CURL_STATIC CURLcode Curl_http(struct connectdata *conn, bool *done) +{ + struct SessionHandle *data = conn->data; + CURLcode result = CURLE_OK; + struct HTTP *http; + const char *ppath = data->state.path; + bool paste_ftp_userpwd = FALSE; + char ftp_typecode[sizeof("/;type=?")] = ""; + const char *host = conn->host.name; + const char *te = ""; /* transfer-encoding */ + const char *ptr; + const char *request; + Curl_HttpReq httpreq = data->set.httpreq; +#if !defined(CURL_DISABLE_COOKIES) + char *addcookies = NULL; +#endif + curl_off_t included_body = 0; + const char *httpstring; + Curl_send_buffer *req_buffer; + curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */ + int seekerr = CURL_SEEKFUNC_OK; + + /* Always consider the DO phase done after this function call, even if there + may be parts of the request that is not yet sent, since we can deal with + the rest of the request in the PERFORM phase. */ + *done = TRUE; + + if(conn->httpversion < 20) { /* unless the connection is re-used and already + http2 */ + switch(conn->negnpn) { + case CURL_HTTP_VERSION_2_0: + conn->httpversion = 20; /* we know we're on HTTP/2 now */ + result = Curl_http2_init(conn); + if(result) + return result; + + result = Curl_http2_setup(conn); + if(result) + return result; + + result = Curl_http2_switched(conn, NULL, 0); + if(result) + return result; + break; + case CURL_HTTP_VERSION_1_1: + /* continue with HTTP/1.1 when explicitly requested */ + break; + default: + /* and as fallback */ + break; + } + } + else { + /* prepare for a http2 request */ + result = Curl_http2_setup(conn); + if(result) + return result; + } + + http = data->req.protop; + + if(!data->state.this_is_a_follow) { + /* Free to avoid leaking memory on multiple requests*/ + free(data->state.first_host); + + data->state.first_host = strdup(conn->host.name); + if(!data->state.first_host) + return CURLE_OUT_OF_MEMORY; + } + http->writebytecount = http->readbytecount = 0; + + if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && + data->set.upload) { + httpreq = HTTPREQ_PUT; + } + + /* Now set the 'request' pointer to the proper request string */ + if(data->set.str[STRING_CUSTOMREQUEST]) + request = data->set.str[STRING_CUSTOMREQUEST]; + else { + if(data->set.opt_no_body) + request = "HEAD"; + else { + DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); + switch(httpreq) { + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + request = "POST"; + break; + case HTTPREQ_PUT: + request = "PUT"; + break; + default: /* this should never happen */ + case HTTPREQ_GET: + request = "GET"; + break; + case HTTPREQ_HEAD: + request = "HEAD"; + break; + } + } + } + + /* The User-Agent string might have been allocated in url.c already, because + it might have been used in the proxy connect, but if we have got a header + with the user-agent string specified, we erase the previously made string + here. */ + if(Curl_checkheaders(conn, "User-Agent:")) { + free(conn->allocptr.uagent); + conn->allocptr.uagent=NULL; + } + + /* setup the authentication headers */ + result = Curl_http_output_auth(conn, request, ppath, FALSE); + if(result) + return result; + + if((data->state.authhost.multi || data->state.authproxy.multi) && + (httpreq != HTTPREQ_GET) && + (httpreq != HTTPREQ_HEAD)) { + /* Auth is required and we are not authenticated yet. Make a PUT or POST + with content-length zero as a "probe". */ + conn->bits.authneg = TRUE; + } + else + conn->bits.authneg = FALSE; + + Curl_safefree(conn->allocptr.ref); + if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) { + conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + if(!conn->allocptr.ref) + return CURLE_OUT_OF_MEMORY; + } + else + conn->allocptr.ref = NULL; + +#if !defined(CURL_DISABLE_COOKIES) + if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:")) + addcookies = data->set.str[STRING_COOKIE]; +#endif + + if(!Curl_checkheaders(conn, "Accept-Encoding:") && + data->set.str[STRING_ENCODING]) { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = + aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); + if(!conn->allocptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; + } + +#ifdef HAVE_LIBZ + /* we only consider transfer-encoding magic if libz support is built-in */ + + if(!Curl_checkheaders(conn, "TE:") && + data->set.http_transfer_encoding) { + /* When we are to insert a TE: header in the request, we must also insert + TE in a Connection: header, so we need to merge the custom provided + Connection: header and prevent the original to get sent. Note that if + the user has inserted his/hers own TE: header we don't do this magic + but then assume that the user will handle it all! */ + char *cptr = Curl_checkheaders(conn, "Connection:"); +#define TE_HEADER "TE: gzip\r\n" + + Curl_safefree(conn->allocptr.te); + + /* Create the (updated) Connection: header */ + conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr): + strdup("Connection: TE\r\n" TE_HEADER); + + if(!conn->allocptr.te) + return CURLE_OUT_OF_MEMORY; + } +#endif + + if(conn->httpversion == 20) + /* In HTTP2 forbids Transfer-Encoding: chunked */ + ptr = NULL; + else { + ptr = Curl_checkheaders(conn, "Transfer-Encoding:"); + if(ptr) { + /* Some kind of TE is requested, check if 'chunked' is chosen */ + data->req.upload_chunky = + Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); + } + else { + if((conn->handler->protocol&PROTO_FAMILY_HTTP) && + data->set.upload && + (data->state.infilesize == -1)) { + if(conn->bits.authneg) + /* don't enable chunked during auth neg */ + ; + else if(use_http_1_1plus(data, conn)) { + /* HTTP, upload, unknown file size and not HTTP 1.0 */ + data->req.upload_chunky = TRUE; + } + else { + failf(data, "Chunky upload is not supported by HTTP 1.0"); + return CURLE_UPLOAD_FAILED; + } + } + else { + /* else, no chunky upload */ + data->req.upload_chunky = FALSE; + } + + if(data->req.upload_chunky) + te = "Transfer-Encoding: chunked\r\n"; + } + } + + Curl_safefree(conn->allocptr.host); + + ptr = Curl_checkheaders(conn, "Host:"); + if(ptr && (!data->state.this_is_a_follow || + Curl_raw_equal(data->state.first_host, conn->host.name))) { +#if !defined(CURL_DISABLE_COOKIES) + /* If we have a given custom Host: header, we extract the host name in + order to possibly use it for cookie reasons later on. We only allow the + custom Host: header if this is NOT a redirect, as setting Host: in the + redirected request is being out on thin ice. Except if the host name + is the same as the first one! */ + char *cookiehost = Curl_copy_header_value(ptr); + if(!cookiehost) + return CURLE_OUT_OF_MEMORY; + if(!*cookiehost) + /* ignore empty data */ + free(cookiehost); + else { + /* If the host begins with '[', we start searching for the port after + the bracket has been closed */ + int startsearch = 0; + if(*cookiehost == '[') { + char *closingbracket; + /* since the 'cookiehost' is an allocated memory area that will be + freed later we cannot simply increment the pointer */ + memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1); + closingbracket = strchr(cookiehost, ']'); + if(closingbracket) + *closingbracket = 0; + } + else { + char *colon = strchr(cookiehost + startsearch, ':'); + if(colon) + *colon = 0; /* The host must not include an embedded port number */ + } + Curl_safefree(conn->allocptr.cookiehost); + conn->allocptr.cookiehost = cookiehost; + } +#endif + + if(strcmp("Host:", ptr)) { + conn->allocptr.host = aprintf("%s\r\n", ptr); + if(!conn->allocptr.host) + return CURLE_OUT_OF_MEMORY; + } + else + /* when clearing the header */ + conn->allocptr.host = NULL; + } + else { + /* When building Host: headers, we must put the host name within + [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ + + if(((conn->given->protocol&CURLPROTO_HTTPS) && + (conn->remote_port == PORT_HTTPS)) || + ((conn->given->protocol&CURLPROTO_HTTP) && + (conn->remote_port == PORT_HTTP)) ) + /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include + the port number in the host string */ + conn->allocptr.host = aprintf("Host: %s%s%s\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":""); + else + conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":"", + conn->remote_port); + + if(!conn->allocptr.host) + /* without Host: we can't make a nice request */ + return CURLE_OUT_OF_MEMORY; + } + +#ifndef CURL_DISABLE_PROXY + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + /* Using a proxy but does not tunnel through it */ + + /* The path sent to the proxy is in fact the entire URL. But if the remote + host is a IDN-name, we must make sure that the request we produce only + uses the encoded host name! */ + if(conn->host.dispname != conn->host.name) { + char *url = data->change.url; + ptr = strstr(url, conn->host.dispname); + if(ptr) { + /* This is where the display name starts in the URL, now replace this + part with the encoded name. TODO: This method of replacing the host + name is rather crude as I believe there's a slight risk that the + user has entered a user name or password that contain the host name + string. */ + size_t currlen = strlen(conn->host.dispname); + size_t newlen = strlen(conn->host.name); + size_t urllen = strlen(url); + + char *newurl; + + newurl = malloc(urllen + newlen - currlen + 1); + if(newurl) { + /* copy the part before the host name */ + memcpy(newurl, url, ptr - url); + /* append the new host name instead of the old */ + memcpy(newurl + (ptr - url), conn->host.name, newlen); + /* append the piece after the host name */ + memcpy(newurl + newlen + (ptr - url), + ptr + currlen, /* copy the trailing zero byte too */ + urllen - (ptr-url) - currlen + 1); + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + data->change.url = newurl; + data->change.url_alloc = TRUE; + } + else + return CURLE_OUT_OF_MEMORY; + } + } + ppath = data->change.url; + if(checkprefix("ftp://", ppath)) { + if(data->set.proxy_transfer_mode) { + /* when doing ftp, append ;type= if not present */ + char *type = strstr(ppath, ";type="); + if(type && type[6] && type[7] == 0) { + switch (Curl_raw_toupper(type[6])) { + case 'A': + case 'D': + case 'I': + break; + default: + type = NULL; + } + } + if(!type) { + char *p = ftp_typecode; + /* avoid sending invalid URLs like ftp://example.com;type=i if the + * user specified ftp://example.com without the slash */ + if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') { + *p++ = '/'; + } + snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c", + data->set.prefer_ascii ? 'a' : 'i'); + } + } + if(conn->bits.user_passwd && !conn->bits.userpwd_in_url) + paste_ftp_userpwd = TRUE; + } + } +#endif /* CURL_DISABLE_PROXY */ + + if(HTTPREQ_POST_FORM == httpreq) { + /* we must build the whole post sequence first, so that we have a size of + the whole transfer before we start to send it */ + result = Curl_getformdata(data, &http->sendit, data->set.httppost, + Curl_checkheaders(conn, "Content-Type:"), + &http->postsize); + if(result) + return result; + } + + http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n"; + + if(( (HTTPREQ_POST == httpreq) || + (HTTPREQ_POST_FORM == httpreq) || + (HTTPREQ_PUT == httpreq) ) && + data->state.resume_from) { + /********************************************************************** + * Resuming upload in HTTP means that we PUT or POST and that we have + * got a resume_from value set. The resume value has already created + * a Range: header that will be passed along. We need to "fast forward" + * the file the given number of bytes and decrease the assume upload + * file size before we continue this venture in the dark lands of HTTP. + *********************************************************************/ + + if(data->state.resume_from < 0 ) { + /* + * This is meant to get the size of the present remote-file by itself. + * We don't support this now. Bail out! + */ + data->state.resume_from = 0; + } + + if(data->state.resume_from && !data->state.this_is_a_follow) { + /* do we still game? */ + + /* Now, let's read off the proper amount of bytes from the + input. */ + if(conn->seek_func) { + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_READ_ERROR; + } + /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + else { + curl_off_t passed=0; + do { + size_t readthisamountnow = + (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? + BUFSIZE : curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + data->set.fread_func(data->state.buffer, 1, readthisamountnow, + data->set.in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T + " bytes from the input", passed); + return CURLE_READ_ERROR; + } + } while(passed < data->state.resume_from); + } + } + + /* now, decrease the size of the read */ + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; + + if(data->state.infilesize <= 0) { + failf(data, "File already completely uploaded"); + return CURLE_PARTIAL_FILE; + } + } + /* we've passed, proceed as normal */ + } + } + if(data->state.use_range) { + /* + * A range is selected. We use different headers whether we're downloading + * or uploading and we always let customized headers override our internal + * ones if any such are specified. + */ + if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && + !Curl_checkheaders(conn, "Range:")) { + /* if a line like this was already allocated, free the previous one */ + free(conn->allocptr.rangeline); + conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", + data->state.range); + } + else if((httpreq != HTTPREQ_GET) && + !Curl_checkheaders(conn, "Content-Range:")) { + + /* if a line like this was already allocated, free the previous one */ + free(conn->allocptr.rangeline); + + if(data->set.set_resume_from < 0) { + /* Upload resume was asked for, but we don't know the size of the + remote part so we tell the server (and act accordingly) that we + upload the whole file (again) */ + conn->allocptr.rangeline = + aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.infilesize - 1, data->state.infilesize); + + } + else if(data->state.resume_from) { + /* This is because "resume" was selected */ + curl_off_t total_expected_size= + data->state.resume_from + data->state.infilesize; + conn->allocptr.rangeline = + aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.range, total_expected_size-1, + total_expected_size); + } + else { + /* Range was selected and then we just pass the incoming range and + append total size */ + conn->allocptr.rangeline = + aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.range, data->state.infilesize); + } + if(!conn->allocptr.rangeline) + return CURLE_OUT_OF_MEMORY; + } + } + + /* Use 1.1 unless the user specifically asked for 1.0 or the server only + supports 1.0 */ + httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0"; + + /* initialize a dynamic send-buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + /* add the main request stuff */ + /* GET/HEAD/POST/PUT */ + result = Curl_add_bufferf(req_buffer, "%s ", request); + if(result) + return result; + + /* url */ + if(paste_ftp_userpwd) + result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s", + conn->user, conn->passwd, + ppath + sizeof("ftp://") - 1); + else + result = Curl_add_buffer(req_buffer, ppath, strlen(ppath)); + if(result) + return result; + + result = + Curl_add_bufferf(req_buffer, + "%s" /* ftp typecode (;type=x) */ + " HTTP/%s\r\n" /* HTTP version */ + "%s" /* host */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + "%s" /* range */ + "%s" /* user agent */ + "%s" /* accept */ + "%s" /* TE: */ + "%s" /* accept-encoding */ + "%s" /* referer */ + "%s" /* Proxy-Connection */ + "%s",/* transfer-encoding */ + + ftp_typecode, + httpstring, + (conn->allocptr.host?conn->allocptr.host:""), + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + conn->allocptr.userpwd?conn->allocptr.userpwd:"", + (data->state.use_range && conn->allocptr.rangeline)? + conn->allocptr.rangeline:"", + (data->set.str[STRING_USERAGENT] && + *data->set.str[STRING_USERAGENT] && + conn->allocptr.uagent)? + conn->allocptr.uagent:"", + http->p_accept?http->p_accept:"", + conn->allocptr.te?conn->allocptr.te:"", + (data->set.str[STRING_ENCODING] && + *data->set.str[STRING_ENCODING] && + conn->allocptr.accept_encoding)? + conn->allocptr.accept_encoding:"", + (data->change.referer && conn->allocptr.ref)? + conn->allocptr.ref:"" /* Referer: */, + (conn->bits.httpproxy && + !conn->bits.tunnel_proxy && + !Curl_checkProxyheaders(conn, "Proxy-Connection:"))? + "Proxy-Connection: Keep-Alive\r\n":"", + te + ); + + /* + * Free userpwd for Negotiate/NTLM. Cannot reuse as it is associated with + * the connection and shouldn't be repeated over it either. + */ + switch (data->state.authhost.picked) { + case CURLAUTH_NEGOTIATE: + case CURLAUTH_NTLM: + case CURLAUTH_NTLM_WB: + Curl_safefree(conn->allocptr.userpwd); + break; + } + + /* + * Same for proxyuserpwd + */ + switch (data->state.authproxy.picked) { + case CURLAUTH_NEGOTIATE: + case CURLAUTH_NTLM: + case CURLAUTH_NTLM_WB: + Curl_safefree(conn->allocptr.proxyuserpwd); + break; + } + + if(result) + return result; + + if(!(conn->handler->flags&PROTOPT_SSL) && + conn->httpversion != 20 && + (data->set.httpversion == CURL_HTTP_VERSION_2_0)) { + /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done + over SSL */ + result = Curl_http2_request_upgrade(req_buffer, conn); + if(result) + return result; + } + +#if !defined(CURL_DISABLE_COOKIES) + if(data->cookies || addcookies) { + struct Cookie *co=NULL; /* no cookies from start */ + int count=0; + + if(data->cookies) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + co = Curl_cookie_getlist(data->cookies, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:host, + data->state.path, + (conn->handler->protocol&CURLPROTO_HTTPS)? + TRUE:FALSE); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + if(co) { + struct Cookie *store=co; + /* now loop through all cookies that matched */ + while(co) { + if(co->value) { + if(0 == count) { + result = Curl_add_bufferf(req_buffer, "Cookie: "); + if(result) + break; + } + result = Curl_add_bufferf(req_buffer, + "%s%s=%s", count?"; ":"", + co->name, co->value); + if(result) + break; + count++; + } + co = co->next; /* next cookie please */ + } + Curl_cookie_freelist(store, FALSE); /* free the cookie list */ + } + if(addcookies && !result) { + if(!count) + result = Curl_add_bufferf(req_buffer, "Cookie: "); + if(!result) { + result = Curl_add_bufferf(req_buffer, "%s%s", count?"; ":"", + addcookies); + count++; + } + } + if(count && !result) + result = Curl_add_buffer(req_buffer, "\r\n", 2); + + if(result) + return result; + } +#endif + + if(data->set.timecondition) { + result = Curl_add_timecondition(data, req_buffer); + if(result) + return result; + } + + result = Curl_add_custom_headers(conn, FALSE, req_buffer); + if(result) + return result; + + http->postdata = NULL; /* nothing to post at this point */ + Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */ + + /* 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 + data yet. */ + + switch(httpreq) { + + case HTTPREQ_POST_FORM: + if(!http->sendit || conn->bits.authneg) { + /* nothing to post! */ + result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); + if(result) + return result; + + result = Curl_add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, + -1, NULL); + break; + } + + if(Curl_FormInit(&http->form, http->sendit)) { + failf(data, "Internal HTTP POST error!"); + return CURLE_HTTP_POST_ERROR; + } + + /* Get the currently set callback function pointer and store that in the + form struct since we might want the actual user-provided callback later + on. The conn->fread_func pointer itself will be changed for the + multipart case to the function that returns a multipart formatted + stream. */ + http->form.fread_func = conn->fread_func; + + /* Set the read function to read from the generated form data */ + conn->fread_func = (curl_read_callback)Curl_FormReader; + conn->fread_in = &http->form; + + http->sending = HTTPSEND_BODY; + + if(!data->req.upload_chunky && + !Curl_checkheaders(conn, "Content-Length:")) { + /* only add Content-Length if not uploading chunked */ + result = Curl_add_bufferf(req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", http->postsize); + if(result) + return result; + } + + result = expect100(data, conn, req_buffer); + if(result) + return result; + + { + + /* Get Content-Type: line from Curl_formpostheader. + */ + char *contentType; + size_t linelength=0; + contentType = Curl_formpostheader((void *)&http->form, + &linelength); + if(!contentType) { + failf(data, "Could not get Content-Type header line!"); + return CURLE_HTTP_POST_ERROR; + } + + result = Curl_add_buffer(req_buffer, contentType, linelength); + if(result) + return result; + } + + /* make the request end in a true CRLF */ + result = Curl_add_buffer(req_buffer, "\r\n", 2); + if(result) + return result; + + /* set upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); + + /* fire away the whole request to the server */ + result = Curl_add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, FIRSTSOCKET, + &http->writebytecount); + + if(result) { + Curl_formclean(&http->sendit); /* free that whole lot */ + return result; + } + + /* convert the form data */ + result = Curl_convert_form(data, http->sendit); + if(result) { + Curl_formclean(&http->sendit); /* free that whole lot */ + return result; + } + + break; + + case HTTPREQ_PUT: /* Let's PUT the data to the server! */ + + if(conn->bits.authneg) + postsize = 0; + else + postsize = data->state.infilesize; + + if((postsize != -1) && !data->req.upload_chunky && + !Curl_checkheaders(conn, "Content-Length:")) { + /* only add Content-Length if not uploading chunked */ + result = Curl_add_bufferf(req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", postsize); + if(result) + return result; + } + + if(postsize != 0) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + + result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */ + if(result) + return result; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize); + + /* this sends the buffer and frees all the buffer resources */ + result = Curl_add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending PUT request"); + else + /* prepare for transfer */ + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, postsize?FIRSTSOCKET:-1, + postsize?&http->writebytecount:NULL); + if(result) + return result; + break; + + case HTTPREQ_POST: + /* this is the simple POST, using x-www-form-urlencoded style */ + + if(conn->bits.authneg) + postsize = 0; + else { + /* figure out the size of the postfields */ + postsize = (data->set.postfieldsize != -1)? + data->set.postfieldsize: + (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1); + } + + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + if((postsize != -1) && !data->req.upload_chunky && + !Curl_checkheaders(conn, "Content-Length:")) { + /* we allow replacing this header if not during auth negotiation, + although it isn't very wise to actually set your own */ + result = Curl_add_bufferf(req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", postsize); + if(result) + return result; + } + + if(!Curl_checkheaders(conn, "Content-Type:")) { + result = Curl_add_bufferf(req_buffer, + "Content-Type: application/" + "x-www-form-urlencoded\r\n"); + if(result) + return result; + } + + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(conn, "Expect:"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; + + if(data->set.postfields) { + + /* In HTTP2, we send request body in DATA frame regardless of + its size. */ + if(conn->httpversion != 20 && + !data->state.expect100header && + (postsize < MAX_INITIAL_POST_SIZE)) { + /* if we don't use expect: 100 AND + postsize is less than MAX_INITIAL_POST_SIZE + + then append the post data to the HTTP request header. This limit + is no magic limit but only set to prevent really huge POSTs to + get the data duplicated with malloc() and family. */ + + result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + + if(!data->req.upload_chunky) { + /* We're not sending it 'chunked', append it to the request + already now to reduce the number if send() calls */ + result = Curl_add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + included_body = postsize; + } + else { + if(postsize) { + /* Append the POST data chunky-style */ + result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); + if(!result) { + result = Curl_add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + if(!result) + result = Curl_add_buffer(req_buffer, "\r\n", 2); + included_body = postsize + 2; + } + } + if(!result) + result = Curl_add_buffer(req_buffer, "\x30\x0d\x0a\x0d\x0a", 5); + /* 0 CR LF CR LF */ + included_body += 5; + } + if(result) + return result; + /* Make sure the progress information is accurate */ + Curl_pgrsSetUploadSize(data, postsize); + } + else { + /* A huge POST coming up, do data separate from the request */ + http->postsize = postsize; + http->postdata = data->set.postfields; + + http->sending = HTTPSEND_BODY; + + conn->fread_func = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); + + result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + } + } + else { + result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + + if(data->req.upload_chunky && conn->bits.authneg) { + /* Chunky upload is selected and we're negotiating auth still, send + end-of-data only */ + result = Curl_add_buffer(req_buffer, + "\x30\x0d\x0a\x0d\x0a", 5); + /* 0 CR LF CR LF */ + if(result) + return result; + } + + else if(data->set.postfieldsize) { + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize?postsize:-1); + + /* set the pointer to mark that we will send the post body using the + read callback, but only if we're not in authenticate + negotiation */ + if(!conn->bits.authneg) { + http->postdata = (char *)&http->postdata; + http->postsize = postsize; + } + } + } + /* issue the request */ + result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, + (size_t)included_body, FIRSTSOCKET); + + if(result) + failf(data, "Failed sending HTTP POST request"); + else + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); + break; + + default: + result = Curl_add_buffer(req_buffer, "\r\n", 2); + if(result) + return result; + + /* issue the request */ + result = Curl_add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + + if(result) + failf(data, "Failed sending HTTP request"); + else + /* HTTP GET/HEAD download: */ + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, + http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); + } + if(result) + return result; + + if(http->writebytecount) { + /* if a request-body has been sent off, we make sure this progress is noted + properly */ + Curl_pgrsSetUploadCounter(data, http->writebytecount); + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + if(http->writebytecount >= postsize) { + /* already sent the entire request body, mark the "upload" as + complete */ + infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T + " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n", + http->writebytecount, postsize); + data->req.upload_done = TRUE; + data->req.keepon &= ~KEEP_SEND; /* we're done writing */ + data->req.exp100 = EXP100_SEND_DATA; /* already sent */ + } + } + + return result; +} + +/* + * checkhttpprefix() + * + * Returns TRUE if member of the list matches prefix of string + */ +static bool +checkhttpprefix(struct SessionHandle *data, + const char *s) +{ + struct curl_slist *head = data->set.http200aliases; + bool rc = FALSE; +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding using a scratch area */ + char *scratch = strdup(s); + if(NULL == scratch) { + failf (data, "Failed to allocate memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + } + if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(scratch); + return FALSE; /* can't return CURLE_foobar so return FALSE */ + } + s = scratch; +#endif /* CURL_DOES_CONVERSIONS */ + + while(head) { + if(checkprefix(head->data, s)) { + rc = TRUE; + break; + } + head = head->next; + } + + if(!rc && (checkprefix("HTTP/", s))) + rc = TRUE; + +#ifdef CURL_DOES_CONVERSIONS + free(scratch); +#endif /* CURL_DOES_CONVERSIONS */ + return rc; +} + +#ifndef CURL_DISABLE_RTSP +static bool +checkrtspprefix(struct SessionHandle *data, + const char *s) +{ + +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding using a scratch area */ + char *scratch = strdup(s); + if(NULL == scratch) { + failf (data, "Failed to allocate memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + } + if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(scratch); + return FALSE; /* can't return CURLE_foobar so return FALSE */ + } + s = scratch; +#else + (void)data; /* unused */ +#endif /* CURL_DOES_CONVERSIONS */ + if(checkprefix("RTSP/", s)) + return TRUE; + else + return FALSE; +} +#endif /* CURL_DISABLE_RTSP */ + +static bool +checkprotoprefix(struct SessionHandle *data, struct connectdata *conn, + const char *s) +{ +#ifndef CURL_DISABLE_RTSP + if(conn->handler->protocol & CURLPROTO_RTSP) + return checkrtspprefix(data, s); +#else + (void)conn; +#endif /* CURL_DISABLE_RTSP */ + + return checkhttpprefix(data, s); +} + +/* + * header_append() copies a chunk of data to the end of the already received + * header. We make sure that the full string fit in the allocated header + * buffer, or else we enlarge it. + */ +static CURLcode header_append(struct SessionHandle *data, + struct SingleRequest *k, + size_t length) +{ + if(k->hbuflen + length >= data->state.headersize) { + /* We enlarge the header buffer as it is too small */ + char *newbuff; + size_t hbufp_index; + size_t newsize; + + if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) { + /* The reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause + reallocs infinitely */ + failf (data, "Avoided giant realloc for header (max is %d)!", + CURL_MAX_HTTP_HEADER); + return CURLE_OUT_OF_MEMORY; + } + + newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2); + hbufp_index = k->hbufp - data->state.headerbuff; + newbuff = realloc(data->state.headerbuff, newsize); + if(!newbuff) { + failf (data, "Failed to alloc memory for big header!"); + return CURLE_OUT_OF_MEMORY; + } + data->state.headersize=newsize; + data->state.headerbuff = newbuff; + k->hbufp = data->state.headerbuff + hbufp_index; + } + memcpy(k->hbufp, k->str_start, length); + k->hbufp += length; + k->hbuflen += length; + *k->hbufp = 0; + + return CURLE_OK; +} + +static void print_http_error(struct SessionHandle *data) +{ + struct SingleRequest *k = &data->req; + char *beg = k->p; + + /* make sure that data->req.p points to the HTTP status line */ + if(!strncmp(beg, "HTTP", 4)) { + + /* skip to HTTP status code */ + beg = strchr(beg, ' '); + if(beg && *++beg) { + + /* find trailing CR */ + char end_char = '\r'; + char *end = strchr(beg, end_char); + if(!end) { + /* try to find LF (workaround for non-compliant HTTP servers) */ + end_char = '\n'; + end = strchr(beg, end_char); + } + + if(end) { + /* temporarily replace CR or LF by NUL and print the error message */ + *end = '\0'; + failf(data, "The requested URL returned error: %s", beg); + + /* restore the previously replaced CR or LF */ + *end = end_char; + return; + } + } + } + + /* fall-back to printing the HTTP status code only */ + failf(data, "The requested URL returned error: %d", k->httpcode); +} + +/* + * Read any HTTP header lines from the server and pass them to the client app. + */ +CURL_STATIC CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, + struct connectdata *conn, + ssize_t *nread, + bool *stop_reading) +{ + CURLcode result; + struct SingleRequest *k = &data->req; + + /* header line within buffer loop */ + do { + size_t rest_length; + size_t full_length; + int writetype; + + /* str_start is start of line within buf */ + k->str_start = k->str; + + /* data is in network encoding so use 0x0a instead of '\n' */ + k->end_ptr = memchr(k->str_start, 0x0a, *nread); + + if(!k->end_ptr) { + /* Not a complete header line within buffer, append the data to + the end of the headerbuff. */ + result = header_append(data, k, *nread); + if(result) + return result; + + if(!k->headerline && (k->hbuflen>5)) { + /* make a first check that this looks like a protocol header */ + if(!checkprotoprefix(data, conn, data->state.headerbuff)) { + /* this is not the beginning of a protocol first header line */ + k->header = FALSE; + k->badheader = HEADER_ALLBAD; + break; + } + } + + break; /* read more and try again */ + } + + /* decrease the size of the remaining (supposed) header line */ + rest_length = (k->end_ptr - k->str)+1; + *nread -= (ssize_t)rest_length; + + k->str = k->end_ptr + 1; /* move past new line */ + + full_length = k->str - k->str_start; + + result = header_append(data, k, full_length); + if(result) + return result; + + k->end_ptr = k->hbufp; + k->p = data->state.headerbuff; + + /**** + * We now have a FULL header line that p points to + *****/ + + if(!k->headerline) { + /* the first read header */ + if((k->hbuflen>5) && + !checkprotoprefix(data, conn, data->state.headerbuff)) { + /* this is not the beginning of a protocol first header line */ + k->header = FALSE; + if(*nread) + /* since there's more, this is a partial bad header */ + k->badheader = HEADER_PARTHEADER; + else { + /* this was all we read so it's all a bad header */ + k->badheader = HEADER_ALLBAD; + *nread = (ssize_t)rest_length; + } + break; + } + } + + /* headers are in network encoding so + use 0x0a and 0x0d instead of '\n' and '\r' */ + if((0x0a == *k->p) || (0x0d == *k->p)) { + size_t headerlen; + /* Zero-length header line means end of headers! */ + +#ifdef CURL_DOES_CONVERSIONS + if(0x0d == *k->p) { + *k->p = '\r'; /* replace with CR in host encoding */ + k->p++; /* pass the CR byte */ + } + if(0x0a == *k->p) { + *k->p = '\n'; /* replace with LF in host encoding */ + k->p++; /* pass the LF byte */ + } +#else + if('\r' == *k->p) + k->p++; /* pass the \r byte */ + if('\n' == *k->p) + k->p++; /* pass the \n byte */ +#endif /* CURL_DOES_CONVERSIONS */ + + if(100 <= k->httpcode && 199 >= k->httpcode) { + /* + * We have made a HTTP PUT or POST and this is 1.1-lingo + * that tells us that the server is OK with this and ready + * to receive the data. + * However, we'll get more headers now so we must get + * back into the header-parsing state! + */ + k->header = TRUE; + k->headerline = 0; /* restart the header line counter */ + + /* "A user agent MAY ignore unexpected 1xx status responses." */ + switch(k->httpcode) { + case 100: + /* if we did wait for this do enable write now! */ + if(k->exp100) { + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + } + break; + case 101: + /* Switching Protocols */ + if(k->upgr101 == UPGR101_REQUESTED) { + infof(data, "Received 101\n"); + k->upgr101 = UPGR101_RECEIVED; + + /* switch to http2 now. The bytes after response headers + are also processed here, otherwise they are lost. */ + result = Curl_http2_switched(conn, k->str, *nread); + if(result) + return result; + *nread = 0; + } + break; + default: + break; + } + } + else { + k->header = FALSE; /* no more header to parse! */ + + if((k->size == -1) && !k->chunk && !conn->bits.close && + (conn->httpversion == 11) && + !(conn->handler->protocol & CURLPROTO_RTSP) && + data->set.httpreq != HTTPREQ_HEAD) { + /* On HTTP 1.1, when connection is not to get closed, but no + Content-Length nor Content-Encoding chunked have been + received, according to RFC2616 section 4.4 point 5, we + assume that the server will close the connection to + signal the end of the document. */ + infof(data, "no chunk, no close, no size. Assume close to " + "signal end\n"); + connclose(conn, "HTTP: No end-of-message indicator"); + } + } + + /* + * When all the headers have been parsed, see if we should give + * up and return an error. + */ + if(http_should_fail(conn)) { + failf (data, "The requested URL returned error: %d", + k->httpcode); + return CURLE_HTTP_RETURNED_ERROR; + } + + /* now, only output this if the header AND body are requested: + */ + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + headerlen = k->p - data->state.headerbuff; + + result = Curl_client_write(conn, writetype, + data->state.headerbuff, + headerlen); + if(result) + return result; + + data->info.header_size += (long)headerlen; + data->req.headerbytecount += (long)headerlen; + + data->req.deductheadercount = + (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0; + + if(!*stop_reading) { + /* Curl_http_auth_act() checks what authentication methods + * that are available and decides which one (if any) to + * use. It will set 'newurl' if an auth method was picked. */ + result = Curl_http_auth_act(conn); + + if(result) + return result; + + if(k->httpcode >= 300) { + if((!conn->bits.authneg) && !conn->bits.close && + !conn->bits.rewindaftersend) { + /* + * General treatment of errors when about to send data. Including : + * "417 Expectation Failed", while waiting for 100-continue. + * + * The check for close above is done simply because of something + * else has already deemed the connection to get closed then + * something else should've considered the big picture and we + * avoid this check. + * + * rewindaftersend indicates that something has told libcurl to + * continue sending even if it gets discarded + */ + + switch(data->set.httpreq) { + case HTTPREQ_PUT: + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + /* We got an error response. If this happened before the whole + * request body has been sent we stop sending and mark the + * connection for closure after we've read the entire response. + */ + if(!k->upload_done) { + infof(data, "HTTP error before end of send, stop sending\n"); + connclose(conn, "Stop sending data before everything sent"); + k->upload_done = TRUE; + k->keepon &= ~KEEP_SEND; /* don't send */ + if(data->state.expect100header) + k->exp100 = EXP100_FAILED; + } + break; + + default: /* default label present to avoid compiler warnings */ + break; + } + } + } + + if(conn->bits.rewindaftersend) { + /* We rewind after a complete send, so thus we continue + sending now */ + infof(data, "Keep sending data to get tossed away!\n"); + k->keepon |= KEEP_SEND; + } + } + + if(!k->header) { + /* + * really end-of-headers. + * + * If we requested a "no body", this is a good time to get + * out and return home. + */ + if(data->set.opt_no_body) + *stop_reading = TRUE; + else { + /* If we know the expected size of this document, we set the + maximum download size to the size of the expected + document or else, we won't know when to stop reading! + + Note that we set the download maximum even if we read a + "Connection: close" header, to make sure that + "Content-Length: 0" still prevents us from attempting to + read the (missing) response-body. + */ + /* According to RFC2616 section 4.4, we MUST ignore + Content-Length: headers if we are now receiving data + using chunked Transfer-Encoding. + */ + if(k->chunk) + k->maxdownload = k->size = -1; + } + if(-1 != k->size) { + /* We do this operation even if no_body is true, since this + data might be retrieved later with curl_easy_getinfo() + and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */ + + Curl_pgrsSetDownloadSize(data, k->size); + k->maxdownload = k->size; + } + + /* If max download size is *zero* (nothing) we already + have nothing and can safely return ok now! */ + if(0 == k->maxdownload) + *stop_reading = TRUE; + + if(*stop_reading) { + /* we make sure that this socket isn't read more now */ + k->keepon &= ~KEEP_RECV; + } + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + k->str_start, headerlen, conn); + break; /* exit header line loop */ + } + + /* We continue reading headers, so reset the line-based + header parsing variables hbufp && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + continue; + } + + /* + * Checks for special headers coming up. + */ + + if(!k->headerline++) { + /* This is the first header, it MUST be the error code line + or else we consider this to be the body right away! */ + int httpversion_major; + int rtspversion_major; + int nc = 0; +#ifdef CURL_DOES_CONVERSIONS +#define HEADER1 scratch +#define SCRATCHSIZE 21 + CURLcode res; + char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */ + /* We can't really convert this yet because we + don't know if it's the 1st header line or the body. + So we do a partial conversion into a scratch area, + leaving the data at k->p as-is. + */ + strncpy(&scratch[0], k->p, SCRATCHSIZE); + scratch[SCRATCHSIZE] = 0; /* null terminate */ + res = Curl_convert_from_network(data, + &scratch[0], + SCRATCHSIZE); + if(res) + /* Curl_convert_from_network calls failf if unsuccessful */ + return res; +#else +#define HEADER1 k->p /* no conversion needed, just use k->p */ +#endif /* CURL_DOES_CONVERSIONS */ + + if(conn->handler->protocol & PROTO_FAMILY_HTTP) { + /* + * https://tools.ietf.org/html/rfc7230#section-3.1.2 + * + * The reponse code is always a three-digit number in HTTP as the spec + * says. We try to allow any number here, but we cannot make + * guarantees on future behaviors since it isn't within the protocol. + */ + nc = sscanf(HEADER1, + " HTTP/%d.%d %d", + &httpversion_major, + &conn->httpversion, + &k->httpcode); + if(nc==3) { + conn->httpversion += 10 * httpversion_major; + + if(k->upgr101 == UPGR101_RECEIVED) { + /* supposedly upgraded to http2 now */ + if(conn->httpversion != 20) + infof(data, "Lying server, not serving HTTP/2\n"); + } + } + else { + /* this is the real world, not a Nirvana + NCSA 1.5.x returns this crap when asked for HTTP/1.1 + */ + nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode); + conn->httpversion = 10; + + /* If user has set option HTTP200ALIASES, + compare header line against list of aliases + */ + if(!nc) { + if(checkhttpprefix(data, k->p)) { + nc = 1; + k->httpcode = 200; + conn->httpversion = 10; + } + } + } + } + else if(conn->handler->protocol & CURLPROTO_RTSP) { + nc = sscanf(HEADER1, + " RTSP/%d.%d %3d", + &rtspversion_major, + &conn->rtspversion, + &k->httpcode); + if(nc==3) { + conn->rtspversion += 10 * rtspversion_major; + conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */ + } + else { + /* TODO: do we care about the other cases here? */ + nc = 0; + } + } + + if(nc) { + data->info.httpcode = k->httpcode; + + data->info.httpversion = conn->httpversion; + if(!data->state.httpversion || + data->state.httpversion > conn->httpversion) + /* store the lowest server version we encounter */ + data->state.httpversion = conn->httpversion; + + /* + * This code executes as part of processing the header. As a + * result, it's not totally clear how to interpret the + * response code yet as that depends on what other headers may + * be present. 401 and 407 may be errors, but may be OK + * depending on how authentication is working. Other codes + * are definitely errors, so give up here. + */ + if(data->set.http_fail_on_error && (k->httpcode >= 400) && + ((k->httpcode != 401) || !conn->bits.user_passwd) && + ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) { + + if(data->state.resume_from && + (data->set.httpreq==HTTPREQ_GET) && + (k->httpcode == 416)) { + /* "Requested Range Not Satisfiable", just proceed and + pretend this is no error */ + } + else { + /* serious error, go home! */ + print_http_error(data); + return CURLE_HTTP_RETURNED_ERROR; + } + } + + if(conn->httpversion == 10) { + /* Default action for HTTP/1.0 must be to close, unless + we get one of those fancy headers that tell us the + server keeps it open for us! */ + infof(data, "HTTP 1.0, assume close after body\n"); + connclose(conn, "HTTP/1.0 close after body"); + } + else if(conn->httpversion == 20 || + (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) { + /* Don't enable pipelining for HTTP/2 or upgraded connection. For + HTTP/2, we do not support multiplexing. In general, requests + cannot be pipelined in upgraded connection, since it is now + different protocol. */ + DEBUGF(infof(data, + "HTTP 2 or upgraded connection do not support " + "pipelining for now\n")); + } + else if(conn->httpversion >= 11 && + !conn->bits.close) { + struct connectbundle *cb_ptr; + + /* If HTTP version is >= 1.1 and connection is persistent + server supports pipelining. */ + DEBUGF(infof(data, + "HTTP 1.1 or later with persistent connection, " + "pipelining supported\n")); + /* Activate pipelining if needed */ + cb_ptr = conn->bundle; + if(cb_ptr) { + if(!Curl_pipeline_site_blacklisted(data, conn)) + cb_ptr->server_supports_pipelining = TRUE; + } + } + + switch(k->httpcode) { + case 204: + /* (quote from RFC2616, section 10.2.5): The server has + * fulfilled the request but does not need to return an + * entity-body ... The 204 response MUST NOT include a + * message-body, and thus is always terminated by the first + * empty line after the header fields. */ + /* FALLTHROUGH */ + case 304: + /* (quote from RFC2616, section 10.3.5): The 304 response + * MUST NOT contain a message-body, and thus is always + * terminated by the first empty line after the header + * fields. */ + if(data->set.timecondition) + data->info.timecond = TRUE; + k->size=0; + k->maxdownload=0; + k->ignorecl = TRUE; /* ignore Content-Length headers */ + break; + default: + /* nothing */ + break; + } + } + else { + k->header = FALSE; /* this is not a header line */ + break; + } + } + + result = Curl_convert_from_network(data, k->p, strlen(k->p)); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + + /* Check for Content-Length: header lines to get size */ + if(!k->ignorecl && !data->set.ignorecl && + checkprefix("Content-Length:", k->p)) { + curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10); + if(data->set.max_filesize && + contentlength > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + if(contentlength >= 0) { + k->size = contentlength; + k->maxdownload = k->size; + /* we set the progress download size already at this point + just to make it easier for apps/callbacks to extract this + info as soon as possible */ + Curl_pgrsSetDownloadSize(data, k->size); + } + else { + /* Negative Content-Length is really odd, and we know it + happens for example when older Apache servers send large + files */ + connclose(conn, "negative content-length"); + infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T + ", closing after transfer\n", contentlength); + } + } + /* check for Content-Type: header lines to get the MIME-type */ + else if(checkprefix("Content-Type:", k->p)) { + char *contenttype = Curl_copy_header_value(k->p); + if(!contenttype) + return CURLE_OUT_OF_MEMORY; + if(!*contenttype) + /* ignore empty data */ + free(contenttype); + else { + Curl_safefree(data->info.contenttype); + data->info.contenttype = contenttype; + } + } + else if(checkprefix("Server:", k->p)) { + char *server_name = Curl_copy_header_value(k->p); + + /* Turn off pipelining if the server version is blacklisted */ + if(conn->bundle && conn->bundle->server_supports_pipelining) { + if(Curl_pipeline_server_blacklisted(data, server_name)) + conn->bundle->server_supports_pipelining = FALSE; + } + free(server_name); + } + else if((conn->httpversion == 10) && + conn->bits.httpproxy && + Curl_compareheader(k->p, + "Proxy-Connection:", "keep-alive")) { + /* + * When a HTTP/1.0 reply comes when using a proxy, the + * 'Proxy-Connection: keep-alive' line tells us the + * connection will be kept alive for our pleasure. + * Default action for 1.0 is to close. + */ + connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */ + infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); + } + else if((conn->httpversion == 11) && + conn->bits.httpproxy && + Curl_compareheader(k->p, + "Proxy-Connection:", "close")) { + /* + * We get a HTTP/1.1 response from a proxy and it says it'll + * close down after this transfer. + */ + connclose(conn, "Proxy-Connection: asked to close after done"); + infof(data, "HTTP/1.1 proxy connection set close!\n"); + } + else if((conn->httpversion == 10) && + Curl_compareheader(k->p, "Connection:", "keep-alive")) { + /* + * A HTTP/1.0 reply with the 'Connection: keep-alive' line + * tells us the connection will be kept alive for our + * pleasure. Default action for 1.0 is to close. + * + * [RFC2068, section 19.7.1] */ + connkeep(conn, "Connection keep-alive"); + infof(data, "HTTP/1.0 connection set to keep alive!\n"); + } + else if(Curl_compareheader(k->p, "Connection:", "close")) { + /* + * [RFC 2616, section 8.1.2.1] + * "Connection: close" is HTTP/1.1 language and means that + * the connection will close when this request has been + * served. + */ + connclose(conn, "Connection: close used"); + } + else if(checkprefix("Transfer-Encoding:", k->p)) { + /* One or more encodings. We check for chunked and/or a compression + algorithm. */ + /* + * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding + * means that the server will send a series of "chunks". Each + * chunk starts with line with info (including size of the + * coming block) (terminated with CRLF), then a block of data + * with the previously mentioned size. There can be any amount + * of chunks, and a chunk-data set to zero signals the + * end-of-chunks. */ + + char *start; + + /* Find the first non-space letter */ + start = k->p + 18; + + for(;;) { + /* skip whitespaces and commas */ + while(*start && (ISSPACE(*start) || (*start == ','))) + start++; + + if(checkprefix("chunked", start)) { + k->chunk = TRUE; /* chunks coming our way */ + + /* init our chunky engine */ + Curl_httpchunk_init(conn); + + start += 7; + } + + if(k->auto_decoding) + /* TODO: we only support the first mentioned compression for now */ + break; + + if(checkprefix("identity", start)) { + k->auto_decoding = IDENTITY; + start += 8; + } + else if(checkprefix("deflate", start)) { + k->auto_decoding = DEFLATE; + start += 7; + } + else if(checkprefix("gzip", start)) { + k->auto_decoding = GZIP; + start += 4; + } + else if(checkprefix("x-gzip", start)) { + k->auto_decoding = GZIP; + start += 6; + } + else if(checkprefix("compress", start)) { + k->auto_decoding = COMPRESS; + start += 8; + } + else if(checkprefix("x-compress", start)) { + k->auto_decoding = COMPRESS; + start += 10; + } + else + /* unknown! */ + break; + + } + + } + else if(checkprefix("Content-Encoding:", k->p) && + (data->set.str[STRING_ENCODING] || + conn->httpversion == 20)) { + /* + * Process Content-Encoding. Look for the values: identity, + * gzip, deflate, compress, x-gzip and x-compress. x-gzip and + * x-compress are the same as gzip and compress. (Sec 3.5 RFC + * 2616). zlib cannot handle compress. However, errors are + * handled further down when the response body is processed + */ + char *start; + + /* Find the first non-space letter */ + start = k->p + 17; + while(*start && ISSPACE(*start)) + start++; + + /* Record the content-encoding for later use */ + if(checkprefix("identity", start)) + k->auto_decoding = IDENTITY; + else if(checkprefix("deflate", start)) + k->auto_decoding = DEFLATE; + else if(checkprefix("gzip", start) + || checkprefix("x-gzip", start)) + k->auto_decoding = GZIP; + else if(checkprefix("compress", start) + || checkprefix("x-compress", start)) + k->auto_decoding = COMPRESS; + } + else if(checkprefix("Content-Range:", k->p)) { + /* Content-Range: bytes [num]- + Content-Range: bytes: [num]- + Content-Range: [num]- + Content-Range: [asterisk]/[total] + + The second format was added since Sun's webserver + JavaWebServer/1.1.1 obviously sends the header this way! + The third added since some servers use that! + The forth means the requested range was unsatisfied. + */ + + char *ptr = k->p + 14; + + /* Move forward until first digit or asterisk */ + while(*ptr && !ISDIGIT(*ptr) && *ptr != '*') + ptr++; + + /* if it truly stopped on a digit */ + if(ISDIGIT(*ptr)) { + k->offset = curlx_strtoofft(ptr, NULL, 10); + + if(data->state.resume_from == k->offset) + /* we asked for a resume and we got it */ + k->content_range = TRUE; + } + else + data->state.resume_from = 0; /* get everything */ + } +#if !defined(CURL_DISABLE_COOKIES) + else if(data->cookies && + checkprefix("Set-Cookie:", k->p)) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, + CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_add(data, + data->cookies, TRUE, k->p+11, + /* If there is a custom-set Host: name, use it + here, or else use real peer host name. */ + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:conn->host.name, + data->state.path); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +#endif + else if(checkprefix("Last-Modified:", k->p) && + (data->set.timecondition || data->set.get_filetime) ) { + time_t secs=time(NULL); + k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), + &secs); + if(data->set.get_filetime) + data->info.filetime = (long)k->timeofdoc; + } + else if((checkprefix("WWW-Authenticate:", k->p) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", k->p) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(k->p); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(conn, proxy, auth); + + free(auth); + + if(result) + return result; + } + else if((k->httpcode >= 300 && k->httpcode < 400) && + checkprefix("Location:", k->p) && + !data->req.location) { + /* this is the URL that the server advises us to use instead */ + char *location = Curl_copy_header_value(k->p); + if(!location) + return CURLE_OUT_OF_MEMORY; + if(!*location) + /* ignore empty data */ + free(location); + else { + data->req.location = location; + + if(data->set.http_follow_location) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->req.location); /* clone */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + + /* some cases of POST and PUT etc needs to rewind the data + stream at this point */ + result = http_perhapsrewind(conn); + if(result) + return result; + } + } + } + else if(conn->handler->protocol & CURLPROTO_RTSP) { + result = Curl_rtsp_parseheader(conn, k->p); + if(result) + return result; + } + + /* + * End of header-checks. Write them to the client. + */ + + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + k->p, (size_t)k->hbuflen, conn); + + result = Curl_client_write(conn, writetype, k->p, k->hbuflen); + if(result) + return result; + + data->info.header_size += (long)k->hbuflen; + data->req.headerbytecount += (long)k->hbuflen; + + /* reset hbufp pointer && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + } + while(!*stop_reading && *k->str); /* header line within buffer */ + + /* We might have reached the end of the header part here, but + there might be a non-header part left in the end of the read + buffer. */ + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_HTTP */ diff --git a/libcurl/src/lib/http.h b/libcurl/src/lib/http.h new file mode 100644 index 0000000..08e1198 --- /dev/null +++ b/libcurl/src/lib/http.h @@ -0,0 +1,224 @@ +#ifndef HEADER_CURL_HTTP_H +#define HEADER_CURL_HTTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#ifdef USE_NGHTTP2 +#include +#endif + +extern const struct Curl_handler Curl_handler_http; + +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_https; +#endif + +/* Header specific functions */ +CURL_STATIC bool Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const char *content); /* content string to find */ + +CURL_STATIC char *Curl_checkheaders(const struct connectdata *conn, + const char *thisheader); +CURL_STATIC char *Curl_copy_header_value(const char *header); + +CURL_STATIC char *Curl_checkProxyheaders(const struct connectdata *conn, + const char *thisheader); +/* ------------------------------------------------------------------------- */ +/* + * The add_buffer series of functions are used to build one large memory chunk + * from repeated function invokes. Used so that the entire HTTP request can + * be sent in one go. + */ +struct Curl_send_buffer { + char *buffer; + size_t size_max; + size_t size_used; +}; +typedef struct Curl_send_buffer Curl_send_buffer; + +CURL_STATIC Curl_send_buffer *Curl_add_buffer_init(void); +CURL_STATIC CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...); +CURL_STATIC CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size); +CURL_STATIC CURLcode Curl_add_buffer_send(Curl_send_buffer *in, + struct connectdata *conn, + long *bytes_written, + size_t included_body_bytes, + int socketindex); + +CURL_STATIC CURLcode Curl_add_timecondition(struct SessionHandle *data, + Curl_send_buffer *buf); +CURL_STATIC CURLcode Curl_add_custom_headers(struct connectdata *conn, + bool is_connect, + Curl_send_buffer *req_buffer); + +/* protocol-specific functions set up to be called by the main engine */ +CURL_STATIC CURLcode Curl_http(struct connectdata *conn, bool *done); +CURL_STATIC CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); +CURL_STATIC CURLcode Curl_http_connect(struct connectdata *conn, bool *done); +CURL_STATIC CURLcode Curl_http_setup_conn(struct connectdata *conn); + +/* The following functions are defined in http_chunks.c */ +CURL_STATIC void Curl_httpchunk_init(struct connectdata *conn); +CURL_STATIC CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, + ssize_t length, ssize_t *wrote); + +/* These functions are in http.c */ +CURL_STATIC void Curl_http_auth_stage(struct SessionHandle *data, int stage); +CURL_STATIC CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, + const char *auth); +CURL_STATIC CURLcode Curl_http_auth_act(struct connectdata *conn); +CURL_STATIC CURLcode Curl_http_perhapsrewind(struct connectdata *conn); + +/* If only the PICKNONE bit is set, there has been a round-trip and we + selected to use no auth at all. Ie, we actively select no auth, as opposed + to not having one selected. The other CURLAUTH_* defines are present in the + public curl/curl.h header. */ +#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */ + +/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST + data get included in the initial data chunk sent to the server. If the + data is larger than this, it will automatically get split up in multiple + system calls. + + This value used to be fairly big (100K), but we must take into account that + if the server rejects the POST due for authentication reasons, this data + will always be uncondtionally sent and thus it may not be larger than can + always be afforded to send twice. + + It must not be greater than 64K to work on VMS. +*/ +#ifndef MAX_INITIAL_POST_SIZE +#define MAX_INITIAL_POST_SIZE (64*1024) +#endif + +#ifndef TINY_INITIAL_POST_SIZE +#define TINY_INITIAL_POST_SIZE 1024 +#endif + +#endif /* CURL_DISABLE_HTTP */ + +/**************************************************************************** + * HTTP unique setup + ***************************************************************************/ +struct HTTP { + struct FormData *sendit; + curl_off_t postsize; /* off_t to handle large file sizes */ + const char *postdata; + + const char *p_pragma; /* Pragma: string */ + const char *p_accept; /* Accept: string */ + curl_off_t readbytecount; + curl_off_t writebytecount; + + /* For FORM posting */ + struct Form form; + + struct back { + curl_read_callback fread_func; /* backup storage for fread pointer */ + void *fread_in; /* backup storage for fread_in pointer */ + const char *postdata; + curl_off_t postsize; + } backup; + + enum { + HTTPSEND_NADA, /* init */ + HTTPSEND_REQUEST, /* sending a request */ + HTTPSEND_BODY, /* sending body */ + HTTPSEND_LAST /* never use this */ + } sending; + + void *send_buffer; /* used if the request couldn't be sent in one chunk, + points to an allocated send_buffer struct */ +}; + +typedef int (*sending)(void); /* Curl_send */ +typedef int (*recving)(void); /* Curl_recv */ + +struct http_conn { +#ifdef USE_NGHTTP2 +#define H2_BINSETTINGS_LEN 80 + nghttp2_session *h2; + uint8_t binsettings[H2_BINSETTINGS_LEN]; + size_t binlen; /* length of the binsettings data */ + char *mem; /* points to a buffer in memory to store */ + size_t len; /* size of the buffer 'mem' points to */ + bool bodystarted; + sending send_underlying; /* underlying send Curl_send callback */ + recving recv_underlying; /* underlying recv Curl_recv callback */ + bool closed; /* TRUE on HTTP2 stream close */ + uint32_t error_code; /* HTTP/2 error code */ + 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 + fed into upper layer */ + int32_t stream_id; /* stream we are interested in */ + const uint8_t *data; /* pointer to data chunk, received in + on_data_chunk */ + size_t datalen; /* the number of bytes left in data */ + char *inbuf; /* buffer to receive data from underlying socket */ + /* We need separate buffer for transmission and reception because we + may call nghttp2_session_send() after the + nghttp2_session_mem_recv() but mem buffer is still not full. In + this case, we wrongly sends the content of mem buffer if we share + them for both cases. */ + 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_left; /* number of bytes left to upload */ + int status_code; /* HTTP status code */ +#else + int unused; /* prevent a compiler warning */ +#endif +}; + +CURL_STATIC CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, + struct connectdata *conn, + ssize_t *nread, + bool *stop_reading); + +/** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication + * method. conn->data->state.authdone is set to TRUE when authentication is + * done. + * + * @param conn all information about the current connection + * @param request pointer to the request keyword + * @param path pointer to the requested path + * @param proxytunnel boolean if this is the request setting up a "proxy + * tunnel" + * + * @returns CURLcode + */ +CURL_STATIC CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel); /* TRUE if this is the request setting + up the proxy tunnel */ + +#endif /* HEADER_CURL_HTTP_H */ + diff --git a/libcurl/src/lib/http2.c b/libcurl/src/lib/http2.c new file mode 100644 index 0000000..33fc34d --- /dev/null +++ b/libcurl/src/lib/http2.c @@ -0,0 +1,1077 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NGHTTP2 +#include "curl_printf.h" +#include +#include "urldata.h" +#include "http2.h" +#include "http.h" +#include "sendf.h" +#include "curl_base64.h" +#include "rawstr.h" +#include "multiif.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if (NGHTTP2_VERSION_NUM < 0x000600) +#error too old nghttp2 version, upgrade! +#endif + +static int http2_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to + numsocks + number of + sockets */ + int numsocks) +{ + const struct http_conn *httpc = &conn->proto.httpc; + int bitmap = GETSOCK_BLANK; + (void)numsocks; + + /* TODO We should check underlying socket state if it is SSL socket + because of renegotiation. */ + sock[0] = conn->sock[FIRSTSOCKET]; + + if(nghttp2_session_want_read(httpc->h2)) + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + + if(nghttp2_session_want_write(httpc->h2)) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +} + +static int http2_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ + return http2_perform_getsock(conn, sock, numsocks); +} + +static CURLcode http2_disconnect(struct connectdata *conn, + bool dead_connection) +{ + struct http_conn *httpc = &conn->proto.httpc; + (void)dead_connection; + + DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); + + nghttp2_session_del(httpc->h2); + + Curl_safefree(httpc->header_recvbuf->buffer); + Curl_safefree(httpc->header_recvbuf); + + Curl_safefree(httpc->inbuf); + + DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); + + return CURLE_OK; +} + +/* + * HTTP2 handler interface. This isn't added to the general list of protocols + * but will be used at run-time when the protocol is dynamically switched from + * HTTP to HTTP2. + */ +const struct Curl_handler Curl_handler_http2 = { + "HTTP2", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + http2_getsock, /* proto_getsock */ + http2_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + http2_perform_getsock, /* perform_getsock */ + http2_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +const struct Curl_handler Curl_handler_http2_ssl = { + "HTTP2", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + http2_getsock, /* proto_getsock */ + http2_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + http2_perform_getsock, /* perform_getsock */ + http2_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTPS, /* protocol */ + PROTOPT_SSL /* flags */ +}; + +/* + * Store nghttp2 version info in this buffer, Prefix with a space. Return + * total length written. + */ +CURL_STATIC int Curl_http2_ver(char *p, size_t len) +{ + nghttp2_info *h2 = nghttp2_version(0); + return snprintf(p, len, " nghttp2/%s", h2->version_str); +} + +/* + * The implementation of nghttp2_send_callback type. Here we write |data| with + * size |length| to the network and return the number of bytes actually + * written. See the documentation of nghttp2_send_callback for the details. + */ +static ssize_t send_callback(nghttp2_session *h2, + const uint8_t *data, size_t length, int flags, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *httpc = &conn->proto.httpc; + ssize_t written; + CURLcode result = CURLE_OK; + + (void)h2; + (void)flags; + + written = ((Curl_send*)httpc->send_underlying)(conn, FIRSTSOCKET, + data, length, &result); + + if(result == CURLE_AGAIN) { + return NGHTTP2_ERR_WOULDBLOCK; + } + + if(written == -1) { + failf(conn->data, "Failed sending HTTP2 data"); + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + if(!written) + return NGHTTP2_ERR_WOULDBLOCK; + + return written; +} + +static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; + int rv; + size_t left, ncopy; + + (void)session; + (void)frame; + DEBUGF(infof(conn->data, "on_frame_recv() was called with header %x\n", + 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: + if(frame->headers.cat == NGHTTP2_HCAT_REQUEST) + break; + + 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); + + left = c->header_recvbuf->size_used - c->nread_header_recvbuf; + ncopy = c->len < left ? c->len : left; + + memcpy(c->mem, c->header_recvbuf->buffer + c->nread_header_recvbuf, ncopy); + c->nread_header_recvbuf += ncopy; + + c->mem += ncopy; + c->len -= ncopy; + break; + case NGHTTP2_PUSH_PROMISE: + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_CANCEL); + if(nghttp2_is_fatal(rv)) { + return rv; + } + break; + } + return 0; +} + +static int on_invalid_frame_recv(nghttp2_session *session, + const nghttp2_frame *frame, + uint32_t error_code, void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + DEBUGF(infof(conn->data, + "on_invalid_frame_recv() was called, error_code = %d\n", + error_code)); + return 0; +} + +static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const uint8_t *data, size_t len, void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; + size_t nread; + (void)session; + (void)flags; + (void)data; + DEBUGF(infof(conn->data, "on_data_chunk_recv() " + "len = %u, stream = %x\n", len, stream_id)); + + if(stream_id != c->stream_id) { + return 0; + } + + nread = c->len < len ? c->len : len; + memcpy(c->mem, data, nread); + + c->mem += nread; + c->len -= nread; + + DEBUGF(infof(conn->data, "%zu data written\n", nread)); + + if(nread < len) { + c->data = data + nread; + c->datalen = len - nread; + return NGHTTP2_ERR_PAUSE; + } + return 0; +} + +static int before_frame_send(nghttp2_session *session, + const nghttp2_frame *frame, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + DEBUGF(infof(conn->data, "before_frame_send() was called\n")); + return 0; +} +static int on_frame_send(nghttp2_session *session, + const nghttp2_frame *frame, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + DEBUGF(infof(conn->data, "on_frame_send() was called\n")); + return 0; +} +static int on_frame_not_send(nghttp2_session *session, + const nghttp2_frame *frame, + int lib_error_code, void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + DEBUGF(infof(conn->data, + "on_frame_not_send() was called, lib_error_code = %d\n", + lib_error_code)); + return 0; +} +static int on_stream_close(nghttp2_session *session, int32_t stream_id, + uint32_t error_code, void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; + (void)session; + (void)stream_id; + DEBUGF(infof(conn->data, "on_stream_close() was called, error_code = %d\n", + error_code)); + + if(stream_id != c->stream_id) { + return 0; + } + + c->error_code = error_code; + c->closed = TRUE; + + return 0; +} + +static int on_begin_headers(nghttp2_session *session, + const nghttp2_frame *frame, void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)frame; + DEBUGF(infof(conn->data, "on_begin_headers() was called\n")); + 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"; + +/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */ +static int on_header(nghttp2_session *session, const nghttp2_frame *frame, + const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, + uint8_t flags, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; + int rv; + int goodname; + int goodheader; + + (void)session; + (void)frame; + (void)flags; + + /* Ignore PUSH_PROMISE for now */ + if(frame->hd.type != NGHTTP2_HEADERS) { + return 0; + } + + if(frame->hd.stream_id != c->stream_id) { + 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 && + memcmp(STATUS, name, namelen) == 0) { + + /* :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; + } + 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 */ + Curl_add_buffer(c->header_recvbuf, name, namelen); + Curl_add_buffer(c->header_recvbuf, ":", 1); + Curl_add_buffer(c->header_recvbuf, value, valuelen); + Curl_add_buffer(c->header_recvbuf, "\r\n", 2); + + DEBUGF(infof(conn->data, "h2 header: %.*s: %.*s\n", + namelen, name, valuelen, value)); + } + + return 0; /* 0 is successful */ +} + +static ssize_t data_source_read_callback(nghttp2_session *session, + int32_t stream_id, + uint8_t *buf, size_t length, + uint32_t *data_flags, + nghttp2_data_source *source, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; + size_t nread; + (void)session; + (void)stream_id; + (void)source; + + nread = c->upload_len < length ? c->upload_len : length; + if(nread > 0) { + memcpy(buf, c->upload_mem, nread); + c->upload_mem += nread; + c->upload_len -= nread; + c->upload_left -= nread; + } + + if(c->upload_left == 0) + *data_flags = 1; + else if(nread == 0) + return NGHTTP2_ERR_DEFERRED; + + return nread; +} + +/* + * The HTTP2 settings we send in the Upgrade request + */ +static nghttp2_settings_entry settings[] = { + { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }, + { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE }, +}; + +#define H2_BUFSIZE 4096 + +/* + * Initialize nghttp2 for a Curl connection + */ +CURL_STATIC CURLcode Curl_http2_init(struct connectdata *conn) +{ + if(!conn->proto.httpc.h2) { + int rc; + nghttp2_session_callbacks *callbacks; + + conn->proto.httpc.inbuf = malloc(H2_BUFSIZE); + if(conn->proto.httpc.inbuf == NULL) + 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 */ + rc = nghttp2_session_client_new(&conn->proto.httpc.h2, + callbacks, conn); + + nghttp2_session_callbacks_del(callbacks); + + if(rc) { + failf(conn->data, "Couldn't initialize nghttp2!"); + return CURLE_OUT_OF_MEMORY; /* most likely at least */ + } + } + return CURLE_OK; +} + +/* + * Send a request using http2 + */ +CURL_STATIC CURLcode Curl_http2_send_request(struct connectdata *conn) +{ + (void)conn; + return CURLE_OK; +} + +/* + * Append headers to ask for a HTTP1.1 to HTTP2 upgrade. + */ +CURL_STATIC CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, + struct connectdata *conn) +{ + CURLcode result; + ssize_t binlen; + char *base64; + size_t blen; + struct SingleRequest *k = &conn->data->req; + uint8_t *binsettings = conn->proto.httpc.binsettings; + + /* As long as we have a fixed set of settings, we don't have to dynamically + * figure out the base64 strings since it'll always be the same. However, + * the settings will likely not be fixed every time in the future. + */ + + /* this returns number of bytes it wrote */ + binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, + settings, + sizeof(settings)/sizeof(settings[0])); + if(!binlen) { + failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); + return CURLE_FAILED_INIT; + } + conn->proto.httpc.binlen = binlen; + + result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen, + &base64, &blen); + if(result) + return result; + + result = Curl_add_bufferf(req, + "Connection: Upgrade, HTTP2-Settings\r\n" + "Upgrade: %s\r\n" + "HTTP2-Settings: %s\r\n", + NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64); + free(base64); + + k->upgr101 = UPGR101_REQUESTED; + + return result; +} + +/* + * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return + * a regular CURLcode value. + */ +static ssize_t http2_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + CURLcode result = CURLE_OK; + ssize_t rv; + ssize_t nread; + struct http_conn *httpc = &conn->proto.httpc; + + (void)sockindex; /* we always do HTTP2 on sockindex 0 */ + + if(httpc->closed) { + /* Reset to FALSE to prevent infinite loop in readwrite_data + function. */ + httpc->closed = FALSE; + return 0; + } + + /* Nullify here because we call nghttp2_session_send() and they + might refer to the old buffer. */ + httpc->upload_mem = NULL; + httpc->upload_len = 0; + + if(httpc->bodystarted && + httpc->nread_header_recvbuf < httpc->header_recvbuf->size_used) { + size_t left = + httpc->header_recvbuf->size_used - httpc->nread_header_recvbuf; + size_t ncopy = len < left ? len : left; + memcpy(mem, httpc->header_recvbuf->buffer + httpc->nread_header_recvbuf, + ncopy); + httpc->nread_header_recvbuf += ncopy; + return ncopy; + } + + if(httpc->data) { + nread = len < httpc->datalen ? len : httpc->datalen; + memcpy(mem, httpc->data, nread); + + httpc->data += nread; + httpc->datalen -= nread; + + infof(conn->data, "%zu data bytes written\n", nread); + if(httpc->datalen == 0) { + httpc->data = NULL; + httpc->datalen = 0; + } + return nread; + } + + conn->proto.httpc.mem = mem; + conn->proto.httpc.len = len; + + infof(conn->data, "http2_recv: %d bytes buffer\n", + conn->proto.httpc.len); + + nread = ((Curl_recv*)httpc->recv_underlying)(conn, FIRSTSOCKET, + httpc->inbuf, H2_BUFSIZE, + &result); + if(result == CURLE_AGAIN) { + *err = result; + return -1; + } + + if(nread == -1) { + failf(conn->data, "Failed receiving HTTP2 data"); + *err = result; + return 0; + } + + if(nread == 0) { + failf(conn->data, "Unexpected EOF"); + *err = CURLE_RECV_ERROR; + return -1; + } + + DEBUGF(infof(conn->data, "nread=%zd\n", nread)); + + rv = nghttp2_session_mem_recv(httpc->h2, + (const uint8_t *)httpc->inbuf, nread); + + if(nghttp2_is_fatal((int)rv)) { + failf(conn->data, "nghttp2_session_mem_recv() returned %d:%s\n", + rv, nghttp2_strerror((int)rv)); + *err = CURLE_RECV_ERROR; + return 0; + } + DEBUGF(infof(conn->data, "nghttp2_session_mem_recv() returns %zd\n", rv)); + /* Always send pending frames in nghttp2 session, because + nghttp2_session_mem_recv() may queue new frame */ + rv = nghttp2_session_send(httpc->h2); + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return 0; + } + if(len != httpc->len) { + return len - conn->proto.httpc.len; + } + /* If stream is closed, return 0 to signal the http routine to close + the connection */ + if(httpc->closed) { + /* Reset to FALSE to prevent infinite loop in readwrite_data + function. */ + httpc->closed = FALSE; + if(httpc->error_code != NGHTTP2_NO_ERROR) { + failf(conn->data, + "HTTP/2 stream = %x was not closed cleanly: error_code = %d", + httpc->stream_id, httpc->error_code); + *err = CURLE_HTTP2; + return -1; + } + return 0; + } + *err = CURLE_AGAIN; + 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 */ +static ssize_t http2_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + /* + * BIG TODO: Currently, we send request in this function, but this + * function is also used to send request body. It would be nice to + * add dedicated function for request. + */ + int rv; + struct http_conn *httpc = &conn->proto.httpc; + nghttp2_nv *nva; + size_t nheader; + size_t i; + size_t authority_idx; + char *hdbuf = (char*)mem; + char *end; + nghttp2_data_provider data_prd; + int32_t stream_id; + + (void)sockindex; + + DEBUGF(infof(conn->data, "http2_send len=%zu\n", len)); + + if(httpc->stream_id != -1) { + /* If stream_id != -1, we have dispatched request HEADERS, and now + are going to send or sending request body in DATA frame */ + httpc->upload_mem = mem; + httpc->upload_len = len; + nghttp2_session_resume_data(httpc->h2, httpc->stream_id); + rv = nghttp2_session_send(httpc->h2); + if(nghttp2_is_fatal(rv)) { + *err = CURLE_SEND_ERROR; + return -1; + } + return len - httpc->upload_len; + } + + /* Calculate number of headers contained in [mem, mem + len) */ + /* Here, we assume the curl http code generate *correct* HTTP header + field block */ + nheader = 0; + for(i = 0; i < len; ++i) { + if(hdbuf[i] == 0x0a) { + ++nheader; + } + } + /* We counted additional 2 \n in the first and last line. We need 3 + new headers: :method, :path and :scheme. Therefore we need one + more space. */ + nheader += 1; + nva = malloc(sizeof(nghttp2_nv) * nheader); + if(nva == NULL) { + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + /* Extract :method, :path from request line */ + end = strchr(hdbuf, ' '); + nva[0].name = (unsigned char *)":method"; + nva[0].namelen = (uint16_t)strlen((char *)nva[0].name); + nva[0].value = (unsigned char *)hdbuf; + nva[0].valuelen = (uint16_t)(end - hdbuf); + nva[0].flags = NGHTTP2_NV_FLAG_NONE; + + hdbuf = end + 1; + + end = strchr(hdbuf, ' '); + nva[1].name = (unsigned char *)":path"; + nva[1].namelen = (uint16_t)strlen((char *)nva[1].name); + nva[1].value = (unsigned char *)hdbuf; + nva[1].valuelen = (uint16_t)(end - hdbuf); + nva[1].flags = NGHTTP2_NV_FLAG_NONE; + + nva[2].name = (unsigned char *)":scheme"; + nva[2].namelen = (uint16_t)strlen((char *)nva[2].name); + if(conn->handler->flags & PROTOPT_SSL) + nva[2].value = (unsigned char *)"https"; + else + nva[2].value = (unsigned char *)"http"; + nva[2].valuelen = (uint16_t)strlen((char *)nva[2].value); + nva[2].flags = NGHTTP2_NV_FLAG_NONE; + + hdbuf = strchr(hdbuf, 0x0a); + ++hdbuf; + + authority_idx = 0; + + for(i = 3; i < nheader; ++i) { + end = strchr(hdbuf, ':'); + assert(end); + if(end - hdbuf == 4 && Curl_raw_nequal("host", hdbuf, 4)) { + authority_idx = i; + nva[i].name = (unsigned char *)":authority"; + nva[i].namelen = (uint16_t)strlen((char *)nva[i].name); + } + else { + nva[i].name = (unsigned char *)hdbuf; + nva[i].namelen = (uint16_t)(end - hdbuf); + } + hdbuf = end + 1; + for(; *hdbuf == ' '; ++hdbuf); + end = strchr(hdbuf, 0x0d); + assert(end); + nva[i].value = (unsigned char *)hdbuf; + nva[i].valuelen = (uint16_t)(end - hdbuf); + nva[i].flags = NGHTTP2_NV_FLAG_NONE; + + hdbuf = end + 2; + /* Inspect Content-Length header field and retrieve the request + entity length so that we can set END_STREAM to the last DATA + frame. */ + if(nva[i].namelen == 14 && + Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) { + size_t j; + for(j = 0; j < nva[i].valuelen; ++j) { + httpc->upload_left *= 10; + httpc->upload_left += nva[i].value[j] - '0'; + } + DEBUGF(infof(conn->data, + "request content-length=%zu\n", httpc->upload_left)); + } + } + + /* :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) { + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + case HTTPREQ_PUT: + data_prd.read_callback = data_source_read_callback; + data_prd.source.ptr = NULL; + stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader, + &data_prd, NULL); + break; + default: + stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader, + NULL, NULL); + } + + free(nva); + + if(stream_id < 0) { + *err = CURLE_SEND_ERROR; + return -1; + } + + httpc->stream_id = stream_id; + + rv = nghttp2_session_send(httpc->h2); + + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return -1; + } + + if(httpc->stream_id != -1) { + /* If whole HEADERS frame was sent off to the underlying socket, + the nghttp2 library calls data_source_read_callback. But only + it found that no data available, so it deferred the DATA + transmission. Which means that nghttp2_session_want_write() + returns 0 on http2_perform_getsock(), which results that no + writable socket check is performed. To workaround this, we + issue nghttp2_session_resume_data() here to bring back DATA + transmission from deferred state. */ + nghttp2_session_resume_data(httpc->h2, httpc->stream_id); + } + + return len; +} + +CURL_STATIC CURLcode Curl_http2_setup(struct connectdata *conn) +{ + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + if(conn->handler->flags & PROTOPT_SSL) + conn->handler = &Curl_handler_http2_ssl; + else + conn->handler = &Curl_handler_http2; + + result = Curl_http2_init(conn); + if(result) + return result; + + infof(conn->data, "Using HTTP2\n"); + httpc->bodystarted = FALSE; + httpc->error_code = NGHTTP2_NO_ERROR; + httpc->closed = FALSE; + httpc->header_recvbuf = Curl_add_buffer_init(); + httpc->nread_header_recvbuf = 0; + httpc->data = NULL; + httpc->datalen = 0; + httpc->upload_left = 0; + httpc->upload_mem = NULL; + httpc->upload_len = 0; + httpc->stream_id = -1; + httpc->status_code = -1; + + conn->httpversion = 20; + + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_http2_switched(struct connectdata *conn, + const char *mem, size_t nread) +{ + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + int rv; + struct SessionHandle *data = conn->data; + + result = Curl_http2_setup(conn); + if(result) + return result; + + httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET]; + httpc->send_underlying = (sending)conn->send[FIRSTSOCKET]; + conn->recv[FIRSTSOCKET] = http2_recv; + conn->send[FIRSTSOCKET] = http2_send; + + rv = (int) ((Curl_send*)httpc->send_underlying) + (conn, FIRSTSOCKET, + NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN, + &result); + if(result) + /* TODO: This may get CURLE_AGAIN */ + return result; + + if(rv != 24) { + failf(data, "Only sent partial HTTP2 packet"); + return CURLE_SEND_ERROR; + } + + if(conn->data->req.upgr101 == UPGR101_RECEIVED) { + /* stream 1 is opened implicitly on upgrade */ + httpc->stream_id = 1; + /* queue SETTINGS frame (again) */ + rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings, + httpc->binlen, NULL); + if(rv != 0) { + failf(data, "nghttp2_session_upgrade() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + } + else { + /* stream ID is unknown at this point */ + httpc->stream_id = -1; + rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0); + if(rv != 0) { + failf(data, "nghttp2_submit_settings() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + } + + rv = (int)nghttp2_session_mem_recv(httpc->h2, (const uint8_t*)mem, nread); + + if(rv != (int)nread) { + failf(data, "nghttp2_session_mem_recv() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + + /* Try to send some frames since we may read SETTINGS already. */ + rv = nghttp2_session_send(httpc->h2); + + if(rv != 0) { + failf(data, "nghttp2_session_send() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + + return CURLE_OK; +} + +#endif diff --git a/libcurl/src/lib/http2.h b/libcurl/src/lib/http2.h new file mode 100644 index 0000000..fc801d3 --- /dev/null +++ b/libcurl/src/lib/http2.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_HTTP2_H +#define HEADER_CURL_HTTP2_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NGHTTP2 +#include "http.h" +/* + * Store nghttp2 version info in this buffer, Prefix with a space. Return + * total length written. + */ +CURL_STATIC int Curl_http2_ver(char *p, size_t len); + +CURL_STATIC CURLcode Curl_http2_init(struct connectdata *conn); +CURL_STATIC CURLcode Curl_http2_send_request(struct connectdata *conn); +CURL_STATIC CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, + struct connectdata *conn); +CURL_STATIC CURLcode Curl_http2_setup(struct connectdata *conn); +CURL_STATIC CURLcode Curl_http2_switched(struct connectdata *conn, + const char *data, size_t nread); +#else /* USE_NGHTTP2 */ +#define Curl_http2_init(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_setup(x) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL +#endif + +#endif /* HEADER_CURL_HTTP2_H */ + diff --git a/libcurl/src/lib/http_chunks.c b/libcurl/src/lib/http_chunks.c new file mode 100644 index 0000000..e37dfd8 --- /dev/null +++ b/libcurl/src/lib/http_chunks.c @@ -0,0 +1,382 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#include "urldata.h" /* it includes http_chunks.h */ +#include "sendf.h" /* for the client write stuff */ + +#include "content_encoding.h" +#include "http.h" +#include "non-ascii.h" /* for Curl_convert_to_network prototype */ +#include "strtoofft.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Chunk format (simplified): + * + * [ chunk extension ] CRLF + * CRLF + * + * Highlights from RFC2616 section 3.6 say: + + The chunked encoding modifies the body of a message in order to + transfer it as a series of chunks, each with its own size indicator, + followed by an OPTIONAL trailer containing entity-header fields. This + allows dynamically produced content to be transferred along with the + information necessary for the recipient to verify that it has + received the full message. + + Chunked-Body = *chunk + last-chunk + trailer + CRLF + + chunk = chunk-size [ chunk-extension ] CRLF + chunk-data CRLF + chunk-size = 1*HEX + last-chunk = 1*("0") [ chunk-extension ] CRLF + + chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) + chunk-ext-name = token + chunk-ext-val = token | quoted-string + chunk-data = chunk-size(OCTET) + trailer = *(entity-header CRLF) + + The chunk-size field is a string of hex digits indicating the size of + the chunk. The chunked encoding is ended by any chunk whose size is + zero, followed by the trailer, which is terminated by an empty line. + + */ + +/* Check for an ASCII hex digit. + We avoid the use of isxdigit to accommodate non-ASCII hosts. */ +static bool Curl_isxdigit(char digit) +{ + return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */ + || (digit >= 0x41 && digit <= 0x46) /* A-F */ + || (digit >= 0x61 && digit <= 0x66) /* a-f */ ) ? TRUE : FALSE; +} + +CURL_STATIC void Curl_httpchunk_init(struct connectdata *conn) +{ + struct Curl_chunker *chunk = &conn->chunk; + chunk->hexindex=0; /* start at 0 */ + chunk->dataleft=0; /* no data left yet! */ + chunk->state = CHUNK_HEX; /* we get hex first! */ +} + +/* + * chunk_read() returns a OK for normal operations, or a positive return code + * for errors. STOP means this sequence of chunks is complete. The 'wrote' + * argument is set to tell the caller how many bytes we actually passed to the + * client (for byte-counting and whatever). + * + * The states and the state-machine is further explained in the header file. + * + * This function always uses ASCII hex values to accommodate non-ASCII hosts. + * For example, 0x0d and 0x0a are used instead of '\r' and '\n'. + */ +CURL_STATIC CHUNKcode Curl_httpchunk_read(struct connectdata *conn, + char *datap, + ssize_t datalen, + ssize_t *wrotep) +{ + CURLcode result=CURLE_OK; + struct SessionHandle *data = conn->data; + struct Curl_chunker *ch = &conn->chunk; + struct SingleRequest *k = &data->req; + size_t piece; + curl_off_t length = (curl_off_t)datalen; + size_t *wrote = (size_t *)wrotep; + + *wrote = 0; /* nothing's written yet */ + + /* the original data is written to the client, but we go on with the + chunk read process, to properly calculate the content length*/ + if(data->set.http_te_skip && !k->ignorebody) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen); + if(result) + return CHUNKE_WRITE_ERROR; + } + + while(length) { + switch(ch->state) { + case CHUNK_HEX: + if(Curl_isxdigit(*datap)) { + if(ch->hexindex < MAXNUM_SIZE) { + ch->hexbuffer[ch->hexindex] = *datap; + datap++; + length--; + ch->hexindex++; + } + else { + return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */ + } + } + else { + char *endptr; + if(0 == ch->hexindex) + /* This is illegal data, we received junk where we expected + a hexadecimal digit. */ + return CHUNKE_ILLEGAL_HEX; + + /* length and datap are unmodified */ + ch->hexbuffer[ch->hexindex]=0; + + /* convert to host encoding before calling strtoul */ + result = Curl_convert_from_network(conn->data, ch->hexbuffer, + ch->hexindex); + if(result) { + /* Curl_convert_from_network calls failf if unsuccessful */ + /* Treat it as a bad hex character */ + return CHUNKE_ILLEGAL_HEX; + } + + ch->datasize=curlx_strtoofft(ch->hexbuffer, &endptr, 16); + if((ch->datasize == CURL_OFF_T_MAX) && (errno == ERANGE)) + /* overflow is an error */ + return CHUNKE_ILLEGAL_HEX; + ch->state = CHUNK_LF; /* now wait for the CRLF */ + } + break; + + case CHUNK_LF: + /* waiting for the LF after a chunk size */ + if(*datap == 0x0a) { + /* we're now expecting data to come, unless size was zero! */ + if(0 == ch->datasize) { + ch->state = CHUNK_TRAILER; /* now check for trailers */ + conn->trlPos=0; + } + else + ch->state = CHUNK_DATA; + } + + datap++; + length--; + break; + + case CHUNK_DATA: + /* We expect 'datasize' of data. We have 'length' right now, it can be + more or less than 'datasize'. Get the smallest piece. + */ + piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize); + + /* Write the data portion available */ +#ifdef HAVE_LIBZ + switch (conn->data->set.http_ce_skip? + IDENTITY : data->req.auto_decoding) { + case IDENTITY: +#endif + if(!k->ignorebody) { + if(!data->set.http_te_skip) + result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, + piece); + else + result = CURLE_OK; + } +#ifdef HAVE_LIBZ + break; + + case DEFLATE: + /* update data->req.keep.str to point to the chunk data. */ + data->req.str = datap; + result = Curl_unencode_deflate_write(conn, &data->req, + (ssize_t)piece); + break; + + case GZIP: + /* update data->req.keep.str to point to the chunk data. */ + data->req.str = datap; + result = Curl_unencode_gzip_write(conn, &data->req, + (ssize_t)piece); + break; + + case COMPRESS: + default: + failf (conn->data, + "Unrecognized content encoding type. " + "libcurl understands `identity', `deflate' and `gzip' " + "content encodings."); + return CHUNKE_BAD_ENCODING; + } +#endif + + if(result) + return CHUNKE_WRITE_ERROR; + + *wrote += piece; + + ch->datasize -= piece; /* decrease amount left to expect */ + datap += piece; /* move read pointer forward */ + length -= piece; /* decrease space left in this round */ + + if(0 == ch->datasize) + /* end of data this round, we now expect a trailing CRLF */ + ch->state = CHUNK_POSTLF; + break; + + case CHUNK_POSTLF: + if(*datap == 0x0a) { + /* The last one before we go back to hex state and start all over. */ + Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */ + } + else if(*datap != 0x0d) + return CHUNKE_BAD_CHUNK; + datap++; + length--; + break; + + case CHUNK_TRAILER: + if((*datap == 0x0d) || (*datap == 0x0a)) { + /* this is the end of a trailer, but if the trailer was zero bytes + there was no trailer and we move on */ + + if(conn->trlPos) { + /* we allocate trailer with 3 bytes extra room to fit this */ + conn->trailer[conn->trlPos++]=0x0d; + conn->trailer[conn->trlPos++]=0x0a; + conn->trailer[conn->trlPos]=0; + + /* Convert to host encoding before calling Curl_client_write */ + result = Curl_convert_from_network(conn->data, conn->trailer, + conn->trlPos); + if(result) + /* Curl_convert_from_network calls failf if unsuccessful */ + /* Treat it as a bad chunk */ + return CHUNKE_BAD_CHUNK; + + if(!data->set.http_te_skip) { + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + conn->trailer, conn->trlPos); + if(result) + return CHUNKE_WRITE_ERROR; + } + conn->trlPos=0; + ch->state = CHUNK_TRAILER_CR; + if(*datap == 0x0a) + /* already on the LF */ + break; + } + else { + /* no trailer, we're on the final CRLF pair */ + ch->state = CHUNK_TRAILER_POSTCR; + break; /* don't advance the pointer */ + } + } + else { + /* conn->trailer is assumed to be freed in url.c on a + connection basis */ + if(conn->trlPos >= conn->trlMax) { + /* we always allocate three extra bytes, just because when the full + header has been received we append CRLF\0 */ + char *ptr; + if(conn->trlMax) { + conn->trlMax *= 2; + ptr = realloc(conn->trailer, conn->trlMax + 3); + } + else { + conn->trlMax=128; + ptr = malloc(conn->trlMax + 3); + } + if(!ptr) + return CHUNKE_OUT_OF_MEMORY; + conn->trailer = ptr; + } + conn->trailer[conn->trlPos++]=*datap; + } + datap++; + length--; + break; + + case CHUNK_TRAILER_CR: + if(*datap == 0x0a) { + ch->state = CHUNK_TRAILER_POSTCR; + datap++; + length--; + } + else + return CHUNKE_BAD_CHUNK; + break; + + case CHUNK_TRAILER_POSTCR: + /* We enter this state when a CR should arrive so we expect to + have to first pass a CR before we wait for LF */ + if((*datap != 0x0d) && (*datap != 0x0a)) { + /* not a CR then it must be another header in the trailer */ + ch->state = CHUNK_TRAILER; + break; + } + if(*datap == 0x0d) { + /* skip if CR */ + datap++; + length--; + } + /* now wait for the final LF */ + ch->state = CHUNK_STOP; + break; + + case CHUNK_STOP: + if(*datap == 0x0a) { + length--; + + /* Record the length of any data left in the end of the buffer + even if there's no more chunks to read */ + ch->dataleft = curlx_sotouz(length); + + return CHUNKE_STOP; /* return stop */ + } + else + return CHUNKE_BAD_CHUNK; + } + } + return CHUNKE_OK; +} + +CURL_STATIC const char *Curl_chunked_strerror(CHUNKcode code) +{ + switch (code) { + default: + return "OK"; + case CHUNKE_TOO_LONG_HEX: + return "Too long hexadecimal number"; + case CHUNKE_ILLEGAL_HEX: + return "Illegal or missing hexadecimal sequence"; + case CHUNKE_BAD_CHUNK: + return "Malformed encoding found"; + case CHUNKE_WRITE_ERROR: + return "Write error"; + case CHUNKE_BAD_ENCODING: + return "Bad content-encoding found"; + case CHUNKE_OUT_OF_MEMORY: + return "Out of memory"; + } +} + +#endif /* CURL_DISABLE_HTTP */ diff --git a/libcurl/src/lib/http_chunks.h b/libcurl/src/lib/http_chunks.h new file mode 100644 index 0000000..2389eaa --- /dev/null +++ b/libcurl/src/lib/http_chunks.h @@ -0,0 +1,91 @@ +#ifndef HEADER_CURL_HTTP_CHUNKS_H +#define HEADER_CURL_HTTP_CHUNKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + * The longest possible hexadecimal number we support in a chunked transfer. + * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul() + * to convert it, we "only" support 2^32 bytes chunk data. + */ +#define MAXNUM_SIZE 16 + +typedef enum { + /* await and buffer all hexadecimal digits until we get one that isn't a + hexadecimal digit. When done, we go CHUNK_LF */ + CHUNK_HEX, + + /* wait for LF, ignore all else */ + CHUNK_LF, + + /* We eat the amount of data specified. When done, we move on to the + POST_CR state. */ + CHUNK_DATA, + + /* POSTLF should get a CR and then a LF and nothing else, then move back to + HEX as the CRLF combination marks the end of a chunk. A missing CR is no + big deal. */ + CHUNK_POSTLF, + + /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft' + field in the struct that will tell how many bytes that were not passed to + the client in the end of the last buffer! */ + CHUNK_STOP, + + /* At this point optional trailer headers can be found, unless the next line + is CRLF */ + CHUNK_TRAILER, + + /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR. + Next char must be a LF */ + CHUNK_TRAILER_CR, + + /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be + signalled If this is an empty trailer CHUNKE_STOP will be signalled. + Otherwise the trailer will be broadcasted via Curl_client_write() and the + next state will be CHUNK_TRAILER */ + CHUNK_TRAILER_POSTCR +} ChunkyState; + +typedef enum { + CHUNKE_STOP = -1, + CHUNKE_OK = 0, + CHUNKE_TOO_LONG_HEX = 1, + CHUNKE_ILLEGAL_HEX, + CHUNKE_BAD_CHUNK, + CHUNKE_WRITE_ERROR, + CHUNKE_BAD_ENCODING, + CHUNKE_OUT_OF_MEMORY, + CHUNKE_LAST +} CHUNKcode; + +CURL_STATIC const char *Curl_chunked_strerror(CHUNKcode code); + +struct Curl_chunker { + char hexbuffer[ MAXNUM_SIZE + 1]; + int hexindex; + ChunkyState state; + curl_off_t datasize; + size_t dataleft; /* untouched data amount at the end of the last buffer */ +}; + +#endif /* HEADER_CURL_HTTP_CHUNKS_H */ + diff --git a/libcurl/src/lib/http_digest.c b/libcurl/src/lib/http_digest.c new file mode 100644 index 0000000..2b116ef --- /dev/null +++ b/libcurl/src/lib/http_digest.c @@ -0,0 +1,179 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include "urldata.h" +#include "rawstr.h" +#include "curl_sasl.h" +#include "http_digest.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Test example headers: + +WWW-Authenticate: Digest realm="testrealm", nonce="1053604598" +Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598" + +*/ + +CURL_STATIC CURLcode Curl_input_digest(struct connectdata *conn, + bool proxy, + const char *header) /* rest of the *-authenticate: + header */ +{ + struct SessionHandle *data = conn->data; + + /* Point to the correct struct with this */ + struct digestdata *digest; + + if(proxy) { + digest = &data->state.proxydigest; + } + else { + digest = &data->state.digest; + } + + if(!checkprefix("Digest", header)) + return CURLE_BAD_CONTENT_ENCODING; + + header += strlen("Digest"); + while(*header && ISSPACE(*header)) + header++; + + return Curl_sasl_decode_digest_http_message(header, digest); +} + +CURL_STATIC CURLcode Curl_output_digest(struct connectdata *conn, + bool proxy, + const unsigned char *request, + const unsigned char *uripath) +{ + CURLcode result; + struct SessionHandle *data = conn->data; + unsigned char *path; + char *tmp; + char *response; + size_t len; + bool have_chlg; + + /* Point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + + /* Point to the name and password for this */ + const char *userp; + const char *passwdp; + + /* Point to the correct struct with this */ + struct digestdata *digest; + struct auth *authp; + + if(proxy) { + digest = &data->state.proxydigest; + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->proxyuser; + passwdp = conn->proxypasswd; + authp = &data->state.authproxy; + } + else { + digest = &data->state.digest; + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + passwdp = conn->passwd; + authp = &data->state.authhost; + } + + Curl_safefree(*allocuserpwd); + + /* not set means empty */ + if(!userp) + userp = ""; + + if(!passwdp) + passwdp = ""; + +#if defined(USE_WINDOWS_SSPI) + have_chlg = digest->input_token ? TRUE : FALSE; +#else + have_chlg = digest->nonce ? TRUE : FALSE; +#endif + + if(!have_chlg) { + authp->done = FALSE; + return CURLE_OK; + } + + /* So IE browsers < v7 cut off the URI part at the query part when they + evaluate the MD5 and some (IIS?) servers work with them so we may need to + do the Digest IE-style. Note that the different ways cause different MD5 + sums to get sent. + + Apache servers can be set to do the Digest IE-style automatically using + the BrowserMatch feature: + http://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html#msie + + Further details on Digest implementation differences: + http://www.fngtps.com/2006/09/http-authentication + */ + + if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) { + size_t urilen = tmp - (char *)uripath; + + path = (unsigned char *) aprintf("%.*s", urilen, uripath); + } + else + path = (unsigned char *) strdup((char *) uripath); + + if(!path) + return CURLE_OUT_OF_MEMORY; + + result = Curl_sasl_create_digest_http_message(data, userp, passwdp, request, + path, digest, &response, &len); + free(path); + if(result) + return result; + + *allocuserpwd = aprintf("%sAuthorization: Digest %s\r\n", + proxy ? "Proxy-" : "", + response); + free(response); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + authp->done = TRUE; + + return CURLE_OK; +} + +CURL_STATIC void Curl_digest_cleanup(struct SessionHandle *data) +{ + Curl_sasl_digest_cleanup(&data->state.digest); + Curl_sasl_digest_cleanup(&data->state.proxydigest); +} + +#endif diff --git a/libcurl/src/lib/http_digest.h b/libcurl/src/lib/http_digest.h new file mode 100644 index 0000000..699e2b1 --- /dev/null +++ b/libcurl/src/lib/http_digest.h @@ -0,0 +1,42 @@ +#ifndef HEADER_CURL_HTTP_DIGEST_H +#define HEADER_CURL_HTTP_DIGEST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* this is for digest header input */ +CURL_STATIC CURLcode Curl_input_digest(struct connectdata *conn, + bool proxy, const char *header); + +/* this is for creating digest header output */ +CURL_STATIC CURLcode Curl_output_digest(struct connectdata *conn, + bool proxy, + const unsigned char *request, + const unsigned char *uripath); + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) +CURL_STATIC void Curl_digest_cleanup(struct SessionHandle *data); +#else +#define Curl_digest_cleanup(x) Curl_nop_stmt +#endif + +#endif /* HEADER_CURL_HTTP_DIGEST_H */ diff --git a/libcurl/src/lib/http_negotiate.c b/libcurl/src/lib/http_negotiate.c new file mode 100644 index 0000000..89cb613 --- /dev/null +++ b/libcurl/src/lib/http_negotiate.c @@ -0,0 +1,208 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + +#include "urldata.h" +#include "sendf.h" +#include "curl_gssapi.h" +#include "rawstr.h" +#include "curl_base64.h" +#include "http_negotiate.h" +#include "curl_sasl.h" +#include "url.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +CURL_STATIC CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header) +{ + struct SessionHandle *data = conn->data; + struct negotiatedata *neg_ctx = proxy?&data->state.proxyneg: + &data->state.negotiate; + OM_uint32 major_status, minor_status, discard_st; + gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + size_t len; + size_t rawlen = 0; + CURLcode result; + + if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) { + /* We finished successfully our part of authentication, but server + * rejected it (since we're again here). Exit with an error since we + * can't invent anything better */ + Curl_cleanup_negotiate(data); + return CURLE_LOGIN_DENIED; + } + + if(!neg_ctx->server_name) { + /* Generate our SPN */ + char *spn = Curl_sasl_build_gssapi_spn("HTTP", proxy ? conn->proxy.name : + conn->host.name); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Populate the SPN structure */ + spn_token.value = spn; + spn_token.length = strlen(spn); + + /* Import the SPN */ + major_status = gss_import_name(&minor_status, &spn_token, + GSS_C_NT_HOSTBASED_SERVICE, + &neg_ctx->server_name); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, minor_status, "gss_import_name() failed: "); + + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + free(spn); + } + + header += strlen("Negotiate"); + while(*header && ISSPACE(*header)) + header++; + + len = strlen(header); + if(len > 0) { + result = Curl_base64_decode(header, (unsigned char **)&input_token.value, + &rawlen); + if(result) + return result; + + if(!rawlen) { + infof(data, "Negotiate handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + input_token.length = rawlen; + + DEBUGASSERT(input_token.value != NULL); + } + + major_status = Curl_gss_init_sec_context(data, + &minor_status, + &neg_ctx->context, + neg_ctx->server_name, + &Curl_spnego_mech_oid, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + &output_token, + TRUE, + NULL); + Curl_safefree(input_token.value); + + neg_ctx->status = major_status; + if(GSS_ERROR(major_status)) { + if(output_token.value) + gss_release_buffer(&discard_st, &output_token); + Curl_gss_log_error(conn->data, minor_status, + "gss_init_sec_context() failed: "); + return CURLE_OUT_OF_MEMORY; + } + + if(!output_token.value || !output_token.length) { + if(output_token.value) + gss_release_buffer(&discard_st, &output_token); + return CURLE_OUT_OF_MEMORY; + } + + neg_ctx->output_token = output_token; + + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) +{ + struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: + &conn->data->state.negotiate; + char *encoded = NULL; + size_t len = 0; + char *userp; + CURLcode result; + OM_uint32 discard_st; + + result = Curl_base64_encode(conn->data, + neg_ctx->output_token.value, + neg_ctx->output_token.length, + &encoded, &len); + if(result) { + gss_release_buffer(&discard_st, &neg_ctx->output_token); + neg_ctx->output_token.value = NULL; + neg_ctx->output_token.length = 0; + return result; + } + + if(!encoded || !len) { + gss_release_buffer(&discard_st, &neg_ctx->output_token); + neg_ctx->output_token.value = NULL; + neg_ctx->output_token.length = 0; + return CURLE_REMOTE_ACCESS_DENIED; + } + + userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", + encoded); + if(proxy) { + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = userp; + } + else { + Curl_safefree(conn->allocptr.userpwd); + conn->allocptr.userpwd = userp; + } + + free(encoded); + + return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; +} + +static void cleanup(struct negotiatedata *neg_ctx) +{ + OM_uint32 minor_status; + if(neg_ctx->context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER); + + if(neg_ctx->output_token.value) + gss_release_buffer(&minor_status, &neg_ctx->output_token); + + if(neg_ctx->server_name != GSS_C_NO_NAME) + gss_release_name(&minor_status, &neg_ctx->server_name); + + memset(neg_ctx, 0, sizeof(*neg_ctx)); +} + +CURL_STATIC void Curl_cleanup_negotiate(struct SessionHandle *data) +{ + cleanup(&data->state.negotiate); + cleanup(&data->state.proxyneg); +} + +#endif /* HAVE_GSSAPI && !CURL_DISABLE_HTTP && USE_SPNEGO */ diff --git a/libcurl/src/lib/http_negotiate.h b/libcurl/src/lib/http_negotiate.h new file mode 100644 index 0000000..931ce1f --- /dev/null +++ b/libcurl/src/lib/http_negotiate.h @@ -0,0 +1,42 @@ +#ifndef HEADER_CURL_HTTP_NEGOTIATE_H +#define HEADER_CURL_HTTP_NEGOTIATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_SPNEGO + +/* this is for Negotiate header input */ +CURL_STATIC CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating Negotiate header output */ +CURL_STATIC CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); + +CURL_STATIC void Curl_cleanup_negotiate(struct SessionHandle *data); + +#ifdef USE_WINDOWS_SSPI +#define GSS_ERROR(status) (status & 0x80000000) +#endif + +#endif /* USE_SPNEGO */ + +#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */ diff --git a/libcurl/src/lib/http_negotiate_sspi.c b/libcurl/src/lib/http_negotiate_sspi.c new file mode 100644 index 0000000..efd2164 --- /dev/null +++ b/libcurl/src/lib/http_negotiate_sspi.c @@ -0,0 +1,298 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WINDOWS_SSPI + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + +#include "urldata.h" +#include "sendf.h" +#include "rawstr.h" +#include "warnless.h" +#include "curl_base64.h" +#include "curl_sasl.h" +#include "http_negotiate.h" +#include "curl_multibyte.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +CURL_STATIC CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header) +{ + BYTE *input_token = NULL; + SecBufferDesc out_buff_desc; + SecBuffer out_sec_buff; + SecBufferDesc in_buff_desc; + SecBuffer in_sec_buff; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + size_t len = 0, input_token_len = 0; + CURLcode result; + + /* Point to the username and password */ + const char *userp; + const char *passwdp; + + /* Point to the correct struct with this */ + struct negotiatedata *neg_ctx; + + if(proxy) { + userp = conn->proxyuser; + passwdp = conn->proxypasswd; + neg_ctx = &conn->data->state.proxyneg; + } + else { + userp = conn->user; + 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) { + /* We finished successfully our part of authentication, but server + * rejected it (since we're again here). Exit with an error since we + * can't invent anything better */ + Curl_cleanup_negotiate(conn->data); + return CURLE_LOGIN_DENIED; + } + + if(!neg_ctx->server_name) { + /* Check proxy auth requested but no given proxy name */ + if(proxy && !conn->proxy.name) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* Generate our SPN */ + neg_ctx->server_name = Curl_sasl_build_spn("HTTP", + proxy ? conn->proxy.name : + conn->host.name); + if(!neg_ctx->server_name) + return CURLE_OUT_OF_MEMORY; + } + + if(!neg_ctx->output_token) { + PSecPkgInfo SecurityPackage; + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_NEGOTIATE), + &SecurityPackage); + if(status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + /* Allocate input and output buffers according to the max token size + as indicated by the security package */ + neg_ctx->token_max = SecurityPackage->cbMaxToken; + neg_ctx->output_token = malloc(neg_ctx->token_max); + s_pSecFn->FreeContextBuffer(SecurityPackage); + } + + /* Obtain the input token, if any */ + header += strlen("Negotiate"); + while(*header && ISSPACE(*header)) + header++; + + len = strlen(header); + if(!len) { + /* Is this the first call in a new negotiation? */ + if(neg_ctx->context) { + /* The server rejected our authentication and hasn't suppled any more + negotiation mechanisms */ + return CURLE_LOGIN_DENIED; + } + + /* We have to acquire credentials and allocate memory for the context */ + neg_ctx->credentials = malloc(sizeof(CredHandle)); + neg_ctx->context = malloc(sizeof(CtxtHandle)); + + if(!neg_ctx->credentials || !neg_ctx->context) + return CURLE_OUT_OF_MEMORY; + + if(userp && *userp) { + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &neg_ctx->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ + neg_ctx->p_identity = &neg_ctx->identity; + } + else + /* Use the current Windows user */ + neg_ctx->p_identity = NULL; + + /* Acquire our credientials handle */ + neg_ctx->status = + s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_NEGOTIATE), + SECPKG_CRED_OUTBOUND, NULL, + neg_ctx->p_identity, NULL, NULL, + neg_ctx->credentials, &expiry); + if(neg_ctx->status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + } + else { + result = Curl_base64_decode(header, + (unsigned char **)&input_token, + &input_token_len); + if(result) + return result; + + if(!input_token_len) { + infof(conn->data, + "Negotiate handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + } + + /* Setup the "output" security buffer */ + out_buff_desc.ulVersion = SECBUFFER_VERSION; + out_buff_desc.cBuffers = 1; + out_buff_desc.pBuffers = &out_sec_buff; + out_sec_buff.BufferType = SECBUFFER_TOKEN; + out_sec_buff.pvBuffer = neg_ctx->output_token; + out_sec_buff.cbBuffer = curlx_uztoul(neg_ctx->token_max); + + /* Setup the "input" security buffer if present */ + if(input_token) { + in_buff_desc.ulVersion = SECBUFFER_VERSION; + in_buff_desc.cBuffers = 1; + in_buff_desc.pBuffers = &in_sec_buff; + in_sec_buff.BufferType = SECBUFFER_TOKEN; + in_sec_buff.pvBuffer = input_token; + in_sec_buff.cbBuffer = curlx_uztoul(input_token_len); + } + + /* Generate our message */ + neg_ctx->status = s_pSecFn->InitializeSecurityContext( + neg_ctx->credentials, + input_token ? neg_ctx->context : NULL, + neg_ctx->server_name, + ISC_REQ_CONFIDENTIALITY, + 0, + SECURITY_NATIVE_DREP, + input_token ? &in_buff_desc : NULL, + 0, + neg_ctx->context, + &out_buff_desc, + &attrs, + &expiry); + + free(input_token); + + if(GSS_ERROR(neg_ctx->status)) + return CURLE_OUT_OF_MEMORY; + + if(neg_ctx->status == SEC_I_COMPLETE_NEEDED || + neg_ctx->status == SEC_I_COMPLETE_AND_CONTINUE) { + neg_ctx->status = s_pSecFn->CompleteAuthToken(neg_ctx->context, + &out_buff_desc); + if(GSS_ERROR(neg_ctx->status)) + return CURLE_RECV_ERROR; + } + + neg_ctx->output_token_length = out_sec_buff.cbBuffer; + + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) +{ + struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: + &conn->data->state.negotiate; + char *encoded = NULL; + size_t len = 0; + char *userp; + CURLcode error; + + error = Curl_base64_encode(conn->data, + (const char*)neg_ctx->output_token, + neg_ctx->output_token_length, + &encoded, &len); + if(error) + return error; + + if(!len) + return CURLE_REMOTE_ACCESS_DENIED; + + userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", + encoded); + + if(proxy) { + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = userp; + } + else { + Curl_safefree(conn->allocptr.userpwd); + conn->allocptr.userpwd = userp; + } + free(encoded); + return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; +} + +static void cleanup(struct negotiatedata *neg_ctx) +{ + /* Free our security context */ + if(neg_ctx->context) { + s_pSecFn->DeleteSecurityContext(neg_ctx->context); + free(neg_ctx->context); + neg_ctx->context = NULL; + } + + /* Free our credentials handle */ + if(neg_ctx->credentials) { + s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials); + free(neg_ctx->credentials); + neg_ctx->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(neg_ctx->p_identity); + neg_ctx->p_identity = NULL; + + /* Free the SPN and output token */ + Curl_safefree(neg_ctx->server_name); + Curl_safefree(neg_ctx->output_token); + + /* Reset any variables */ + neg_ctx->token_max = 0; +} + +CURL_STATIC void Curl_cleanup_negotiate(struct SessionHandle *data) +{ + cleanup(&data->state.negotiate); + cleanup(&data->state.proxyneg); +} + +#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ + +#endif /* USE_WINDOWS_SSPI */ diff --git a/libcurl/src/lib/http_proxy.c b/libcurl/src/lib/http_proxy.c new file mode 100644 index 0000000..4c45b9c --- /dev/null +++ b/libcurl/src/lib/http_proxy.c @@ -0,0 +1,590 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) + +#include "urldata.h" +#include +#include "http_proxy.h" +#include "sendf.h" +#include "http.h" +#include "url.h" +#include "select.h" +#include "rawstr.h" +#include "progress.h" +#include "non-ascii.h" +#include "connect.h" +#include "curl_printf.h" +#include "curlx.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +CURL_STATIC CURLcode Curl_proxy_connect(struct connectdata *conn) +{ + if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { +#ifndef CURL_DISABLE_PROXY + /* for [protocol] tunneled through HTTP proxy */ + struct HTTP http_proxy; + void *prot_save; + CURLcode result; + + /* BLOCKING */ + /* We want "seamless" operations through HTTP proxy tunnel */ + + /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the + * member conn->proto.http; we want [protocol] through HTTP and we have + * to change the member temporarily for connecting to the HTTP + * proxy. After Curl_proxyCONNECT we have to set back the member to the + * original pointer + * + * This function might be called several times in the multi interface case + * if the proxy's CONNTECT response is not instant. + */ + prot_save = conn->data->req.protop; + memset(&http_proxy, 0, sizeof(http_proxy)); + conn->data->req.protop = &http_proxy; + connkeep(conn, "HTTP proxy CONNECT"); + result = Curl_proxyCONNECT(conn, FIRSTSOCKET, + conn->host.name, conn->remote_port); + conn->data->req.protop = prot_save; + if(CURLE_OK != result) + return result; + Curl_safefree(conn->allocptr.proxyuserpwd); +#else + return CURLE_NOT_BUILT_IN; +#endif + } + /* no HTTP tunnel proxy, just return */ + return CURLE_OK; +} + +/* + * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This + * function will issue the necessary commands to get a seamless tunnel through + * this proxy. After that, the socket can be used just as a normal socket. + */ + +CURL_STATIC CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int sockindex, + const char *hostname, + int remote_port) +{ + int subversion=0; + struct SessionHandle *data=conn->data; + struct SingleRequest *k = &data->req; + CURLcode result; + curl_socket_t tunnelsocket = conn->sock[sockindex]; + curl_off_t cl=0; + bool closeConnection = FALSE; + bool chunked_encoding = FALSE; + long check; + +#define SELECT_OK 0 +#define SELECT_ERROR 1 +#define SELECT_TIMEOUT 2 + int error = SELECT_OK; + + if(conn->tunnel_state[sockindex] == TUNNEL_COMPLETE) + return CURLE_OK; /* CONNECT is already completed */ + + conn->bits.proxy_connect_closed = FALSE; + + do { + if(TUNNEL_INIT == conn->tunnel_state[sockindex]) { + /* BEGIN CONNECT PHASE */ + char *host_port; + Curl_send_buffer *req_buffer; + + infof(data, "Establish HTTP proxy tunnel to %s:%hu\n", + hostname, remote_port); + + /* This only happens if we've looped here due to authentication + reasons, and we don't really use the newly cloned URL here + then. Just free() it. */ + free(data->req.newurl); + data->req.newurl = NULL; + + /* initialize a dynamic send-buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + host_port = aprintf("%s:%hu", hostname, remote_port); + if(!host_port) { + free(req_buffer); + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the proxy-authorization header, if any */ + result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE); + + free(host_port); + + if(!result) { + char *host=(char *)""; + const char *proxyconn=""; + const char *useragent=""; + const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ? + "1.0" : "1.1"; + char *hostheader= /* host:port with IPv6 support */ + aprintf("%s%s%s:%hu", conn->bits.ipv6_ip?"[":"", + hostname, conn->bits.ipv6_ip?"]":"", + remote_port); + if(!hostheader) { + free(req_buffer); + return CURLE_OUT_OF_MEMORY; + } + + if(!Curl_checkProxyheaders(conn, "Host:")) { + host = aprintf("Host: %s\r\n", hostheader); + if(!host) { + free(hostheader); + free(req_buffer); + return CURLE_OUT_OF_MEMORY; + } + } + if(!Curl_checkProxyheaders(conn, "Proxy-Connection:")) + proxyconn = "Proxy-Connection: Keep-Alive\r\n"; + + if(!Curl_checkProxyheaders(conn, "User-Agent:") && + data->set.str[STRING_USERAGENT]) + useragent = conn->allocptr.uagent; + + result = + Curl_add_bufferf(req_buffer, + "CONNECT %s HTTP/%s\r\n" + "%s" /* Host: */ + "%s" /* Proxy-Authorization */ + "%s" /* User-Agent */ + "%s", /* Proxy-Connection */ + hostheader, + http, + host, + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + useragent, + proxyconn); + + if(host && *host) + free(host); + free(hostheader); + + if(!result) + result = Curl_add_custom_headers(conn, TRUE, req_buffer); + + if(!result) + /* CRLF terminate the request */ + result = Curl_add_bufferf(req_buffer, "\r\n"); + + if(!result) { + /* Send the connect request to the proxy */ + /* BLOCKING */ + result = + Curl_add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, sockindex); + } + req_buffer = NULL; + if(result) + failf(data, "Failed sending CONNECT to proxy"); + } + + free(req_buffer); + if(result) + return result; + + conn->tunnel_state[sockindex] = TUNNEL_CONNECT; + } /* END CONNECT 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 */ + int perline; /* count bytes per line */ + int keepon=TRUE; + ssize_t gotbytes; + char *ptr; + char *line_start; + + ptr=data->state.buffer; + line_start = ptr; + + nread=0; + perline=0; + + while((nreadstate.buffer+BUFSIZE+1); + result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, + &gotbytes); + if(result==CURLE_AGAIN) + continue; /* go loop yourself */ + else if(result) + keepon = FALSE; + else if(gotbytes <= 0) { + keepon = FALSE; + if(data->set.proxyauth && data->state.authproxy.avail) { + /* proxy auth was requested and there was proxy auth available, + then deem this as "mere" proxy disconnect */ + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Proxy CONNECT connection closed"); + } + else { + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted"); + } + } + else { + /* + * We got a whole chunk of data, which can be anything from one + * byte to a set of lines and possibly just a piece of the last + * line. + */ + int i; + + nread += gotbytes; + + if(keepon > TRUE) { + /* This means we are currently ignoring a response-body */ + + nread = 0; /* make next read start over in the read buffer */ + ptr=data->state.buffer; + if(cl) { + /* A Content-Length based body: simply count down the counter + and make sure to break out of the loop when we're done! */ + cl -= gotbytes; + if(cl<=0) { + keepon = FALSE; + break; + } + } + else { + /* chunked-encoded body, so we need to do the chunked dance + properly to know when the end of the body is reached */ + CHUNKcode r; + ssize_t tookcareof=0; + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + keepon = FALSE; + /* we did the full CONNECT treatment, go COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; + } + else + infof(data, "Read %zd bytes of chunk, continue\n", + tookcareof); + } + } + else + for(i = 0; i < gotbytes; ptr++, i++) { + perline++; /* amount of bytes in this line so far */ + if(*ptr == 0x0a) { + char letter; + int writetype; + + /* convert from the network encoding */ + result = Curl_convert_from_network(data, line_start, + perline); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + + /* output debug if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + line_start, (size_t)perline, conn); + + /* send the header to the callback */ + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + result = Curl_client_write(conn, writetype, line_start, + perline); + + data->info.header_size += (long)perline; + data->req.headerbytecount += (long)perline; + + if(result) + return result; + + /* Newlines are CRLF, so the CR is ignored as the line isn't + really terminated until the LF comes. Treat a following CR + as end-of-headers as well.*/ + + if(('\r' == line_start[0]) || + ('\n' == line_start[0])) { + /* end of response-headers from the proxy */ + nread = 0; /* make next read start over in the read + buffer */ + ptr=data->state.buffer; + if((407 == k->httpcode) && !data->state.authproblem) { + /* If we get a 407 response code with content length + when we have no auth problem, we must ignore the + whole response-body */ + keepon = 2; + + if(cl) { + infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T + " bytes of response-body\n", cl); + + /* remove the remaining chunk of what we already + read */ + cl -= (gotbytes - i); + + if(cl<=0) + /* if the whole thing was already read, we are done! + */ + keepon=FALSE; + } + else if(chunked_encoding) { + CHUNKcode r; + /* We set ignorebody true here since the chunked + decoder function will acknowledge that. Pay + attention so that this is cleared again when this + function returns! */ + k->ignorebody = TRUE; + infof(data, "%zd bytes of chunk left\n", gotbytes-i); + + if(line_start[1] == '\n') { + /* this can only be a LF if the letter at index 0 + was a CR */ + line_start++; + i++; + } + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, line_start+1, + gotbytes -i, &gotbytes); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + keepon = FALSE; + /* we did the full CONNECT treatment, go to + COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; + } + else + infof(data, "Read %zd bytes of chunk, continue\n", + gotbytes); + } + else { + /* without content-length or chunked encoding, we + can't keep the connection alive since the close is + the end signal so we bail out at once instead */ + keepon=FALSE; + } + } + else { + keepon = FALSE; + if(200 == data->info.httpproxycode) { + if(gotbytes - (i+1)) + failf(data, "Proxy CONNECT followed by %zd bytes " + "of opaque data. Data ignored (known bug #39)", + gotbytes - (i+1)); + } + } + /* we did the full CONNECT treatment, go to COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; + break; /* breaks out of for-loop, not switch() */ + } + + /* keep a backup of the position we are about to blank */ + letter = line_start[perline]; + line_start[perline]=0; /* zero terminate the buffer */ + if((checkprefix("WWW-Authenticate:", line_start) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", line_start) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(line_start); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(conn, proxy, auth); + + free(auth); + + if(result) + return result; + } + else if(checkprefix("Content-Length:", line_start)) { + cl = curlx_strtoofft(line_start + + strlen("Content-Length:"), NULL, 10); + } + else if(Curl_compareheader(line_start, + "Connection:", "close")) + closeConnection = TRUE; + else if(Curl_compareheader(line_start, + "Transfer-Encoding:", + "chunked")) { + infof(data, "CONNECT responded chunked\n"); + chunked_encoding = TRUE; + /* init our chunky engine */ + Curl_httpchunk_init(conn); + } + else if(Curl_compareheader(line_start, + "Proxy-Connection:", "close")) + closeConnection = TRUE; + else if(2 == sscanf(line_start, "HTTP/1.%d %d", + &subversion, + &k->httpcode)) { + /* store the HTTP code from the proxy */ + data->info.httpproxycode = k->httpcode; + } + /* put back the letter we blanked out before */ + line_start[perline]= letter; + + perline=0; /* line starts over here */ + line_start = ptr+1; /* this skips the zero byte we wrote */ + } + } + } + break; + } /* switch */ + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + } /* while there's buffer left and loop is requested */ + + if(error) + return CURLE_RECV_ERROR; + + if(data->info.httpproxycode != 200) { + /* Deal with the possibly already received authenticate + headers. 'newurl' is set to a new URL if we must loop. */ + result = Curl_http_auth_act(conn); + if(result) + return result; + + if(conn->bits.close) + /* the connection has been marked for closure, most likely in the + Curl_http_auth_act() function and thus we can kill it at once + below + */ + closeConnection = TRUE; + } + + if(closeConnection && data->req.newurl) { + /* Connection closed by server. Don't use it anymore */ + Curl_closesocket(conn, conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + break; + } + } /* END READING RESPONSE PHASE */ + + /* 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 + * is complete we start over in INIT state */ + if(data->req.newurl && + (TUNNEL_COMPLETE == conn->tunnel_state[sockindex])) { + conn->tunnel_state[sockindex] = TUNNEL_INIT; + infof(data, "TUNNEL_STATE switched to: %d\n", + conn->tunnel_state[sockindex]); + } + + } while(data->req.newurl); + + if(200 != data->req.httpcode) { + if(closeConnection && data->req.newurl) { + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Connect me again please\n"); + } + else { + 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 */ + conn->tunnel_state[sockindex] = TUNNEL_INIT; + + 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; + + /* If a proxy-authorization header was used for the proxy, then we should + make sure that it isn't accidentally used for the document request + after we've connected. So let's free and clear it here. */ + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = NULL; + + data->state.authproxy.done = TRUE; + + infof (data, "Proxy replied OK to CONNECT request\n"); + data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ + conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the + document request */ + return CURLE_OK; +} +#endif /* CURL_DISABLE_PROXY */ diff --git a/libcurl/src/lib/http_proxy.h b/libcurl/src/lib/http_proxy.h new file mode 100644 index 0000000..cb50346 --- /dev/null +++ b/libcurl/src/lib/http_proxy.h @@ -0,0 +1,41 @@ +#ifndef HEADER_CURL_HTTP_PROXY_H +#define HEADER_CURL_HTTP_PROXY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) +/* ftp can use this as well */ +CURL_STATIC CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int tunnelsocket, + const char *hostname, int remote_port); + +/* Default proxy timeout in milliseconds */ +#define PROXY_TIMEOUT (3600*1000) + +CURL_STATIC CURLcode Curl_proxy_connect(struct connectdata *conn); + +#else +#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN +#define Curl_proxy_connect(x) CURLE_OK +#endif + +#endif /* HEADER_CURL_HTTP_PROXY_H */ diff --git a/libcurl/src/lib/idn_win32.c b/libcurl/src/lib/idn_win32.c new file mode 100644 index 0000000..b369723 --- /dev/null +++ b/libcurl/src/lib/idn_win32.c @@ -0,0 +1,108 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + /* + * IDN conversions using Windows kernel32 and normaliz libraries. + */ + +#include "curl_setup.h" + +#ifdef USE_WIN32_IDN + +#include "curl_multibyte.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifdef WANT_IDN_PROTOTYPES +# if defined(_SAL_VERSION) +WINNORMALIZEAPI int WINAPI +IdnToAscii(_In_ DWORD dwFlags, + _In_reads_(cchUnicodeChar) LPCWSTR lpUnicodeCharStr, + _In_ int cchUnicodeChar, + _Out_writes_opt_(cchASCIIChar) LPWSTR lpASCIICharStr, + _In_ int cchASCIIChar); +WINNORMALIZEAPI int WINAPI +IdnToUnicode(_In_ DWORD dwFlags, + _In_reads_(cchASCIIChar) LPCWSTR lpASCIICharStr, + _In_ int cchASCIIChar, + _Out_writes_opt_(cchUnicodeChar) LPWSTR lpUnicodeCharStr, + _In_ int cchUnicodeChar); +# else +WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags, + const WCHAR *lpUnicodeCharStr, + int cchUnicodeChar, + WCHAR *lpASCIICharStr, + int cchASCIIChar); +WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags, + const WCHAR *lpASCIICharStr, + int cchASCIIChar, + WCHAR *lpUnicodeCharStr, + int cchUnicodeChar); +# endif +#endif + +#define IDN_MAX_LENGTH 255 + +int curl_win32_idn_to_ascii(const char *in, char **out); +int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8); + +int curl_win32_idn_to_ascii(const char *in, char **out) +{ + wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); + if(in_w) { + wchar_t punycode[IDN_MAX_LENGTH]; + if(IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH) == 0) { + wprintf(L"ERROR %d converting to Punycode\n", GetLastError()); + free(in_w); + return 0; + } + free(in_w); + + *out = Curl_convert_wchar_to_UTF8(punycode); + if(!*out) + return 0; + } + return 1; +} + +int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8) +{ + (void)in_len; /* unused */ + if(in) { + WCHAR unicode[IDN_MAX_LENGTH]; + + if(IdnToUnicode(0, (wchar_t *)in, -1, unicode, IDN_MAX_LENGTH) == 0) { + wprintf(L"ERROR %d converting to Punycode\n", GetLastError()); + return 0; + } + else { + *out_utf8 = Curl_convert_wchar_to_UTF8(unicode); + if(!*out_utf8) + return 0; + } + } + return 1; +} + +#endif /* USE_WIN32_IDN */ diff --git a/libcurl/src/lib/if2ip.c b/libcurl/src/lib/if2ip.c new file mode 100644 index 0000000..c4f6e70 --- /dev/null +++ b/libcurl/src/lib/if2ip.c @@ -0,0 +1,271 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_NET_IF_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif +#ifdef HAVE_IFADDRS_H +# include +#endif +#ifdef HAVE_STROPTS_H +# include +#endif +#ifdef __VMS +# include +#endif + +#include "inet_ntop.h" +#include "strequal.h" +#include "if2ip.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* ------------------------------------------------------------------ */ + +/* Return the scope of the given address. */ +CURL_STATIC unsigned int Curl_ipv6_scope(const struct sockaddr *sa) +{ +#ifndef ENABLE_IPV6 + (void) sa; +#else + if(sa->sa_family == AF_INET6) { + const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *) sa; + const unsigned char * b = sa6->sin6_addr.s6_addr; + unsigned short w = (unsigned short) ((b[0] << 8) | b[1]); + + switch(w & 0xFFC0) { + case 0xFE80: + return IPV6_SCOPE_LINKLOCAL; + case 0xFEC0: + return IPV6_SCOPE_SITELOCAL; + case 0x0000: + w = b[1] | b[2] | b[3] | b[4] | b[5] | b[6] | b[7] | b[8] | b[9] | + b[10] | b[11] | b[12] | b[13] | b[14]; + if(w || b[15] != 0x01) + break; + return IPV6_SCOPE_NODELOCAL; + default: + break; + } + } +#endif + + return IPV6_SCOPE_GLOBAL; +} + + +#if defined(HAVE_GETIFADDRS) + +CURL_STATIC bool Curl_if_is_interface_name(const char *interf) +{ + bool result = FALSE; + + struct ifaddrs *iface, *head; + + if(getifaddrs(&head) >= 0) { + for(iface=head; iface != NULL; iface=iface->ifa_next) { + if(curl_strequal(iface->ifa_name, interf)) { + result = TRUE; + break; + } + } + freeifaddrs(head); + } + return result; +} + +CURL_STATIC if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int remote_scope_id, const char *interf, + char *buf, int buf_size) +{ + struct ifaddrs *iface, *head; + if2ip_result_t res = IF2IP_NOT_FOUND; + +#ifndef ENABLE_IPV6 + (void) remote_scope; + +#ifndef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + (void) remote_scope_id; +#endif + +#endif + + if(getifaddrs(&head) >= 0) { + for(iface = head; iface != NULL; iface=iface->ifa_next) { + if(iface->ifa_addr != NULL) { + if(iface->ifa_addr->sa_family == af) { + if(curl_strequal(iface->ifa_name, interf)) { + void *addr; + char *ip; + char scope[12] = ""; + char ipstr[64]; +#ifdef ENABLE_IPV6 + if(af == AF_INET6) { + unsigned int scopeid = 0; + unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr); + + if(ifscope != remote_scope) { + /* We are interested only in interface addresses whose + scope matches the remote address we want to + connect to: global for global, link-local for + link-local, etc... */ + if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED; + continue; + } + + addr = &((struct sockaddr_in6 *)iface->ifa_addr)->sin6_addr; +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + /* Include the scope of this interface as part of the address */ + scopeid = + ((struct sockaddr_in6 *)iface->ifa_addr)->sin6_scope_id; + + /* If given, scope id should match. */ + if(remote_scope_id && scopeid != remote_scope_id) { + if(res == IF2IP_NOT_FOUND) + res = IF2IP_AF_NOT_SUPPORTED; + + continue; + } +#endif + if(scopeid) + snprintf(scope, sizeof(scope), "%%%u", scopeid); + } + else +#endif + addr = &((struct sockaddr_in *)iface->ifa_addr)->sin_addr; + res = IF2IP_FOUND; + ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr)); + snprintf(buf, buf_size, "%s%s", ip, scope); + break; + } + } + else if((res == IF2IP_NOT_FOUND) && + curl_strequal(iface->ifa_name, interf)) { + res = IF2IP_AF_NOT_SUPPORTED; + } + } + } + + freeifaddrs(head); + } + + return res; +} + +#elif defined(HAVE_IOCTL_SIOCGIFADDR) + +CURL_STATIC bool Curl_if_is_interface_name(const char *interf) +{ + /* This is here just to support the old interfaces */ + char buf[256]; + + return (Curl_if2ip(AF_INET, 0 /* unused */, 0, interf, buf, sizeof(buf)) == + IF2IP_NOT_FOUND) ? FALSE : TRUE; +} + +CURL_STATIC if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int remote_scope_id, const char *interf, + char *buf, int buf_size) +{ + struct ifreq req; + struct in_addr in; + struct sockaddr_in *s; + curl_socket_t dummy; + size_t len; + + (void)remote_scope; + (void)remote_scope_id; + + if(!interf || (af != AF_INET)) + return IF2IP_NOT_FOUND; + + len = strlen(interf); + if(len >= sizeof(req.ifr_name)) + return IF2IP_NOT_FOUND; + + dummy = socket(AF_INET, SOCK_STREAM, 0); + if(CURL_SOCKET_BAD == dummy) + return IF2IP_NOT_FOUND; + + memset(&req, 0, sizeof(req)); + memcpy(req.ifr_name, interf, len+1); + req.ifr_addr.sa_family = AF_INET; + + if(ioctl(dummy, SIOCGIFADDR, &req) < 0) { + sclose(dummy); + /* With SIOCGIFADDR, we cannot tell the difference between an interface + that does not exist and an interface that has no address of the + correct family. Assume the interface does not exist */ + return IF2IP_NOT_FOUND; + } + + s = (struct sockaddr_in *)&req.ifr_addr; + memcpy(&in, &s->sin_addr, sizeof(in)); + Curl_inet_ntop(s->sin_family, &in, buf, buf_size); + + sclose(dummy); + return IF2IP_FOUND; +} + +#else + +CURL_STATIC bool Curl_if_is_interface_name(const char *interf) +{ + (void) interf; + + return FALSE; +} + +CURL_STATIC if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int remote_scope_id, const char *interf, + char *buf, int buf_size) +{ + (void) af; + (void) remote_scope; + (void) remote_scope_id; + (void) interf; + (void) buf; + (void) buf_size; + return IF2IP_NOT_FOUND; +} + +#endif diff --git a/libcurl/src/lib/if2ip.h b/libcurl/src/lib/if2ip.h new file mode 100644 index 0000000..d6499f3 --- /dev/null +++ b/libcurl/src/lib/if2ip.h @@ -0,0 +1,83 @@ +#ifndef HEADER_CURL_IF2IP_H +#define HEADER_CURL_IF2IP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* IPv6 address scopes. */ +#define IPV6_SCOPE_GLOBAL 0 /* Global scope. */ +#define IPV6_SCOPE_LINKLOCAL 1 /* Link-local scope. */ +#define IPV6_SCOPE_SITELOCAL 2 /* Site-local scope (deprecated). */ +#define IPV6_SCOPE_NODELOCAL 3 /* Loopback. */ + +CURL_STATIC unsigned int Curl_ipv6_scope(const struct sockaddr *sa); + +CURL_STATIC bool Curl_if_is_interface_name(const char *interf); + +typedef enum { + IF2IP_NOT_FOUND = 0, /* Interface not found */ + IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */ + IF2IP_FOUND = 2 /* The address has been stored in "buf" */ +} if2ip_result_t; + +CURL_STATIC if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int remote_scope_id, const char *interf, + char *buf, int buf_size); + +#ifdef __INTERIX + +/* Nedelcho Stanev's work-around for SFU 3.0 */ +struct ifreq { +#define IFNAMSIZ 16 +#define IFHWADDRLEN 6 + union { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_metric; + int ifru_mtu; + } ifr_ifru; +}; + +/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the + C code. */ + +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ + +#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ + +#endif /* __INTERIX */ + +#endif /* HEADER_CURL_IF2IP_H */ diff --git a/libcurl/src/lib/imap.c b/libcurl/src/lib/imap.c new file mode 100644 index 0000000..e6d83f2 --- /dev/null +++ b/libcurl/src/lib/imap.c @@ -0,0 +1,2142 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2195 CRAM-MD5 authentication + * RFC2595 Using TLS with IMAP, POP3 and ACAP + * RFC2831 DIGEST-MD5 authentication + * RFC3501 IMAPv4 protocol + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC4959 IMAP Extension for SASL Initial Client Response + * RFC5092 IMAP URL Scheme + * RFC6749 OAuth 2.0 Authorization Framework + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_IMAP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "imap.h" + +#include "strtoofft.h" +#include "strequal.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "rawstr.h" +#include "curl_sasl.h" +#include "warnless.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* Local API functions */ +static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode imap_do(struct connectdata *conn, bool *done); +static CURLcode imap_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode imap_connect(struct connectdata *conn, bool *done); +static CURLcode imap_disconnect(struct connectdata *conn, bool dead); +static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done); +static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode imap_setup_connection(struct connectdata *conn); +static char *imap_atom(const char *str); +static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...); +static CURLcode imap_parse_url_options(struct connectdata *conn); +static CURLcode imap_parse_url_path(struct connectdata *conn); +static CURLcode imap_parse_custom_request(struct connectdata *conn); +static CURLcode imap_perform_authenticate(struct connectdata *conn, + const char *mech, + const char *initresp); +static CURLcode imap_continue_authenticate(struct connectdata *conn, + const char *resp); +static void imap_get_message(char *buffer, char** outptr); + +/* + * IMAP protocol handler. + */ + +const struct Curl_handler Curl_handler_imap = { + "IMAP", /* scheme */ + imap_setup_connection, /* setup_connection */ + imap_do, /* do_it */ + imap_done, /* done */ + ZERO_NULL, /* do_more */ + imap_connect, /* connect_it */ + imap_multi_statemach, /* connecting */ + imap_doing, /* doing */ + imap_getsock, /* proto_getsock */ + imap_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + imap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_IMAP, /* defport */ + CURLPROTO_IMAP, /* protocol */ + PROTOPT_CLOSEACTION /* flags */ +}; + +#ifdef USE_SSL +/* + * IMAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_imaps = { + "IMAPS", /* scheme */ + imap_setup_connection, /* setup_connection */ + imap_do, /* do_it */ + imap_done, /* done */ + ZERO_NULL, /* do_more */ + imap_connect, /* connect_it */ + imap_multi_statemach, /* connecting */ + imap_doing, /* doing */ + imap_getsock, /* proto_getsock */ + imap_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + imap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_IMAPS, /* defport */ + CURLPROTO_IMAPS, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */ +}; +#endif + +#ifndef CURL_DISABLE_HTTP +/* + * HTTP-proxyed IMAP protocol handler. + */ + +static const struct Curl_handler Curl_handler_imap_proxy = { + "IMAP", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_IMAP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * HTTP-proxyed IMAPS protocol handler. + */ + +static const struct Curl_handler Curl_handler_imaps_proxy = { + "IMAPS", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_IMAPS, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; +#endif +#endif + +/* SASL parameters for the imap protocol */ +static const struct SASLproto saslimap = { + "imap", /* The service name */ + '+', /* Code received when continuation is expected */ + 'O', /* Code to receive upon authentication success */ + 0, /* Maximum initial response length (no max) */ + imap_perform_authenticate, /* Send authentication command */ + imap_continue_authenticate, /* Send authentication continuation */ + imap_get_message /* Get SASL response message */ +}; + + +#ifdef USE_SSL +static void imap_to_imaps(struct connectdata *conn) +{ + conn->handler = &Curl_handler_imaps; +} +#else +#define imap_to_imaps(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * imap_matchresp() + * + * Determines whether the untagged response is related to the specified + * command by checking if it is in format "* ..." or + * "* ...". + * + * The "* " marker is assumed to have already been checked by the caller. + */ +static bool imap_matchresp(const char *line, size_t len, const char *cmd) +{ + const char *end = line + len; + size_t cmd_len = strlen(cmd); + + /* Skip the untagged response marker */ + line += 2; + + /* Do we have a number after the marker? */ + if(line < end && ISDIGIT(*line)) { + /* Skip the number */ + do + line++; + while(line < end && ISDIGIT(*line)); + + /* Do we have the space character? */ + if(line == end || *line != ' ') + return FALSE; + + line++; + } + + /* Does the command name match and is it followed by a space character or at + the end of line? */ + if(line + cmd_len <= end && Curl_raw_nequal(line, cmd, cmd_len) && + (line[cmd_len] == ' ' || line + cmd_len + 2 == end)) + return TRUE; + + return FALSE; +} + +/*********************************************************************** + * + * imap_endofresp() + * + * Checks whether the given string is a valid tagged, untagged or continuation + * response which can be processed by the response handler. + */ +static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct IMAP *imap = conn->data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + const char *id = imapc->resptag; + size_t id_len = strlen(id); + + /* Do we have a tagged command response? */ + if(len >= id_len + 1 && !memcmp(id, line, id_len) && line[id_len] == ' ') { + line += id_len + 1; + len -= id_len + 1; + + if(len >= 2 && !memcmp(line, "OK", 2)) + *resp = 'O'; + else if(len >= 2 && !memcmp(line, "NO", 2)) + *resp = 'N'; + else if(len >= 3 && !memcmp(line, "BAD", 3)) + *resp = 'B'; + else { + failf(conn->data, "Bad tagged response"); + *resp = -1; + } + + return TRUE; + } + + /* Do we have an untagged command response? */ + if(len >= 2 && !memcmp("* ", line, 2)) { + switch(imapc->state) { + /* States which are interested in untagged responses */ + case IMAP_CAPABILITY: + if(!imap_matchresp(line, len, "CAPABILITY")) + return FALSE; + break; + + case IMAP_LIST: + if((!imap->custom && !imap_matchresp(line, len, "LIST")) || + (imap->custom && !imap_matchresp(line, len, imap->custom) && + (strcmp(imap->custom, "STORE") || + !imap_matchresp(line, len, "FETCH")) && + strcmp(imap->custom, "SELECT") && + strcmp(imap->custom, "EXAMINE") && + strcmp(imap->custom, "SEARCH") && + strcmp(imap->custom, "EXPUNGE") && + strcmp(imap->custom, "LSUB") && + strcmp(imap->custom, "UID") && + strcmp(imap->custom, "NOOP"))) + return FALSE; + break; + + case IMAP_SELECT: + /* SELECT is special in that its untagged responses do not have a + common prefix so accept anything! */ + break; + + case IMAP_FETCH: + if(!imap_matchresp(line, len, "FETCH")) + return FALSE; + break; + + case IMAP_SEARCH: + if(!imap_matchresp(line, len, "SEARCH")) + return FALSE; + break; + + /* Ignore other untagged responses */ + default: + return FALSE; + } + + *resp = '*'; + return TRUE; + } + + /* Do we have a continuation response? This should be a + symbol followed by + a space and optionally some text as per RFC-3501 for the AUTHENTICATE and + APPEND commands and as outlined in Section 4. Examples of RFC-4959 but + some e-mail servers ignore this and only send a single + instead. */ + if((len == 3 && !memcmp("+", line, 1)) || + (len >= 2 && !memcmp("+ ", line, 2))) { + switch(imapc->state) { + /* States which are interested in continuation responses */ + case IMAP_AUTHENTICATE: + case IMAP_APPEND: + *resp = '+'; + break; + + default: + failf(conn->data, "Unexpected continuation response"); + *resp = -1; + break; + } + + return TRUE; + } + + return FALSE; /* Nothing for us */ +} + +/*********************************************************************** + * + * imap_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void imap_get_message(char *buffer, char** outptr) +{ + size_t len = 0; + char* message = NULL; + + /* Find the start of the message */ + for(message = buffer + 2; *message == ' ' || *message == '\t'; message++) + ; + + /* Find the end of the message */ + for(len = strlen(message); len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change IMAP state! + */ +static void state(struct connectdata *conn, imapstate newstate) +{ + struct imap_conn *imapc = &conn->proto.imapc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[]={ + "STOP", + "SERVERGREET", + "CAPABILITY", + "STARTTLS", + "UPGRADETLS", + "AUTHENTICATE", + "LOGIN", + "LIST", + "SELECT", + "FETCH", + "FETCH_FINAL", + "APPEND", + "APPEND_FINAL", + "SEARCH", + "LOGOUT", + /* LAST */ + }; + + if(imapc->state != newstate) + infof(conn->data, "IMAP %p state change from %s to %s\n", + (void *)imapc, names[imapc->state], names[newstate]); +#endif + + imapc->state = newstate; +} + +/*********************************************************************** + * + * imap_perform_capability() + * + * Sends the CAPABILITY command in order to obtain a list of server side + * supported capabilities. + */ +static CURLcode imap_perform_capability(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */ + imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */ + imapc->tls_supported = FALSE; /* Clear the TLS capability */ + + /* Send the CAPABILITY command */ + result = imap_sendf(conn, "CAPABILITY"); + + if(!result) + state(conn, IMAP_CAPABILITY); + + return result; +} + +/*********************************************************************** + * + * imap_perform_starttls() + * + * Sends the STARTTLS command to start the upgrade to TLS. + */ +static CURLcode imap_perform_starttls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the STARTTLS command */ + result = imap_sendf(conn, "STARTTLS"); + + if(!result) + state(conn, IMAP_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * imap_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode imap_perform_upgrade_tls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + /* Start the SSL connection */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); + + if(!result) { + if(imapc->state != IMAP_UPGRADETLS) + state(conn, IMAP_UPGRADETLS); + + if(imapc->ssldone) { + imap_to_imaps(conn); + result = imap_perform_capability(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * imap_perform_login() + * + * Sends a clear text LOGIN command to authenticate with. + */ +static CURLcode imap_perform_login(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + char *user; + char *passwd; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, IMAP_STOP); + + return result; + } + + /* Make sure the username and password are in the correct atom format */ + user = imap_atom(conn->user); + passwd = imap_atom(conn->passwd); + + /* Send the LOGIN command */ + result = imap_sendf(conn, "LOGIN %s %s", user ? user : "", + passwd ? passwd : ""); + + free(user); + free(passwd); + + if(!result) + state(conn, IMAP_LOGIN); + + return result; +} + +/*********************************************************************** + * + * imap_perform_authenticate() + * + * Sends an AUTHENTICATE command allowing the client to login with the given + * SASL authentication mechanism. + */ +static CURLcode imap_perform_authenticate(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + + if(initresp) { + /* Send the AUTHENTICATE command with the initial response */ + result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp); + } + else { + /* Send the AUTHENTICATE command */ + result = imap_sendf(conn, "AUTHENTICATE %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * imap_continue_authenticate() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode imap_continue_authenticate(struct connectdata *conn, + const char *resp) +{ + struct imap_conn *imapc = &conn->proto.imapc; + + return Curl_pp_sendf(&imapc->pp, "%s", resp); +} + +/*********************************************************************** + * + * imap_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism, falling back to clear text should a common + * mechanism not be available between the client and server. + */ +static CURLcode imap_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + saslprogress progress; + + /* Check we have enough data to authenticate with and end the + connect phase if we don't */ + if(!Curl_sasl_can_authenticate(&imapc->sasl, conn)) { + state(conn, IMAP_STOP); + return result; + } + + /* Calculate the SASL login details */ + result = Curl_sasl_start(&imapc->sasl, conn, imapc->ir_supported, &progress); + + if(!result) { + if(progress == SASL_INPROGRESS) + state(conn, IMAP_AUTHENTICATE); + else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) + /* Perform clear text authentication */ + result = imap_perform_login(conn); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * imap_perform_list() + * + * Sends a LIST command or an alternative custom request. + */ +static CURLcode imap_perform_list(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct IMAP *imap = data->req.protop; + char *mailbox; + + if(imap->custom) + /* Send the custom request */ + result = imap_sendf(conn, "%s%s", imap->custom, + imap->custom_params ? imap->custom_params : ""); + else { + /* Make sure the mailbox is in the correct atom format */ + mailbox = imap_atom(imap->mailbox ? imap->mailbox : ""); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the LIST command */ + result = imap_sendf(conn, "LIST \"%s\" *", mailbox); + + free(mailbox); + } + + if(!result) + state(conn, IMAP_LIST); + + return result; +} + +/*********************************************************************** + * + * imap_perform_select() + * + * Sends a SELECT command to ask the server to change the selected mailbox. + */ +static CURLcode imap_perform_select(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct IMAP *imap = data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + char *mailbox; + + /* Invalidate old information as we are switching mailboxes */ + Curl_safefree(imapc->mailbox); + Curl_safefree(imapc->mailbox_uidvalidity); + + /* Check we have a mailbox */ + if(!imap->mailbox) { + failf(conn->data, "Cannot SELECT without a mailbox."); + return CURLE_URL_MALFORMAT; + } + + /* Make sure the mailbox is in the correct atom format */ + mailbox = imap_atom(imap->mailbox); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the SELECT command */ + result = imap_sendf(conn, "SELECT %s", mailbox); + + free(mailbox); + + if(!result) + state(conn, IMAP_SELECT); + + return result; +} + +/*********************************************************************** + * + * imap_perform_fetch() + * + * Sends a FETCH command to initiate the download of a message. + */ +static CURLcode imap_perform_fetch(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct IMAP *imap = conn->data->req.protop; + + /* Check we have a UID */ + if(!imap->uid) { + failf(conn->data, "Cannot FETCH without a UID."); + return CURLE_URL_MALFORMAT; + } + + /* Send the FETCH command */ + if(imap->partial) + result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>", + imap->uid, + imap->section ? imap->section : "", + imap->partial); + else + result = imap_sendf(conn, "FETCH %s BODY[%s]", + imap->uid, + imap->section ? imap->section : ""); + + if(!result) + state(conn, IMAP_FETCH); + + return result; +} + +/*********************************************************************** + * + * imap_perform_append() + * + * Sends an APPEND command to initiate the upload of a message. + */ +static CURLcode imap_perform_append(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct IMAP *imap = conn->data->req.protop; + char *mailbox; + + /* Check we have a mailbox */ + if(!imap->mailbox) { + failf(conn->data, "Cannot APPEND without a mailbox."); + return CURLE_URL_MALFORMAT; + } + + /* Check we know the size of the upload */ + if(conn->data->state.infilesize < 0) { + failf(conn->data, "Cannot APPEND with unknown input file size\n"); + return CURLE_UPLOAD_FAILED; + } + + /* Make sure the mailbox is in the correct atom format */ + mailbox = imap_atom(imap->mailbox); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the APPEND command */ + result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", + mailbox, conn->data->state.infilesize); + + free(mailbox); + + if(!result) + state(conn, IMAP_APPEND); + + return result; +} + +/*********************************************************************** + * + * imap_perform_search() + * + * Sends a SEARCH command. + */ +static CURLcode imap_perform_search(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct IMAP *imap = conn->data->req.protop; + + /* Check we have a query string */ + if(!imap->query) { + failf(conn->data, "Cannot SEARCH without a query string."); + return CURLE_URL_MALFORMAT; + } + + /* Send the SEARCH command */ + result = imap_sendf(conn, "SEARCH %s", imap->query); + + if(!result) + state(conn, IMAP_SEARCH); + + return result; +} + +/*********************************************************************** + * + * imap_perform_logout() + * + * Performs the logout action prior to sclose() being called. + */ +static CURLcode imap_perform_logout(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the LOGOUT command */ + result = imap_sendf(conn, "LOGOUT"); + + if(!result) + state(conn, IMAP_LOGOUT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode imap_state_servergreet_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != 'O') { + failf(data, "Got unexpected imap-server response"); + result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */ + } + else + result = imap_perform_capability(conn); + + return result; +} + +/* For CAPABILITY responses */ +static CURLcode imap_state_capability_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + const char *line = data->state.buffer; + size_t wordlen; + + (void)instate; /* no use for this yet */ + + /* Do we have a untagged response? */ + if(imapcode == '*') { + line += 2; + + /* Loop through the data line */ + for(;;) { + while(*line && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + } + + if(!*line) + break; + + /* Extract the word */ + for(wordlen = 0; line[wordlen] && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Does the server support the STARTTLS capability? */ + if(wordlen == 8 && !memcmp(line, "STARTTLS", 8)) + imapc->tls_supported = TRUE; + + /* Has the server explicitly disabled clear text authentication? */ + else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13)) + imapc->login_disabled = TRUE; + + /* Does the server support the SASL-IR capability? */ + else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7)) + imapc->ir_supported = TRUE; + + /* Do we have a SASL based authentication mechanism? */ + else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { + size_t llen; + unsigned int mechbit; + + line += 5; + wordlen -= 5; + + /* Test the word for a matching authentication mechanism */ + if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) && + llen == wordlen) + imapc->sasl.authmechs |= mechbit; + } + + line += wordlen; + } + } + else if(imapcode == 'O') { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(imapc->tls_supported) + /* Switch to TLS connection now */ + result = imap_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = imap_perform_authentication(conn); + else { + failf(data, "STARTTLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = imap_perform_authentication(conn); + } + else + result = imap_perform_authentication(conn); + + return result; +} + +/* For STARTTLS responses */ +static CURLcode imap_state_starttls_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != 'O') { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied. %c", imapcode); + result = CURLE_USE_SSL_FAILED; + } + else + result = imap_perform_authentication(conn); + } + else + result = imap_perform_upgrade_tls(conn); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode imap_state_auth_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&imapc->sasl, conn, imapcode, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, IMAP_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ + if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) + /* Perform clear text authentication */ + result = imap_perform_login(conn); + else { + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + } + break; + default: + break; + } + + return result; +} + +/* For LOGIN responses */ +static CURLcode imap_state_login_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != 'O') { + failf(data, "Access denied. %c", imapcode); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For LIST responses */ +static CURLcode imap_state_list_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + char *line = conn->data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* No use for this yet */ + + if(imapcode == '*') { + /* Temporarily add the LF character back and send as body to the client */ + line[len] = '\n'; + result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + line[len] = '\0'; + } + else if(imapcode != 'O') + result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */ + else + /* End of DO phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For SELECT responses */ +static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct IMAP *imap = conn->data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + const char *line = data->state.buffer; + char tmp[20]; + + (void)instate; /* no use for this yet */ + + if(imapcode == '*') { + /* See if this is an UIDVALIDITY response */ + if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) { + Curl_safefree(imapc->mailbox_uidvalidity); + imapc->mailbox_uidvalidity = strdup(tmp); + } + } + else if(imapcode == 'O') { + /* Check if the UIDVALIDITY has been specified and matches */ + if(imap->uidvalidity && imapc->mailbox_uidvalidity && + strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)) { + failf(conn->data, "Mailbox UIDVALIDITY has changed"); + result = CURLE_REMOTE_FILE_NOT_FOUND; + } + else { + /* Note the currently opened mailbox on this connection */ + imapc->mailbox = strdup(imap->mailbox); + + if(imap->custom) + result = imap_perform_list(conn); + else if(imap->query) + result = imap_perform_search(conn); + else + result = imap_perform_fetch(conn); + } + } + else { + failf(data, "Select failed"); + result = CURLE_LOGIN_DENIED; + } + + return result; +} + +/* For the (first line of the) FETCH responses */ +static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + const char *ptr = data->state.buffer; + bool parsed = FALSE; + curl_off_t size; + + (void)instate; /* no use for this yet */ + + if(imapcode != '*') { + Curl_pgrsSetDownloadSize(data, -1); + state(conn, IMAP_STOP); + return CURLE_REMOTE_FILE_NOT_FOUND; /* TODO: Fix error code */ + } + + /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse + the continuation data contained within the curly brackets */ + while(*ptr && (*ptr != '{')) + ptr++; + + if(*ptr == '{') { + char *endptr; + size = curlx_strtoofft(ptr + 1, &endptr, 10); + if(endptr - ptr > 1 && endptr[0] == '}' && + endptr[1] == '\r' && endptr[2] == '\0') + parsed = TRUE; + } + + if(parsed) { + infof(data, "Found %" CURL_FORMAT_CURL_OFF_TU " bytes to download\n", + size); + Curl_pgrsSetDownloadSize(data, size); + + if(pp->cache) { + /* At this point there is a bunch of data in the header "cache" that is + actually body content, send it as body and then skip it. Do note + that there may even be additional "headers" after the body. */ + size_t chunk = pp->cache_size; + + if(chunk > (size_t)size) + /* The conversion from curl_off_t to size_t is always fine here */ + chunk = (size_t)size; + + result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk); + if(result) + return result; + + data->req.bytecount += chunk; + + infof(data, "Written %" CURL_FORMAT_CURL_OFF_TU + " bytes, %" CURL_FORMAT_CURL_OFF_TU + " bytes are left for transfer\n", (curl_off_t)chunk, + size - chunk); + + /* Have we used the entire cache or just part of it?*/ + if(pp->cache_size > chunk) { + /* Only part of it so shrink the cache to fit the trailing data */ + memmove(pp->cache, pp->cache + chunk, pp->cache_size - chunk); + pp->cache_size -= chunk; + } + else { + /* Free the cache */ + Curl_safefree(pp->cache); + + /* Reset the cache size */ + pp->cache_size = 0; + } + } + + if(data->req.bytecount == size) + /* The entire data is already transferred! */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + else { + /* IMAP download */ + data->req.maxdownload = size; + Curl_setup_transfer(conn, FIRSTSOCKET, size, FALSE, NULL, -1, NULL); + } + } + else { + /* We don't know how to parse this line */ + failf(pp->conn->data, "Failed to parse FETCH response."); + result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */ + } + + /* End of DO phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For final FETCH responses performed after the download */ +static CURLcode imap_state_fetch_final_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* No use for this yet */ + + if(imapcode != 'O') + result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: Fix error code */ + else + /* End of DONE phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For APPEND responses */ +static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* No use for this yet */ + + if(imapcode != '+') { + result = CURLE_UPLOAD_FAILED; + } + else { + /* Set the progress upload size */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* IMAP upload */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + + /* End of DO phase */ + state(conn, IMAP_STOP); + } + + return result; +} + +/* For final APPEND responses performed after the upload */ +static CURLcode imap_state_append_final_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* No use for this yet */ + + if(imapcode != 'O') + result = CURLE_UPLOAD_FAILED; + else + /* End of DONE phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For SEARCH responses */ +static CURLcode imap_state_search_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + char *line = conn->data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* No use for this yet */ + + if(imapcode == '*') { + /* Temporarily add the LF character back and send as body to the client */ + line[len] = '\n'; + result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + line[len] = '\0'; + } + else if(imapcode != 'O') + result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */ + else + /* End of DO phase */ + state(conn, IMAP_STOP); + + return result; +} + +static CURLcode imap_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int imapcode; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */ + if(imapc->state == IMAP_UPGRADETLS) + return imap_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &imapcode, &nread); + if(result) + return result; + + /* Was there an error parsing the response line? */ + if(imapcode == -1) + return CURLE_FTP_WEIRD_SERVER_REPLY; + + if(!imapcode) + break; + + /* We have now received a full IMAP server response */ + switch(imapc->state) { + case IMAP_SERVERGREET: + result = imap_state_servergreet_resp(conn, imapcode, imapc->state); + break; + + case IMAP_CAPABILITY: + result = imap_state_capability_resp(conn, imapcode, imapc->state); + break; + + case IMAP_STARTTLS: + result = imap_state_starttls_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE: + result = imap_state_auth_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LOGIN: + result = imap_state_login_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LIST: + result = imap_state_list_resp(conn, imapcode, imapc->state); + break; + + case IMAP_SELECT: + result = imap_state_select_resp(conn, imapcode, imapc->state); + break; + + case IMAP_FETCH: + result = imap_state_fetch_resp(conn, imapcode, imapc->state); + break; + + case IMAP_FETCH_FINAL: + result = imap_state_fetch_final_resp(conn, imapcode, imapc->state); + break; + + case IMAP_APPEND: + result = imap_state_append_resp(conn, imapcode, imapc->state); + break; + + case IMAP_APPEND_FINAL: + result = imap_state_append_final_resp(conn, imapcode, imapc->state); + break; + + case IMAP_SEARCH: + result = imap_state_search_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LOGOUT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, IMAP_STOP); + break; + } + } while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); + if(result || !imapc->ssldone) + return result; + } + + result = Curl_pp_statemach(&imapc->pp, FALSE); + *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode imap_block_statemach(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + while(imapc->state != IMAP_STOP && !result) + result = Curl_pp_statemach(&imapc->pp, TRUE); + + return result; +} + +/* Allocate and initialize the struct IMAP for the current SessionHandle if + required */ +static CURLcode imap_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct IMAP *imap; + + imap = data->req.protop = calloc(sizeof(struct IMAP), 1); + if(!imap) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the IMAP "protocol connect" and "doing" phases only */ +static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks); +} + +/*********************************************************************** + * + * imap_connect() + * + * This function should do everything that is to be considered a part of the + * connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + */ +static CURLcode imap_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in IMAP */ + connkeep(conn, "IMAP default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = imap_statemach_act; + pp->endofresp = imap_endofresp; + pp->conn = conn; + + /* Set the default preferred authentication type and mechanism */ + imapc->preftype = IMAP_TYPE_ANY; + Curl_sasl_init(&imapc->sasl, &saslimap); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = imap_parse_url_options(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, IMAP_SERVERGREET); + + /* Start off with an response id of '*' */ + strcpy(imapc->resptag, "*"); + + result = imap_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * imap_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode imap_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct IMAP *imap = data->req.protop; + + (void)premature; + + if(!imap) + /* When the easy handle is removed from the multi interface while libcurl + is still trying to resolve the host name, the IMAP struct is not yet + initialized. However, the removal action calls Curl_done() which in + turn calls this function, so we simply return success. */ + return CURLE_OK; + + if(status) { + connclose(conn, "IMAP done with bad status"); /* marked for closure */ + result = status; /* use the already set error code */ + } + else if(!data->set.connect_only && !imap->custom && + (imap->uid || data->set.upload)) { + /* Handle responses after FETCH or APPEND transfer has finished */ + if(!data->set.upload) + state(conn, IMAP_FETCH_FINAL); + else { + /* End the APPEND command first by sending an empty line */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", ""); + if(!result) + state(conn, IMAP_APPEND_FINAL); + } + + /* Run the state-machine + + TODO: when the multi interface is used, this _really_ should be using + the imap_multi_statemach function but we have no general support for + non-blocking DONE operations, not in the multi state machine and with + Curl_done() invokes on several places in the code! + */ + if(!result) + result = imap_block_statemach(conn); + } + + /* Cleanup our per-request based variables */ + Curl_safefree(imap->mailbox); + Curl_safefree(imap->uidvalidity); + Curl_safefree(imap->uid); + Curl_safefree(imap->section); + Curl_safefree(imap->partial); + Curl_safefree(imap->query); + Curl_safefree(imap->custom); + Curl_safefree(imap->custom_params); + + /* Clear the transfer mode for the next request */ + imap->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * imap_perform() + * + * This is the actual DO function for IMAP. Fetch or append a message, or do + * other things according to the options previously setup. + */ +static CURLcode imap_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is IMAP and no proxy */ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct IMAP *imap = data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + bool selected = FALSE; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* Requested no body means no transfer */ + imap->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Determine if the requested mailbox (with the same UIDVALIDITY if set) + has already been selected on this connection */ + if(imap->mailbox && imapc->mailbox && + !strcmp(imap->mailbox, imapc->mailbox) && + (!imap->uidvalidity || !imapc->mailbox_uidvalidity || + !strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity))) + selected = TRUE; + + /* Start the first command in the DO phase */ + if(conn->data->set.upload) + /* APPEND can be executed directly */ + result = imap_perform_append(conn); + else if(imap->custom && (selected || !imap->mailbox)) + /* Custom command using the same mailbox or no mailbox */ + result = imap_perform_list(conn); + else if(!imap->custom && selected && imap->uid) + /* FETCH from the same mailbox */ + result = imap_perform_fetch(conn); + else if(!imap->custom && selected && imap->query) + /* SEARCH the current mailbox */ + result = imap_perform_search(conn); + else if(imap->mailbox && !selected && + (imap->custom || imap->uid || imap->query)) + /* SELECT the mailbox */ + result = imap_perform_select(conn); + else + /* LIST */ + result = imap_perform_list(conn); + + if(result) + return result; + + /* Run the state-machine */ + result = imap_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * imap_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (imap_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode imap_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the URL path */ + result = imap_parse_url_path(conn); + if(result) + return result; + + /* Parse the custom request */ + result = imap_parse_custom_request(conn); + if(result) + return result; + + result = imap_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * imap_disconnect() + * + * Disconnect from an IMAP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct imap_conn *imapc = &conn->proto.imapc; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The IMAP session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart) + if(!imap_perform_logout(conn)) + (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&imapc->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, imapc->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(imapc->mailbox); + Curl_safefree(imapc->mailbox_uidvalidity); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) +{ + struct IMAP *imap = conn->data->req.protop; + + (void)connected; + + if(imap->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = imap_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = imap_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * imap_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode imap_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct SessionHandle *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = imap_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = imap_dophase_done(conn, connected); + + return result; +} + +static CURLcode imap_setup_connection(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + + /* Initialise the IMAP layer */ + CURLcode result = imap_init(conn); + if(result) + return result; + + if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { + /* Unless we have asked to tunnel IMAP operations through the proxy, we + switch and use HTTP operations only */ +#ifndef CURL_DISABLE_HTTP + if(conn->handler == &Curl_handler_imap) + conn->handler = &Curl_handler_imap_proxy; + else { +#ifdef USE_SSL + conn->handler = &Curl_handler_imaps_proxy; +#else + failf(data, "IMAPS not supported!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + + /* set it up as an HTTP connection instead */ + return conn->handler->setup_connection(conn); +#else + failf(data, "IMAP over http proxy requires HTTP support built-in!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + + data->state.path++; /* don't include the initial slash */ + + return CURLE_OK; +} + +/*********************************************************************** + * + * imap_sendf() + * + * Sends the formated string as an IMAP command to the server. + * + * Designed to never block. + */ +static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + char *taggedfmt; + va_list ap; + + DEBUGASSERT(fmt); + + /* Calculate the next command ID wrapping at 3 digits */ + imapc->cmdid = (imapc->cmdid + 1) % 1000; + + /* Calculate the tag based on the connection ID and command ID */ + snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d", + 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid); + + /* Prefix the format with the tag */ + taggedfmt = aprintf("%s %s", imapc->resptag, fmt); + if(!taggedfmt) + return CURLE_OUT_OF_MEMORY; + + /* Send the data with the tag */ + va_start(ap, fmt); + result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap); + va_end(ap); + + free(taggedfmt); + + return result; +} + +/*********************************************************************** + * + * imap_atom() + * + * Checks the input string for characters that need escaping and returns an + * atom ready for sending to the server. + * + * The returned string needs to be freed. + * + */ +static char *imap_atom(const char *str) +{ + const char *p1; + char *p2; + size_t backsp_count = 0; + size_t quote_count = 0; + bool space_exists = FALSE; + size_t newlen = 0; + char *newstr = NULL; + + if(!str) + return NULL; + + /* Count any unescaped characters */ + p1 = str; + while(*p1) { + if(*p1 == '\\') + backsp_count++; + else if(*p1 == '"') + quote_count++; + else if(*p1 == ' ') + space_exists = TRUE; + + p1++; + } + + /* Does the input contain any unescaped characters? */ + if(!backsp_count && !quote_count && !space_exists) + return strdup(str); + + /* Calculate the new string length */ + newlen = strlen(str) + backsp_count + quote_count + (space_exists ? 2 : 0); + + /* Allocate the new string */ + newstr = (char *) malloc((newlen + 1) * sizeof(char)); + if(!newstr) + return NULL; + + /* Surround the string in quotes if necessary */ + p2 = newstr; + if(space_exists) { + newstr[0] = '"'; + newstr[newlen - 1] = '"'; + p2++; + } + + /* Copy the string, escaping backslash and quote characters along the way */ + p1 = str; + while(*p1) { + if(*p1 == '\\' || *p1 == '"') { + *p2 = '\\'; + p2++; + } + + *p2 = *p1; + + p1++; + p2++; + } + + /* Terminate the string */ + newstr[newlen] = '\0'; + + return newstr; +} + +/*********************************************************************** + * + * imap_is_bchar() + * + * Portable test of whether the specified char is a "bchar" as defined in the + * grammar of RFC-5092. + */ +static bool imap_is_bchar(char ch) +{ + switch(ch) { + /* bchar */ + case ':': case '@': case '/': + /* bchar -> achar */ + case '&': case '=': + /* bchar -> achar -> uchar -> unreserved */ + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': + case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': + case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': + case 'V': case 'W': case 'X': case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': + case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': + case 'v': case 'w': case 'x': case 'y': case 'z': + case '-': case '.': case '_': case '~': + /* bchar -> achar -> uchar -> sub-delims-sh */ + case '!': case '$': case '\'': case '(': case ')': case '*': + case '+': case ',': + /* bchar -> achar -> uchar -> pct-encoded */ + case '%': /* HEXDIG chars are already included above */ + return true; + + default: + return false; + } +} + +/*********************************************************************** + * + * imap_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode imap_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + const char *ptr = conn->options; + + imapc->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strnequal(key, "AUTH=", 5)) + result = Curl_sasl_parse_url_auth_option(&imapc->sasl, + value, ptr - value); + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + switch(imapc->sasl.prefmech) { + case SASL_AUTH_NONE: + imapc->preftype = IMAP_TYPE_NONE; + break; + case SASL_AUTH_DEFAULT: + imapc->preftype = IMAP_TYPE_ANY; + break; + default: + imapc->preftype = IMAP_TYPE_SASL; + break; + } + + return result; +} + +/*********************************************************************** + * + * imap_parse_url_path() + * + * Parse the URL path into separate path components. + * + */ +static CURLcode imap_parse_url_path(struct connectdata *conn) +{ + /* The imap struct is already initialised in imap_connect() */ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct IMAP *imap = data->req.protop; + const char *begin = data->state.path; + const char *ptr = begin; + + /* See how much of the URL is a valid path and decode it */ + while(imap_is_bchar(*ptr)) + ptr++; + + if(ptr != begin) { + /* Remove the trailing slash if present */ + const char *end = ptr; + if(end > begin && end[-1] == '/') + end--; + + result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL, + TRUE); + if(result) + return result; + } + else + imap->mailbox = NULL; + + /* There can be any number of parameters in the form ";NAME=VALUE" */ + while(*ptr == ';') { + char *name; + char *value; + size_t valuelen; + + /* Find the length of the name parameter */ + begin = ++ptr; + while(*ptr && *ptr != '=') + ptr++; + + if(!*ptr) + return CURLE_URL_MALFORMAT; + + /* Decode the name parameter */ + result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE); + if(result) + return result; + + /* Find the length of the value parameter */ + begin = ++ptr; + while(imap_is_bchar(*ptr)) + ptr++; + + /* Decode the value parameter */ + result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE); + if(result) { + free(name); + return result; + } + + DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value)); + + /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and + PARTIAL) stripping of the trailing slash character if it is present. + + Note: Unknown parameters trigger a URL_MALFORMAT error. */ + if(Curl_raw_equal(name, "UIDVALIDITY") && !imap->uidvalidity) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->uidvalidity = value; + value = NULL; + } + else if(Curl_raw_equal(name, "UID") && !imap->uid) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->uid = value; + value = NULL; + } + else if(Curl_raw_equal(name, "SECTION") && !imap->section) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->section = value; + value = NULL; + } + else if(Curl_raw_equal(name, "PARTIAL") && !imap->partial) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->partial = value; + value = NULL; + } + else { + free(name); + free(value); + + return CURLE_URL_MALFORMAT; + } + + free(name); + free(value); + } + + /* Does the URL contain a query parameter? Only valid when we have a mailbox + and no UID as per RFC-5092 */ + if(imap->mailbox && !imap->uid && *ptr == '?') { + /* Find the length of the query parameter */ + begin = ++ptr; + while(imap_is_bchar(*ptr)) + ptr++; + + /* Decode the query parameter */ + result = Curl_urldecode(data, begin, ptr - begin, &imap->query, NULL, + TRUE); + if(result) + return result; + } + + /* Any extra stuff at the end of the URL is an error */ + if(*ptr) + return CURLE_URL_MALFORMAT; + + return CURLE_OK; +} + +/*********************************************************************** + * + * imap_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode imap_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct IMAP *imap = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + if(custom) { + /* URL decode the custom request */ + result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE); + + /* Extract the parameters if specified */ + if(!result) { + const char *params = imap->custom; + + while(*params && *params != ' ') + params++; + + if(*params) { + imap->custom_params = strdup(params); + imap->custom[params - imap->custom] = '\0'; + + if(!imap->custom_params) + result = CURLE_OUT_OF_MEMORY; + } + } + } + + return result; +} + +#endif /* CURL_DISABLE_IMAP */ diff --git a/libcurl/src/lib/imap.h b/libcurl/src/lib/imap.h new file mode 100644 index 0000000..3189daa --- /dev/null +++ b/libcurl/src/lib/imap.h @@ -0,0 +1,96 @@ +#ifndef HEADER_CURL_IMAP_H +#define HEADER_CURL_IMAP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * IMAP unique setup + ***************************************************************************/ +typedef enum { + IMAP_STOP, /* do nothing state, stops the state machine */ + IMAP_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + IMAP_CAPABILITY, + IMAP_STARTTLS, + IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + IMAP_AUTHENTICATE, + IMAP_LOGIN, + IMAP_LIST, + IMAP_SELECT, + IMAP_FETCH, + IMAP_FETCH_FINAL, + IMAP_APPEND, + IMAP_APPEND_FINAL, + IMAP_SEARCH, + IMAP_LOGOUT, + IMAP_LAST /* never used */ +} imapstate; + +/* This IMAP struct is used in the SessionHandle. All IMAP data that is + connection-oriented must be in imap_conn to properly deal with the fact that + perhaps the SessionHandle is changed between the times the connection is + used. */ +struct IMAP { + curl_pp_transfer transfer; + char *mailbox; /* Mailbox to select */ + char *uidvalidity; /* UIDVALIDITY to check in select */ + char *uid; /* Message UID to fetch */ + char *section; /* Message SECTION to fetch */ + char *partial; /* Message PARTIAL to fetch */ + char *query; /* Query to search for */ + char *custom; /* Custom request */ + char *custom_params; /* Parameters for the custom request */ +}; + +/* imap_conn is used for struct connection-oriented data in the connectdata + struct */ +struct imap_conn { + struct pingpong pp; + imapstate state; /* Always use imap.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + struct SASL sasl; /* SASL-related parameters */ + unsigned int preftype; /* Preferred authentication type */ + int cmdid; /* Last used command ID */ + char resptag[5]; /* Response tag to wait for */ + bool tls_supported; /* StartTLS capability supported by server */ + bool login_disabled; /* LOGIN command disabled by server */ + bool ir_supported; /* Initial response supported by server */ + char *mailbox; /* The last selected mailbox */ + char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */ +}; + +extern const struct Curl_handler Curl_handler_imap; +extern const struct Curl_handler Curl_handler_imaps; + +/* Authentication type flags */ +#define IMAP_TYPE_CLEARTEXT (1 << 0) +#define IMAP_TYPE_SASL (1 << 1) + +/* Authentication type values */ +#define IMAP_TYPE_NONE 0 +#define IMAP_TYPE_ANY ~0U + +#endif /* HEADER_CURL_IMAP_H */ diff --git a/libcurl/src/lib/inet_ntop.c b/libcurl/src/lib/inet_ntop.c new file mode 100644 index 0000000..daf9c1c --- /dev/null +++ b/libcurl/src/lib/inet_ntop.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Original code by Paul Vixie. "curlified" by Gisle Vanem. + */ + +#include "curl_setup.h" + +#ifndef HAVE_INET_NTOP + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "curl_printf.h" + +#include "inet_ntop.h" + +#define IN6ADDRSZ 16 +#define INADDRSZ 4 +#define INT16SZ 2 + +/* + * Format an IPv4 address, more or less like inet_ntoa(). + * + * Returns `dst' (as a const) + * Note: + * - uses no statics + * - takes a unsigned char* not an in_addr as input + */ +static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size) +{ + char tmp[sizeof "255.255.255.255"]; + size_t len; + + DEBUGASSERT(size >= 16); + + tmp[0] = '\0'; + (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", + ((int)((unsigned char)src[0])) & 0xff, + ((int)((unsigned char)src[1])) & 0xff, + ((int)((unsigned char)src[2])) & 0xff, + ((int)((unsigned char)src[3])) & 0xff); + + len = strlen(tmp); + if(len == 0 || len >= size) { + SET_ERRNO(ENOSPC); + return (NULL); + } + strcpy(dst, tmp); + return dst; +} + +#ifdef ENABLE_IPV6 +/* + * Convert IPv6 binary address into presentation (printable) format. + */ +static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + char *tp; + struct { + long base; + long len; + } best, cur; + unsigned long words[IN6ADDRSZ / INT16SZ]; + int i; + + /* Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof(words)); + for(i = 0; i < IN6ADDRSZ; i++) + words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); + + best.base = -1; + cur.base = -1; + best.len = 0; + cur.len = 0; + + for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if(words[i] == 0) { + if(cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } + else if(cur.base != -1) { + if(best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + if((cur.base != -1) && (best.base == -1 || cur.len > best.len)) + best = cur; + if(best.base != -1 && best.len < 2) + best.base = -1; + /* Format the result. */ + tp = tmp; + for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if(best.base != -1 && i >= best.base && i < (best.base + best.len)) { + if(i == best.base) + *tp++ = ':'; + continue; + } + + /* Are we following an initial run of 0x00s or any real hex? + */ + if(i != 0) + *tp++ = ':'; + + /* Is this address an encapsulated IPv4? + */ + if(i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) { + SET_ERRNO(ENOSPC); + return (NULL); + } + tp += strlen(tp); + break; + } + tp += snprintf(tp, 5, "%lx", words[i]); + } + + /* Was it a trailing run of 0x00's? + */ + if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* Check for overflow, copy, and we're done. + */ + if((size_t)(tp - tmp) > size) { + SET_ERRNO(ENOSPC); + return (NULL); + } + strcpy(dst, tmp); + return dst; +} +#endif /* ENABLE_IPV6 */ + +/* + * Convert a network format address to presentation format. + * + * Returns pointer to presentation format address (`buf'). + * Returns NULL on error and errno set with the specific + * error, EAFNOSUPPORT or ENOSPC. + * + * On Windows we store the error in the thread errno, not + * in the winsock error code. This is to avoid losing the + * actual last winsock error. So use macro ERRNO to fetch the + * errno this function sets when returning NULL, not SOCKERRNO. + */ +CURL_STATIC char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size) +{ + switch (af) { + case AF_INET: + return inet_ntop4((const unsigned char*)src, buf, size); +#ifdef ENABLE_IPV6 + case AF_INET6: + return inet_ntop6((const unsigned char*)src, buf, size); +#endif + default: + SET_ERRNO(EAFNOSUPPORT); + return NULL; + } +} +#endif /* HAVE_INET_NTOP */ diff --git a/libcurl/src/lib/inet_ntop.h b/libcurl/src/lib/inet_ntop.h new file mode 100644 index 0000000..68e393a --- /dev/null +++ b/libcurl/src/lib/inet_ntop.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_INET_NTOP_H +#define HEADER_CURL_INET_NTOP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +CURL_STATIC char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size); + +#ifdef HAVE_INET_NTOP +#ifdef HAVE_ARPA_INET_H +#include +#endif +#define Curl_inet_ntop(af,addr,buf,size) \ + inet_ntop(af, addr, buf, (curl_socklen_t)size) +#endif + +#endif /* HEADER_CURL_INET_NTOP_H */ + diff --git a/libcurl/src/lib/inet_pton.c b/libcurl/src/lib/inet_pton.c new file mode 100644 index 0000000..5556b30 --- /dev/null +++ b/libcurl/src/lib/inet_pton.c @@ -0,0 +1,234 @@ +/* This is from the BIND 4.9.4 release, modified to compile by itself */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "curl_setup.h" + +#ifndef HAVE_INET_PTON + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "inet_pton.h" + +#define IN6ADDRSZ 16 +#define INADDRSZ 4 +#define INT16SZ 2 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4(const char *src, unsigned char *dst); +#ifdef ENABLE_IPV6 +static int inet_pton6(const char *src, unsigned char *dst); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * notice: + * On Windows we store the error in the thread errno, not + * in the winsock error code. This is to avoid losing the + * actual last winsock error. So use macro ERRNO to fetch the + * errno this function sets when returning (-1), not SOCKERRNO. + * author: + * Paul Vixie, 1996. + */ +CURL_STATIC int +Curl_inet_pton(int af, const char *src, void *dst) +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, (unsigned char *)dst)); +#ifdef ENABLE_IPV6 + case AF_INET6: + return (inet_pton6(src, (unsigned char *)dst)); +#endif + default: + SET_ERRNO(EAFNOSUPPORT); + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, unsigned char *dst) +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + tp = tmp; + *tp = 0; + while((ch = *src++) != '\0') { + const char *pch; + + if((pch = strchr(digits, ch)) != NULL) { + unsigned int val = *tp * 10 + (unsigned int)(pch - digits); + + if(saw_digit && *tp == 0) + return (0); + if(val > 255) + return (0); + *tp = (unsigned char)val; + if(! saw_digit) { + if(++octets > 4) + return (0); + saw_digit = 1; + } + } + else if(ch == '.' && saw_digit) { + if(octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } + else + return (0); + } + if(octets < 4) + return (0); + memcpy(dst, tmp, INADDRSZ); + return (1); +} + +#ifdef ENABLE_IPV6 +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(const char *src, unsigned char *dst) +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + size_t val; + + memset((tp = tmp), 0, IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if(*src == ':') + if(*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while((ch = *src++) != '\0') { + const char *pch; + + if((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if(pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if(++saw_xdigit > 4) + return (0); + continue; + } + if(ch == ':') { + curtok = src; + if(!saw_xdigit) { + if(colonp) + return (0); + colonp = tp; + continue; + } + if(tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if(ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if(saw_xdigit) { + if(tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if(colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const ssize_t n = tp - colonp; + ssize_t i; + + if(tp == endp) + return (0); + for(i = 1; i <= n; i++) { + *(endp - i) = *(colonp + n - i); + *(colonp + n - i) = 0; + } + tp = endp; + } + if(tp != endp) + return (0); + memcpy(dst, tmp, IN6ADDRSZ); + return (1); +} +#endif /* ENABLE_IPV6 */ + +#endif /* HAVE_INET_PTON */ diff --git a/libcurl/src/lib/inet_pton.h b/libcurl/src/lib/inet_pton.h new file mode 100644 index 0000000..a17b001 --- /dev/null +++ b/libcurl/src/lib/inet_pton.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_INET_PTON_H +#define HEADER_CURL_INET_PTON_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +CURL_STATIC int Curl_inet_pton(int, const char *, void *); + +#ifdef HAVE_INET_PTON +#ifdef HAVE_ARPA_INET_H +#include +#endif +#define Curl_inet_pton(x,y,z) inet_pton(x,y,z) +#endif + +#endif /* HEADER_CURL_INET_PTON_H */ + diff --git a/libcurl/src/lib/krb5.c b/libcurl/src/lib/krb5.c new file mode 100644 index 0000000..4c5b78f --- /dev/null +++ b/libcurl/src/lib/krb5.c @@ -0,0 +1,332 @@ +/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c + * + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Hgskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Copyright (c) 2004 - 2015 Daniel Stenberg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_FTP) + +#ifdef HAVE_NETDB_H +#include +#endif + +#include "urldata.h" +#include "curl_base64.h" +#include "ftp.h" +#include "curl_gssapi.h" +#include "sendf.h" +#include "curl_sec.h" +#include "warnless.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define LOCAL_ADDR (&conn->local_addr) +#define REMOTE_ADDR conn->ip_addr->ai_addr + +static int +krb5_init(void *app_data) +{ + gss_ctx_id_t *context = app_data; + /* Make sure our context is initialized for krb5_end. */ + *context = GSS_C_NO_CONTEXT; + return 0; +} + +static int +krb5_check_prot(void *app_data, int level) +{ + (void)app_data; /* unused */ + if(level == PROT_CONFIDENTIAL) + return -1; + return 0; +} + +static int +krb5_decode(void *app_data, void *buf, int len, + int level UNUSED_PARAM, + struct connectdata *conn UNUSED_PARAM) +{ + gss_ctx_id_t *context = app_data; + OM_uint32 maj, min; + gss_buffer_desc enc, dec; + + (void)level; + (void)conn; + + enc.value = buf; + enc.length = len; + maj = gss_unseal(&min, *context, &enc, &dec, NULL, NULL); + if(maj != GSS_S_COMPLETE) { + if(len >= 4) + strcpy(buf, "599 "); + return -1; + } + + memcpy(buf, dec.value, dec.length); + len = curlx_uztosi(dec.length); + gss_release_buffer(&min, &dec); + + return len; +} + +static int +krb5_overhead(void *app_data, int level, int len) +{ + /* no arguments are used */ + (void)app_data; + (void)level; + (void)len; + return 0; +} + +static int +krb5_encode(void *app_data, const void *from, int length, int level, void **to) +{ + gss_ctx_id_t *context = app_data; + gss_buffer_desc dec, enc; + OM_uint32 maj, min; + int state; + int len; + + /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal + * libraries modify the input buffer in gss_seal() + */ + dec.value = (void*)from; + dec.length = length; + maj = gss_seal(&min, *context, + level == PROT_PRIVATE, + GSS_C_QOP_DEFAULT, + &dec, &state, &enc); + + if(maj != GSS_S_COMPLETE) + return -1; + + /* malloc a new buffer, in case gss_release_buffer doesn't work as + expected */ + *to = malloc(enc.length); + if(!*to) + return -1; + memcpy(*to, enc.value, enc.length); + len = curlx_uztosi(enc.length); + gss_release_buffer(&min, &enc); + return len; +} + +static int +krb5_auth(void *app_data, struct connectdata *conn) +{ + int ret = AUTH_OK; + char *p; + const char *host = conn->host.name; + ssize_t nread; + curl_socklen_t l = sizeof(conn->local_addr); + struct SessionHandle *data = conn->data; + CURLcode result; + const char *service = "ftp", *srv_host = "host"; + gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp; + OM_uint32 maj, min; + gss_name_t gssname; + gss_ctx_id_t *context = app_data; + struct gss_channel_bindings_struct chan; + size_t base64_sz = 0; + + if(getsockname(conn->sock[FIRSTSOCKET], + (struct sockaddr *)LOCAL_ADDR, &l) < 0) + perror("getsockname()"); + + chan.initiator_addrtype = GSS_C_AF_INET; + chan.initiator_address.length = l - 4; + chan.initiator_address.value = + &((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr; + chan.acceptor_addrtype = GSS_C_AF_INET; + chan.acceptor_address.length = l - 4; + chan.acceptor_address.value = + &((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr; + chan.application_data.length = 0; + chan.application_data.value = NULL; + + /* this loop will execute twice (once for service, once for host) */ + for(;;) { + /* this really shouldn't be repeated here, but can't help it */ + if(service == srv_host) { + result = Curl_ftpsendf(conn, "AUTH GSSAPI"); + + if(result) + return -2; + if(Curl_GetFTPResponse(&nread, conn, NULL)) + return -1; + + if(data->state.buffer[0] != '3') + return -1; + } + + input_buffer.value = data->state.buffer; + input_buffer.length = snprintf(input_buffer.value, BUFSIZE, "%s@%s", + service, host); + maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE, + &gssname); + if(maj != GSS_S_COMPLETE) { + gss_release_name(&min, &gssname); + if(service == srv_host) { + Curl_failf(data, "Error importing service name %s", + input_buffer.value); + return AUTH_ERROR; + } + service = srv_host; + continue; + } + /* We pass NULL as |output_name_type| to avoid a leak. */ + gss_display_name(&min, gssname, &output_buffer, NULL); + Curl_infof(data, "Trying against %s\n", output_buffer.value); + gssresp = GSS_C_NO_BUFFER; + *context = GSS_C_NO_CONTEXT; + + do { + /* Release the buffer at each iteration to avoid leaking: the first time + we are releasing the memory from gss_display_name. The last item is + taken care by a final gss_release_buffer. */ + gss_release_buffer(&min, &output_buffer); + ret = AUTH_OK; + maj = Curl_gss_init_sec_context(data, + &min, + context, + gssname, + &Curl_krb5_mech_oid, + &chan, + gssresp, + &output_buffer, + TRUE, + NULL); + + if(gssresp) { + free(_gssresp.value); + gssresp = NULL; + } + + if(GSS_ERROR(maj)) { + Curl_infof(data, "Error creating security context\n"); + ret = AUTH_ERROR; + break; + } + + if(output_buffer.length != 0) { + result = Curl_base64_encode(data, (char *)output_buffer.value, + output_buffer.length, &p, &base64_sz); + if(result) { + Curl_infof(data, "base64-encoding: %s\n", + curl_easy_strerror(result)); + ret = AUTH_CONTINUE; + break; + } + + result = Curl_ftpsendf(conn, "ADAT %s", p); + + free(p); + + if(result) { + ret = -2; + break; + } + + if(Curl_GetFTPResponse(&nread, conn, NULL)) { + ret = -1; + break; + } + + if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') { + Curl_infof(data, "Server didn't accept auth data\n"); + ret = AUTH_ERROR; + break; + } + + p = data->state.buffer + 4; + p = strstr(p, "ADAT="); + if(p) { + result = Curl_base64_decode(p + 5, + (unsigned char **)&_gssresp.value, + &_gssresp.length); + if(result) { + Curl_failf(data, "base64-decoding: %s", + curl_easy_strerror(result)); + ret = AUTH_CONTINUE; + break; + } + } + + gssresp = &_gssresp; + } + } while(maj == GSS_S_CONTINUE_NEEDED); + + gss_release_name(&min, &gssname); + gss_release_buffer(&min, &output_buffer); + + if(gssresp) + free(_gssresp.value); + + if(ret == AUTH_OK || service == srv_host) + return ret; + + service = srv_host; + } + return ret; +} + +static void krb5_end(void *app_data) +{ + OM_uint32 min; + gss_ctx_id_t *context = app_data; + if(*context != GSS_C_NO_CONTEXT) { +#ifdef DEBUGBUILD + OM_uint32 maj = +#endif + gss_delete_sec_context(&min, context, GSS_C_NO_BUFFER); + DEBUGASSERT(maj == GSS_S_COMPLETE); + } +} + +struct Curl_sec_client_mech Curl_krb5_client_mech = { + "GSSAPI", + sizeof(gss_ctx_id_t), + krb5_init, + krb5_auth, + krb5_end, + krb5_check_prot, + krb5_overhead, + krb5_encode, + krb5_decode +}; + +#endif /* HAVE_GSSAPI && !CURL_DISABLE_FTP */ diff --git a/libcurl/src/lib/ldap.c b/libcurl/src/lib/ldap.c new file mode 100644 index 0000000..4d91282 --- /dev/null +++ b/libcurl/src/lib/ldap.c @@ -0,0 +1,1013 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP) + +/* + * Notice that USE_OPENLDAP is only a source code selection switch. When + * libcurl is built with USE_OPENLDAP defined the libcurl source code that + * gets compiled is the code from openldap.c, otherwise the code that gets + * compiled is the code from ldap.c. + * + * When USE_OPENLDAP is defined a recent version of the OpenLDAP library + * might be required for compilation and runtime. In order to use ancient + * OpenLDAP library versions, USE_OPENLDAP shall not be defined. + */ + +#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */ +# include +# ifndef LDAP_VENDOR_NAME +# error Your Platform SDK is NOT sufficient for LDAP support! \ + Update your Platform SDK, or disable LDAP support! +# else +# include +# endif +#else +# define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */ +# ifdef HAVE_LBER_H +# include +# endif +# include +# if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H)) +# include +# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */ +#endif + +/* These are macros in both (in above ) and typedefs + * in BoringSSL's + */ +#ifdef HAVE_BORINGSSL +# undef X509_NAME +# undef X509_CERT_PAIR +# undef X509_EXTENSIONS +#endif + +#include "urldata.h" +#include +#include "sendf.h" +#include "escape.h" +#include "progress.h" +#include "transfer.h" +#include "strequal.h" +#include "strtok.h" +#include "curl_ldap.h" +#include "curl_multibyte.h" +#include "curl_base64.h" +#include "rawstr.h" +#include "connect.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef HAVE_LDAP_URL_PARSE + +/* Use our own implementation. */ + +typedef struct { + char *lud_host; + int lud_port; +#if defined(USE_WIN32_LDAP) + TCHAR *lud_dn; + TCHAR **lud_attrs; +#else + char *lud_dn; + char **lud_attrs; +#endif + int lud_scope; +#if defined(USE_WIN32_LDAP) + TCHAR *lud_filter; +#else + char *lud_filter; +#endif + char **lud_exts; + size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the + "real" struct so can only be used in code + without HAVE_LDAP_URL_PARSE defined */ +} CURL_LDAPURLDesc; + +#undef LDAPURLDesc +#define LDAPURLDesc CURL_LDAPURLDesc + +static int _ldap_url_parse (const struct connectdata *conn, + LDAPURLDesc **ludp); +static void _ldap_free_urldesc (LDAPURLDesc *ludp); + +#undef ldap_free_urldesc +#define ldap_free_urldesc _ldap_free_urldesc +#endif + +#ifdef DEBUG_LDAP + #define LDAP_TRACE(x) do { \ + _ldap_trace ("%u: ", __LINE__); \ + _ldap_trace x; \ + } WHILE_FALSE + + static void _ldap_trace (const char *fmt, ...); +#else + #define LDAP_TRACE(x) Curl_nop_stmt +#endif + + +static CURLcode Curl_ldap(struct connectdata *conn, bool *done); + +/* + * LDAP protocol handler. + */ + +const struct Curl_handler Curl_handler_ldap = { + "LDAP", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_ldap, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef HAVE_LDAP_SSL +/* + * LDAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ldaps = { + "LDAPS", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_ldap, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAPS, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + + +static CURLcode Curl_ldap(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + int rc = 0; + LDAP *server = NULL; + LDAPURLDesc *ludp = NULL; + LDAPMessage *ldapmsg = NULL; + LDAPMessage *entryIterator; + int num = 0; + struct SessionHandle *data=conn->data; + int ldap_proto = LDAP_VERSION3; + int ldap_ssl = 0; + char *val_b64 = NULL; + size_t val_b64_sz = 0; + curl_off_t dlsize = 0; +#ifdef LDAP_OPT_NETWORK_TIMEOUT + struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */ +#endif +#if defined(USE_WIN32_LDAP) + TCHAR *host = NULL; + TCHAR *user = NULL; + TCHAR *passwd = NULL; +#else + char *host = NULL; + char *user = NULL; + char *passwd = NULL; +#endif + + *done = TRUE; /* unconditionally */ + infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n", + LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); + infof(data, "LDAP local: %s\n", data->change.url); + +#ifdef HAVE_LDAP_URL_PARSE + rc = ldap_url_parse(data->change.url, &ludp); +#else + rc = _ldap_url_parse(conn, &ludp); +#endif + if(rc != 0) { + failf(data, "LDAP local: %s", ldap_err2string(rc)); + result = CURLE_LDAP_INVALID_URL; + goto quit; + } + + /* Get the URL scheme ( either ldap or ldaps ) */ + if(conn->given->flags & PROTOPT_SSL) + ldap_ssl = 1; + infof(data, "LDAP local: trying to establish %s connection\n", + ldap_ssl ? "encrypted" : "cleartext"); + +#if defined(USE_WIN32_LDAP) + host = Curl_convert_UTF8_to_tchar(conn->host.name); + if(!host) { + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } + + if(conn->bits.user_passwd) { + user = Curl_convert_UTF8_to_tchar(conn->user); + passwd = Curl_convert_UTF8_to_tchar(conn->passwd); + if(!user || !passwd) { + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } + } +#else + host = conn->host.name; + + if(conn->bits.user_passwd) { + user = conn->user; + passwd = conn->passwd; + } +#endif + +#ifdef LDAP_OPT_NETWORK_TIMEOUT + ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout); +#endif + ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); + + if(ldap_ssl) { +#ifdef HAVE_LDAP_SSL +#ifdef USE_WIN32_LDAP + /* Win32 LDAP SDK doesn't support insecure mode without CA! */ + server = ldap_sslinit(host, (int)conn->port, 1); + ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); +#else + int ldap_option; + char* ldap_ca = data->set.str[STRING_SSL_CAFILE]; +#if defined(CURL_HAS_NOVELL_LDAPSDK) + rc = ldapssl_client_init(NULL, NULL); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + if(data->set.ssl.verifypeer) { + /* Novell SDK supports DER or BASE64 files. */ + int cert_type = LDAPSSL_CERT_FILETYPE_B64; + if((data->set.str[STRING_CERT_TYPE]) && + (Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER"))) + cert_type = LDAPSSL_CERT_FILETYPE_DER; + if(!ldap_ca) { + failf(data, "LDAP local: ERROR %s CA cert not set!", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM")); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + infof(data, "LDAP local: using %s CA cert '%s'\n", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), + ldap_ca); + rc = ldapssl_add_trusted_cert(ldap_ca, cert_type); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting %s CA cert: %s", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + ldap_option = LDAPSSL_VERIFY_SERVER; + } + else + ldap_option = LDAPSSL_VERIFY_NONE; + rc = ldapssl_set_verify_mode(ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting cert verify mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + server = ldapssl_init(host, (int)conn->port, 1); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } +#elif defined(LDAP_OPT_X_TLS) + if(data->set.ssl.verifypeer) { + /* OpenLDAP SDK supports BASE64 files. */ + if((data->set.str[STRING_CERT_TYPE]) && + (!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) { + failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + if(!ldap_ca) { + failf(data, "LDAP local: ERROR PEM CA cert not set!"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca); + rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting PEM CA cert: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + ldap_option = LDAP_OPT_X_TLS_DEMAND; + } + else + ldap_option = LDAP_OPT_X_TLS_NEVER; + + rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting cert verify mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + server = ldap_init(host, (int)conn->port); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } + ldap_option = LDAP_OPT_X_TLS_HARD; + rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } +/* + rc = ldap_start_tls_s(server, NULL, NULL); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } +*/ +#else + /* we should probably never come up to here since configure + should check in first place if we can support LDAP SSL/TLS */ + failf(data, "LDAP local: SSL/TLS not supported with this version " + "of the OpenLDAP toolkit\n"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; +#endif +#endif +#endif /* CURL_LDAP_USE_SSL */ + } + else { + server = ldap_init(host, (int)conn->port); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } + } +#ifdef USE_WIN32_LDAP + ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); +#endif + + rc = ldap_simple_bind_s(server, user, passwd); + if(!ldap_ssl && rc != 0) { + ldap_proto = LDAP_VERSION2; + ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); + rc = ldap_simple_bind_s(server, user, passwd); + } + if(rc != 0) { + failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc)); + result = CURLE_LDAP_CANNOT_BIND; + goto quit; + } + + rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, + ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); + + if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) { + failf(data, "LDAP remote: %s", ldap_err2string(rc)); + result = CURLE_LDAP_SEARCH_FAILED; + goto quit; + } + + for(num = 0, entryIterator = ldap_first_entry(server, ldapmsg); + entryIterator; + entryIterator = ldap_next_entry(server, entryIterator), num++) { + BerElement *ber = NULL; +#if defined(USE_WIN32_LDAP) + TCHAR *attribute; +#else + char *attribute; /*! suspicious that this isn't 'const' */ +#endif + int i; + + /* Get the DN and write it to the client */ + { + char *name; + size_t name_len; +#if defined(USE_WIN32_LDAP) + TCHAR *dn = ldap_get_dn(server, entryIterator); + name = Curl_convert_tchar_to_UTF8(dn); + if(!name) { + ldap_memfree(dn); + + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } +#else + char *dn = name = ldap_get_dn(server, entryIterator); +#endif + name_len = strlen(name); + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name, + name_len); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + dlsize += name_len + 5; + +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + } + + /* Get the attributes and write them to the client */ + for(attribute = ldap_first_attribute(server, entryIterator, &ber); + attribute; + attribute = ldap_next_attribute(server, entryIterator, ber)) { + BerValue **vals; + size_t attr_len; +#if defined(USE_WIN32_LDAP) + char *attr = Curl_convert_tchar_to_UTF8(attribute); + if(!attr) { + if(ber) + ber_free(ber, 0); + + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } +#else + char *attr = attribute; +#endif + attr_len = strlen(attr); + + vals = ldap_get_values_len(server, entryIterator, attribute); + if(vals != NULL) { + for(i = 0; (vals[i] != NULL); i++) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *) attr, attr_len); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += attr_len + 3; + + if((attr_len > 7) && + (strcmp(";binary", (char *) attr + (attr_len - 7)) == 0)) { + /* Binary attribute, encode to base64. */ + result = Curl_base64_encode(data, + vals[i]->bv_val, + vals[i]->bv_len, + &val_b64, + &val_b64_sz); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + if(val_b64_sz > 0) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, + val_b64_sz); + free(val_b64); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += val_b64_sz; + } + } + else { + result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val, + vals[i]->bv_len); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += vals[i]->bv_len; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize++; + } + + /* Free memory used to store values */ + ldap_value_free_len(vals); + } + + /* Free the attribute as we are done with it */ +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) + goto quit; + dlsize++; + Curl_pgrsSetDownloadCounter(data, dlsize); + } + + if(ber) + ber_free(ber, 0); + } + +quit: + if(ldapmsg) { + ldap_msgfree(ldapmsg); + LDAP_TRACE (("Received %d entries\n", num)); + } + if(rc == LDAP_SIZELIMIT_EXCEEDED) + infof(data, "There are more than %d entries\n", num); + if(ludp) + ldap_free_urldesc(ludp); + if(server) + ldap_unbind_s(server); +#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK) + if(ldap_ssl) + ldapssl_client_deinit(); +#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */ + +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(passwd); + Curl_unicodefree(user); + Curl_unicodefree(host); +#endif + + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + connclose(conn, "LDAP connection always disable re-use"); + + return result; +} + +#ifdef DEBUG_LDAP +static void _ldap_trace (const char *fmt, ...) +{ + static int do_trace = -1; + va_list args; + + if(do_trace == -1) { + const char *env = getenv("CURL_TRACE"); + do_trace = (env && strtol(env, NULL, 10) > 0); + } + if(!do_trace) + return; + + va_start (args, fmt); + vfprintf (stderr, fmt, args); + va_end (args); +} +#endif + +#ifndef HAVE_LDAP_URL_PARSE + +/* + * Return scope-value for a scope-string. + */ +static int str2scope (const char *p) +{ + if(strequal(p, "one")) + return LDAP_SCOPE_ONELEVEL; + if(strequal(p, "onetree")) + return LDAP_SCOPE_ONELEVEL; + if(strequal(p, "base")) + return LDAP_SCOPE_BASE; + if(strequal(p, "sub")) + return LDAP_SCOPE_SUBTREE; + if(strequal( p, "subtree")) + return LDAP_SCOPE_SUBTREE; + return (-1); +} + +/* + * Split 'str' into strings separated by commas. + * Note: out[] points into 'str'. + */ +static bool split_str(char *str, char ***out, size_t *count) +{ + char **res; + char *lasts; + char *s; + size_t i; + size_t items = 1; + + s = strchr(str, ','); + while(s) { + items++; + s = strchr(++s, ','); + } + + res = calloc(items, sizeof(char *)); + if(!res) + return FALSE; + + for(i = 0, s = strtok_r(str, ",", &lasts); s && i < items; + s = strtok_r(NULL, ",", &lasts), i++) + res[i] = s; + + *out = res; + *count = items; + + return TRUE; +} + +/* + * Break apart the pieces of an LDAP URL. + * Syntax: + * ldap://:/???? + * + * already known from 'conn->host.name'. + * already known from 'conn->remote_port'. + * extract the rest from 'conn->data->state.path+1'. All fields are optional. + * e.g. + * ldap://:/??? + * yields ludp->lud_dn = "". + * + * Defined in RFC4516 section 2. + */ +static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) +{ + int rc = LDAP_SUCCESS; + char *path; + char *p; + char *q; + size_t i; + + if(!conn->data || + !conn->data->state.path || + conn->data->state.path[0] != '/' || + !checkprefix("LDAP", conn->data->change.url)) + return LDAP_INVALID_SYNTAX; + + ludp->lud_scope = LDAP_SCOPE_BASE; + ludp->lud_port = conn->remote_port; + ludp->lud_host = conn->host.name; + + /* Duplicate the path */ + p = path = strdup(conn->data->state.path + 1); + if(!path) + return LDAP_NO_MEMORY; + + /* Parse the DN (Distinguished Name) */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + char *dn = p; + char *unescaped; + + LDAP_TRACE (("DN '%s'\n", dn)); + + /* Unescape the DN */ + unescaped = curl_easy_unescape(conn->data, dn, 0, NULL); + if(!unescaped) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_dn) { + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_dn = unescaped; +#endif + } + + p = q; + if(!p) + goto quit; + + /* Parse the attributes. skip "??" */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + char **attributes; + size_t count = 0; + + /* Split the string into an array of attributes */ + if(!split_str(p, &attributes, &count)) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + + /* Allocate our array (+1 for the NULL entry) */ +#if defined(USE_WIN32_LDAP) + ludp->lud_attrs = calloc(count + 1, sizeof(TCHAR *)); +#else + ludp->lud_attrs = calloc(count + 1, sizeof(char *)); +#endif + if(!ludp->lud_attrs) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } + + for(i = 0; i < count; i++) { + char *unescaped; + + LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i])); + + /* Unescape the attribute */ + unescaped = curl_easy_unescape(conn->data, attributes[i], 0, NULL); + if(!unescaped) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_attrs[i]) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_attrs[i] = unescaped; +#endif + + ludp->lud_attrs_dups++; + } + + free(attributes); + } + + p = q; + if(!p) + goto quit; + + /* Parse the scope. skip "??" */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + ludp->lud_scope = str2scope(p); + if(ludp->lud_scope == -1) { + rc = LDAP_INVALID_SYNTAX; + + goto quit; + } + LDAP_TRACE (("scope %d\n", ludp->lud_scope)); + } + + p = q; + if(!p) + goto quit; + + /* Parse the filter */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + char *filter = p; + char *unescaped; + + LDAP_TRACE (("filter '%s'\n", filter)); + + /* Unescape the filter */ + unescaped = curl_easy_unescape(conn->data, filter, 0, NULL); + if(!unescaped) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_filter) { + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_filter = unescaped; +#endif + } + + p = q; + if(p && !*p) { + rc = LDAP_INVALID_SYNTAX; + + goto quit; + } + +quit: + free(path); + + return rc; +} + +static int _ldap_url_parse (const struct connectdata *conn, + LDAPURLDesc **ludpp) +{ + LDAPURLDesc *ludp = calloc(1, sizeof(*ludp)); + int rc; + + *ludpp = NULL; + if(!ludp) + return LDAP_NO_MEMORY; + + rc = _ldap_url_parse2 (conn, ludp); + if(rc != LDAP_SUCCESS) { + _ldap_free_urldesc(ludp); + ludp = NULL; + } + *ludpp = ludp; + return (rc); +} + +static void _ldap_free_urldesc (LDAPURLDesc *ludp) +{ + size_t i; + + if(!ludp) + return; + + free(ludp->lud_dn); + free(ludp->lud_filter); + + if(ludp->lud_attrs) { + for(i = 0; i < ludp->lud_attrs_dups; i++) + free(ludp->lud_attrs[i]); + free(ludp->lud_attrs); + } + + free (ludp); +} +#endif /* !HAVE_LDAP_URL_PARSE */ +#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */ diff --git a/libcurl/src/lib/libcurl.rc b/libcurl/src/lib/libcurl.rc new file mode 100644 index 0000000..47b944a --- /dev/null +++ b/libcurl/src/lib/libcurl.rc @@ -0,0 +1,63 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include +#include "../include/curl/curlver.h" + +LANGUAGE 0x09,0x01 + +#define RC_VERSION LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0 + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RC_VERSION + PRODUCTVERSION RC_VERSION + FILEFLAGSMASK 0x3fL +#if defined(DEBUGBUILD) || defined(_DEBUG) + FILEFLAGS 1 +#else + FILEFLAGS 0 +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "The cURL library, http://curl.haxx.se/\0" + VALUE "FileDescription", "libcurl Shared Library\0" + VALUE "FileVersion", LIBCURL_VERSION "\0" + VALUE "InternalName", "libcurl\0" + VALUE "OriginalFilename", "libcurl.dll\0" + VALUE "ProductName", "The cURL library\0" + VALUE "ProductVersion", LIBCURL_VERSION "\0" + VALUE "LegalCopyright", " " LIBCURL_COPYRIGHT "\0" + VALUE "License", "http://curl.haxx.se/docs/copyright.html\0" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/libcurl/src/lib/llist.c b/libcurl/src/lib/llist.c new file mode 100644 index 0000000..9e6e6ce --- /dev/null +++ b/libcurl/src/lib/llist.c @@ -0,0 +1,212 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "llist.h" +#include "curl_memory.h" + +/* this must be the last include file */ +#include "memdebug.h" + +/* + * @unittest: 1300 + */ +static void +llist_init(struct curl_llist *l, curl_llist_dtor dtor) +{ + l->size = 0; + l->dtor = dtor; + l->head = NULL; + l->tail = NULL; +} + +CURL_STATIC struct curl_llist * +Curl_llist_alloc(curl_llist_dtor dtor) +{ + struct curl_llist *list; + + list = malloc(sizeof(struct curl_llist)); + if(!list) + return NULL; + + llist_init(list, dtor); + + return list; +} + +/* + * Curl_llist_insert_next() + * + * Inserts a new list element after the given one 'e'. If the given existing + * entry is NULL and the list already has elements, the new one will be + * inserted first in the list. + * + * Returns: 1 on success and 0 on failure. + * + * @unittest: 1300 + */ +CURL_STATIC int +Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, + const void *p) +{ + struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element)); + if(!ne) + return 0; + + ne->ptr = (void *) p; + if(list->size == 0) { + list->head = ne; + list->head->prev = NULL; + list->head->next = NULL; + list->tail = ne; + } + else { + /* if 'e' is NULL here, we insert the new element first in the list */ + ne->next = e?e->next:list->head; + ne->prev = e; + if(!e) { + list->head->prev = ne; + list->head = ne; + } + else if(e->next) { + e->next->prev = ne; + } + else { + list->tail = ne; + } + if(e) + e->next = ne; + } + + ++list->size; + + return 1; +} + +/* + * @unittest: 1300 + */ +CURL_STATIC int +Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, + void *user) +{ + if(e == NULL || list->size == 0) + return 1; + + if(e == list->head) { + list->head = e->next; + + if(list->head == NULL) + list->tail = NULL; + else + e->next->prev = NULL; + } + else { + e->prev->next = e->next; + if(!e->next) + list->tail = e->prev; + else + e->next->prev = e->prev; + } + + list->dtor(user, e->ptr); + + e->ptr = NULL; + e->prev = NULL; + e->next = NULL; + + free(e); + --list->size; + + return 1; +} + +CURL_STATIC void +Curl_llist_destroy(struct curl_llist *list, void *user) +{ + if(list) { + while(list->size > 0) + Curl_llist_remove(list, list->tail, user); + + free(list); + } +} + +CURL_STATIC size_t +Curl_llist_count(struct curl_llist *list) +{ + return list->size; +} + +/* + * @unittest: 1300 + */ +CURL_STATIC int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, + struct curl_llist *to_list, + struct curl_llist_element *to_e) +{ + /* Remove element from list */ + if(e == NULL || list->size == 0) + return 0; + + if(e == list->head) { + list->head = e->next; + + if(list->head == NULL) + list->tail = NULL; + else + e->next->prev = NULL; + } + else { + e->prev->next = e->next; + if(!e->next) + list->tail = e->prev; + else + e->next->prev = e->prev; + } + + --list->size; + + /* Add element to to_list after to_e */ + if(to_list->size == 0) { + to_list->head = e; + to_list->head->prev = NULL; + to_list->head->next = NULL; + to_list->tail = e; + } + else { + e->next = to_e->next; + e->prev = to_e; + if(to_e->next) { + to_e->next->prev = e; + } + else { + to_list->tail = e; + } + to_e->next = e; + } + + ++to_list->size; + + return 1; +} diff --git a/libcurl/src/lib/llist.h b/libcurl/src/lib/llist.h new file mode 100644 index 0000000..85915b0 --- /dev/null +++ b/libcurl/src/lib/llist.h @@ -0,0 +1,57 @@ +#ifndef HEADER_CURL_LLIST_H +#define HEADER_CURL_LLIST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include + +typedef void (*curl_llist_dtor)(void *, void *); + +struct curl_llist_element { + void *ptr; + + struct curl_llist_element *prev; + struct curl_llist_element *next; +}; + +struct curl_llist { + struct curl_llist_element *head; + struct curl_llist_element *tail; + + curl_llist_dtor dtor; + + size_t size; +}; + +CURL_STATIC struct curl_llist *Curl_llist_alloc(curl_llist_dtor); +CURL_STATIC int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *, + const void *); +CURL_STATIC int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, + void *); +CURL_STATIC size_t Curl_llist_count(struct curl_llist *); +CURL_STATIC void Curl_llist_destroy(struct curl_llist *, void *); +CURL_STATIC int Curl_llist_move(struct curl_llist *, struct curl_llist_element *, + struct curl_llist *, struct curl_llist_element *); + +#endif /* HEADER_CURL_LLIST_H */ + diff --git a/libcurl/src/lib/md4.c b/libcurl/src/lib/md4.c new file mode 100644 index 0000000..700f832 --- /dev/null +++ b/libcurl/src/lib/md4.c @@ -0,0 +1,304 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD4 Message-Digest Algorithm (RFC 1320). + * + * Homepage: + http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. In case + * this attempt to disclaim copyright and place the software in the public + * domain is deemed null and void, then the software is Copyright (c) 2001 + * Alexander Peslyak and it is hereby released to the general public under the + * following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#include "curl_setup.h" + +/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so + * that we have a local implementation of it */ +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) + +#include "curl_md4.h" +#include "warnless.h" + +#ifndef HAVE_OPENSSL + +#include + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD4_u32plus; + +typedef struct { + MD4_u32plus lo, hi; + MD4_u32plus a, b, c, d; + unsigned char buffer[64]; + MD4_u32plus block[16]; +} MD4_CTX; + +static void MD4_Init(MD4_CTX *ctx); +static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size); +static void MD4_Final(unsigned char *result, MD4_CTX *ctx); + +/* + * The basic MD4 functions. + * + * F and G are optimized compared to their RFC 1320 definitions, with the + * optimization for F borrowed from Colin Plumb's MD5 implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* + * The MD4 transformation for all three rounds. + */ +#define STEP(f, a, b, c, d, x, s) \ + (a) += f((b), (c), (d)) + (x); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD4_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD4_u32plus)ptr[(n) * 4] | \ + ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD4_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(MD4_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD4_u32plus a, b, c, d; + MD4_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 3) + STEP(F, d, a, b, c, SET(1), 7) + STEP(F, c, d, a, b, SET(2), 11) + STEP(F, b, c, d, a, SET(3), 19) + STEP(F, a, b, c, d, SET(4), 3) + STEP(F, d, a, b, c, SET(5), 7) + STEP(F, c, d, a, b, SET(6), 11) + STEP(F, b, c, d, a, SET(7), 19) + STEP(F, a, b, c, d, SET(8), 3) + STEP(F, d, a, b, c, SET(9), 7) + STEP(F, c, d, a, b, SET(10), 11) + STEP(F, b, c, d, a, SET(11), 19) + STEP(F, a, b, c, d, SET(12), 3) + STEP(F, d, a, b, c, SET(13), 7) + STEP(F, c, d, a, b, SET(14), 11) + STEP(F, b, c, d, a, SET(15), 19) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while(size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +static void MD4_Init(MD4_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) +{ + MD4_u32plus saved_lo; + unsigned long used, available; + + saved_lo = ctx->lo; + if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += (MD4_u32plus)size >> 29; + + used = saved_lo & 0x3f; + + if(used) { + available = 64 - used; + + if(size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if(size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +static void MD4_Final(unsigned char *result, MD4_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if(available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); + ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); + ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); + ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff); + ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); + ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); + ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); + ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); + + body(ctx, ctx->buffer, 64); + + result[0] = curlx_ultouc((ctx->a)&0xff); + result[1] = curlx_ultouc((ctx->a >> 8)&0xff); + result[2] = curlx_ultouc((ctx->a >> 16)&0xff); + result[3] = curlx_ultouc(ctx->a >> 24); + result[4] = curlx_ultouc((ctx->b)&0xff); + result[5] = curlx_ultouc((ctx->b >> 8)&0xff); + result[6] = curlx_ultouc((ctx->b >> 16)&0xff); + result[7] = curlx_ultouc(ctx->b >> 24); + result[8] = curlx_ultouc((ctx->c)&0xff); + result[9] = curlx_ultouc((ctx->c >> 8)&0xff); + result[10] = curlx_ultouc((ctx->c >> 16)&0xff); + result[11] = curlx_ultouc(ctx->c >> 24); + result[12] = curlx_ultouc((ctx->d)&0xff); + result[13] = curlx_ultouc((ctx->d >> 8)&0xff); + result[14] = curlx_ultouc((ctx->d >> 16)&0xff); + result[15] = curlx_ultouc(ctx->d >> 24); + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif + +CURL_STATIC void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len) +{ + MD4_CTX ctx; + MD4_Init(&ctx); + MD4_Update(&ctx, input, curlx_uztoui(len)); + MD4_Final(output, &ctx); +} +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */ diff --git a/libcurl/src/lib/md5.c b/libcurl/src/lib/md5.c new file mode 100644 index 0000000..efed3b8 --- /dev/null +++ b/libcurl/src/lib/md5.c @@ -0,0 +1,560 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +#include "curl_md5.h" +#include "curl_hmac.h" +#include "warnless.h" + +#if defined(USE_GNUTLS_NETTLE) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct md5_ctx MD5_CTX; + +static void MD5_Init(MD5_CTX * ctx) +{ + md5_init(ctx); +} + +static void MD5_Update(MD5_CTX * ctx, + const unsigned char * input, + unsigned int inputLen) +{ + md5_update(ctx, inputLen, input); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx) +{ + md5_digest(ctx, 16, digest); +} + +#elif defined(USE_GNUTLS) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef gcry_md_hd_t MD5_CTX; + +static void MD5_Init(MD5_CTX * ctx) +{ + gcry_md_open(ctx, GCRY_MD_MD5, 0); +} + +static void MD5_Update(MD5_CTX * ctx, + const unsigned char * input, + unsigned int inputLen) +{ + gcry_md_write(*ctx, input, inputLen); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx) +{ + memcpy(digest, gcry_md_read(*ctx, 0), 16); + gcry_md_close(*ctx); +} + +#elif defined(USE_OPENSSL) +/* When OpenSSL is available we use the MD5-function from OpenSSL */ +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ + (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ + (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000)) + +/* For Apple operating systems: CommonCrypto has the functions we need. + These functions are available on Tiger and later, as well as iOS 2.0 + and later. If you're building for an older cat, well, sorry. + + Declaring the functions as static like this seems to be a bit more + reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */ +# include +# define MD5_CTX CC_MD5_CTX +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +static void MD5_Init(MD5_CTX *ctx) +{ + CC_MD5_Init(ctx); +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + CC_MD5_Update(ctx, input, inputLen); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + CC_MD5_Final(digest, ctx); +} + +#elif defined(_WIN32) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct { + HCRYPTPROV hCryptProv; + HCRYPTHASH hHash; +} MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx) +{ + if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash); + } +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + unsigned long length = 0; + CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0); + if(length == 16) + CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0); + if(ctx->hHash) + CryptDestroyHash(ctx->hHash); + if(ctx->hCryptProv) + CryptReleaseContext(ctx->hCryptProv, 0); +} + +#elif defined(USE_AXTLS) +#include +#include +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" +#else +/* When no other crypto library is available we use this code segment */ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#include + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx); +static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +static void MD5_Final(unsigned char *result, MD5_CTX *ctx); + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD5_u32plus a, b, c, d; + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while(size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +static void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used, available; + + saved_lo = ctx->lo; + if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += (MD5_u32plus)size >> 29; + + used = saved_lo & 0x3f; + + if(used) { + available = 64 - used; + + if(size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if(size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +static void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if(available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); + ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); + ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); + ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24); + ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); + ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); + ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); + ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); + + body(ctx, ctx->buffer, 64); + + result[0] = curlx_ultouc((ctx->a)&0xff); + result[1] = curlx_ultouc((ctx->a >> 8)&0xff); + result[2] = curlx_ultouc((ctx->a >> 16)&0xff); + result[3] = curlx_ultouc(ctx->a >> 24); + result[4] = curlx_ultouc((ctx->b)&0xff); + result[5] = curlx_ultouc((ctx->b >> 8)&0xff); + result[6] = curlx_ultouc((ctx->b >> 16)&0xff); + result[7] = curlx_ultouc(ctx->b >> 24); + result[8] = curlx_ultouc((ctx->c)&0xff); + result[9] = curlx_ultouc((ctx->c >> 8)&0xff); + result[10] = curlx_ultouc((ctx->c >> 16)&0xff); + result[11] = curlx_ultouc(ctx->c >> 24); + result[12] = curlx_ultouc((ctx->d)&0xff); + result[13] = curlx_ultouc((ctx->d >> 8)&0xff); + result[14] = curlx_ultouc((ctx->d >> 16)&0xff); + result[15] = curlx_ultouc(ctx->d >> 24); + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif /* CRYPTO LIBS */ + +const HMAC_params Curl_HMAC_MD5[] = { + { + (HMAC_hinit_func) MD5_Init, /* Hash initialization function. */ + (HMAC_hupdate_func) MD5_Update, /* Hash update function. */ + (HMAC_hfinal_func) MD5_Final, /* Hash computation end function. */ + sizeof(MD5_CTX), /* Size of hash context structure. */ + 64, /* Maximum key length. */ + 16 /* Result size. */ + } +}; + +const MD5_params Curl_DIGEST_MD5[] = { + { + (Curl_MD5_init_func) MD5_Init, /* Digest initialization function */ + (Curl_MD5_update_func) MD5_Update, /* Digest update function */ + (Curl_MD5_final_func) MD5_Final, /* Digest computation end function */ + sizeof(MD5_CTX), /* Size of digest context struct */ + 16 /* Result size */ + } +}; + +/* + * @unittest: 1601 + */ +CURL_STATIC void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */ + const unsigned char *input) +{ + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, input, curlx_uztoui(strlen((char *)input))); + MD5_Final(outbuffer, &ctx); +} + +CURL_STATIC MD5_context *Curl_MD5_init(const MD5_params *md5params) +{ + MD5_context *ctxt; + + /* Create MD5 context */ + ctxt = malloc(sizeof *ctxt); + + if(!ctxt) + return ctxt; + + ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize); + + if(!ctxt->md5_hashctx) { + free(ctxt); + return NULL; + } + + ctxt->md5_hash = md5params; + + (*md5params->md5_init_func)(ctxt->md5_hashctx); + + return ctxt; +} + +CURL_STATIC int Curl_MD5_update(MD5_context *context, + const unsigned char *data, + unsigned int len) +{ + (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len); + + return 0; +} + +CURL_STATIC int Curl_MD5_final(MD5_context *context, unsigned char *result) +{ + (*context->md5_hash->md5_final_func)(result, context->md5_hashctx); + + free(context->md5_hashctx); + free(context); + + return 0; +} + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libcurl/src/lib/memdebug.c b/libcurl/src/lib/memdebug.c new file mode 100644 index 0000000..3b38a74 --- /dev/null +++ b/libcurl/src/lib/memdebug.c @@ -0,0 +1,489 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURLDEBUG + +#include + +#include "curl_printf.h" +#include "urldata.h" + +#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef HAVE_ASSERT_H +# define assert(x) Curl_nop_stmt +#endif + +/* + * Until 2011-08-17 libcurl's Memory Tracking feature also performed + * automatic malloc and free filling operations using 0xA5 and 0x13 + * values. Our own preinitialization of dynamically allocated memory + * might be useful when not using third party memory debuggers, but + * on the other hand this would fool memory debuggers into thinking + * that all dynamically allocated memory is properly initialized. + * + * As a default setting, libcurl's Memory Tracking feature no longer + * performs preinitialization of dynamically allocated memory on its + * own. If you know what you are doing, and really want to retain old + * behavior, you can achieve this compiling with preprocessor symbols + * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate + * values. + */ + +#ifdef CURL_MT_MALLOC_FILL +# if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff) +# error "invalid CURL_MT_MALLOC_FILL or out of range" +# endif +#endif + +#ifdef CURL_MT_FREE_FILL +# if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff) +# error "invalid CURL_MT_FREE_FILL or out of range" +# endif +#endif + +#if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL) +# if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL) +# error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL" +# endif +#endif + +#ifdef CURL_MT_MALLOC_FILL +# define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len)) +#else +# define mt_malloc_fill(buf,len) Curl_nop_stmt +#endif + +#ifdef CURL_MT_FREE_FILL +# define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len)) +#else +# define mt_free_fill(buf,len) Curl_nop_stmt +#endif + +struct memdebug { + size_t size; + union { + curl_off_t o; + double d; + void * p; + } mem[1]; + /* I'm hoping this is the thing with the strictest alignment + * requirements. That also means we waste some space :-( */ +}; + +/* + * Note that these debug functions are very simple and they are meant to + * remain so. For advanced analysis, record a log file and write perl scripts + * to analyze them! + * + * Don't use these with multithreaded test programs! + */ + +#define logfile curl_debuglogfile +FILE *curl_debuglogfile = NULL; +static bool memlimit = FALSE; /* enable memory limit */ +static long memsize = 0; /* set number of mallocs allowed */ + +/* this sets the log file name */ +void curl_memdebug(const char *logname) +{ + if(!logfile) { + if(logname && *logname) + logfile = fopen(logname, "w"); + else + logfile = stderr; +#ifdef MEMDEBUG_LOG_SYNC + /* Flush the log file after every line so the log isn't lost in a crash */ + setvbuf(logfile, (char *)NULL, _IOLBF, 0); +#endif + } +} + +/* This function sets the number of malloc() calls that should return + successfully! */ +void curl_memlimit(long limit) +{ + if(!memlimit) { + memlimit = TRUE; + memsize = limit; + } +} + +/* returns TRUE if this isn't allowed! */ +static bool countcheck(const char *func, int line, const char *source) +{ + /* if source is NULL, then the call is made internally and this check + should not be made */ + if(memlimit && source) { + if(!memsize) { + if(source) { + /* log to file */ + curl_memlog("LIMIT %s:%d %s reached memlimit\n", + source, line, func); + /* log to stderr also */ + fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", + source, line, func); + } + SET_ERRNO(ENOMEM); + return TRUE; /* RETURN ERROR! */ + } + else + memsize--; /* countdown */ + + /* log the countdown */ + if(source) + curl_memlog("LIMIT %s:%d %ld ALLOCS left\n", + source, line, memsize); + + } + + return FALSE; /* allow this */ +} + +void *curl_domalloc(size_t wantedsize, int line, const char *source) +{ + struct memdebug *mem; + size_t size; + + assert(wantedsize != 0); + + if(countcheck("malloc", line, source)) + return NULL; + + /* alloc at least 64 bytes */ + size = sizeof(struct memdebug)+wantedsize; + + mem = (Curl_cmalloc)(size); + if(mem) { + /* fill memory with junk */ + mt_malloc_fill(mem->mem, wantedsize); + mem->size = wantedsize; + } + + if(source) + curl_memlog("MEM %s:%d malloc(%zu) = %p\n", + source, line, wantedsize, + mem ? (void *)mem->mem : (void *)0); + + return (mem ? mem->mem : NULL); +} + +void *curl_docalloc(size_t wanted_elements, size_t wanted_size, + int line, const char *source) +{ + struct memdebug *mem; + size_t size, user_size; + + assert(wanted_elements != 0); + assert(wanted_size != 0); + + if(countcheck("calloc", line, source)) + return NULL; + + /* alloc at least 64 bytes */ + user_size = wanted_size * wanted_elements; + size = sizeof(struct memdebug) + user_size; + + mem = (Curl_ccalloc)(1, size); + if(mem) + mem->size = user_size; + + if(source) + curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n", + source, line, wanted_elements, wanted_size, + mem ? (void *)mem->mem : (void *)0); + + return (mem ? mem->mem : NULL); +} + +char *curl_dostrdup(const char *str, int line, const char *source) +{ + char *mem; + size_t len; + + assert(str != NULL); + + if(countcheck("strdup", line, source)) + return NULL; + + len=strlen(str)+1; + + mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */ + if(mem) + memcpy(mem, str, len); + + if(source) + curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n", + source, line, (void *)str, len, (void *)mem); + + return mem; +} + +#if defined(WIN32) && defined(UNICODE) +wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source) +{ + wchar_t *mem; + size_t wsiz, bsiz; + + assert(str != NULL); + + if(countcheck("wcsdup", line, source)) + return NULL; + + wsiz = wcslen(str) + 1; + bsiz = wsiz * sizeof(wchar_t); + + mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */ + if(mem) + memcpy(mem, str, bsiz); + + if(source) + curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n", + source, line, (void *)str, bsiz, (void *)mem); + + return mem; +} +#endif + +/* We provide a realloc() that accepts a NULL as pointer, which then + performs a malloc(). In order to work with ares. */ +void *curl_dorealloc(void *ptr, size_t wantedsize, + int line, const char *source) +{ + struct memdebug *mem=NULL; + + size_t size = sizeof(struct memdebug)+wantedsize; + + assert(wantedsize != 0); + + if(countcheck("realloc", line, source)) + return NULL; + +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:1684) + /* 1684: conversion from pointer to same-sized integral type */ +#endif + + if(ptr) + mem = (void *)((char *)ptr - offsetof(struct memdebug, mem)); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif + + mem = (Curl_crealloc)(mem, size); + if(source) + curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n", + source, line, (void *)ptr, wantedsize, + mem ? (void *)mem->mem : (void *)0); + + if(mem) { + mem->size = wantedsize; + return mem->mem; + } + + return NULL; +} + +void curl_dofree(void *ptr, int line, const char *source) +{ + struct memdebug *mem; + + if(ptr) { + +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:1684) + /* 1684: conversion from pointer to same-sized integral type */ +#endif + + mem = (void *)((char *)ptr - offsetof(struct memdebug, mem)); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif + + /* destroy */ + mt_free_fill(mem->mem, mem->size); + + /* free for real */ + (Curl_cfree)(mem); + } + + if(source) + curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr); +} + +curl_socket_t curl_socket(int domain, int type, int protocol, + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d socket() = %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d socket() = %ld\n" : + "FD %s:%d socket() = %zd\n"; + + curl_socket_t sockfd = socket(domain, type, protocol); + + if(source && (sockfd != CURL_SOCKET_BAD)) + curl_memlog(fmt, source, line, sockfd); + + return sockfd; +} + +#ifdef HAVE_SOCKETPAIR +int curl_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d socketpair() = %d %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d socketpair() = %ld %ld\n" : + "FD %s:%d socketpair() = %zd %zd\n"; + + int res = socketpair(domain, type, protocol, socket_vector); + + if(source && (0 == res)) + curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]); + + return res; +} +#endif + +curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen, + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d accept() = %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d accept() = %ld\n" : + "FD %s:%d accept() = %zd\n"; + + struct sockaddr *addr = (struct sockaddr *)saddr; + curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen; + + curl_socket_t sockfd = accept(s, addr, addrlen); + + if(source && (sockfd != CURL_SOCKET_BAD)) + curl_memlog(fmt, source, line, sockfd); + + return sockfd; +} + +/* separate function to allow libcurl to mark a "faked" close */ +void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d sclose(%d)\n": + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d sclose(%ld)\n": + "FD %s:%d sclose(%zd)\n"; + + if(source) + curl_memlog(fmt, source, line, sockfd); +} + +/* this is our own defined way to close sockets on *ALL* platforms */ +int curl_sclose(curl_socket_t sockfd, int line, const char *source) +{ + int res=sclose(sockfd); + curl_mark_sclose(sockfd, line, source); + return res; +} + +FILE *curl_fopen(const char *file, const char *mode, + int line, const char *source) +{ + FILE *res=fopen(file, mode); + + if(source) + curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", + source, line, file, mode, (void *)res); + + return res; +} + +#ifdef HAVE_FDOPEN +FILE *curl_fdopen(int filedes, const char *mode, + int line, const char *source) +{ + FILE *res=fdopen(filedes, mode); + + if(source) + curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n", + source, line, filedes, mode, (void *)res); + + return res; +} +#endif + +int curl_fclose(FILE *file, int line, const char *source) +{ + int res; + + assert(file != NULL); + + res=fclose(file); + + if(source) + curl_memlog("FILE %s:%d fclose(%p)\n", + source, line, (void *)file); + + return res; +} + +#define LOGLINE_BUFSIZE 1024 + +/* this does the writting to the memory tracking log file */ +void curl_memlog(const char *format, ...) +{ + char *buf; + int nchars; + va_list ap; + + if(!logfile) + return; + + buf = (Curl_cmalloc)(LOGLINE_BUFSIZE); + if(!buf) + return; + + va_start(ap, format); + nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap); + va_end(ap); + + if(nchars > LOGLINE_BUFSIZE - 1) + nchars = LOGLINE_BUFSIZE - 1; + + if(nchars > 0) + fwrite(buf, 1, nchars, logfile); + + (Curl_cfree)(buf); +} + +#endif /* CURLDEBUG */ diff --git a/libcurl/src/lib/memdebug.h b/libcurl/src/lib/memdebug.h new file mode 100644 index 0000000..cfac1e0 --- /dev/null +++ b/libcurl/src/lib/memdebug.h @@ -0,0 +1,176 @@ +#ifndef HEADER_CURL_MEMDEBUG_H +#define HEADER_CURL_MEMDEBUG_H +#ifdef CURLDEBUG +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * CAUTION: this header is designed to work when included by the app-side + * as well as the library. Do not mix with library internals! + */ + +#include "curl_setup.h" + +#include + +#define CURL_MT_LOGFNAME_BUFSIZE 512 + +#define logfile curl_debuglogfile + +extern FILE *logfile; + +/* memory functions */ +CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source); +CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line, + const char *source); +CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line, + const char *source); +CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source); +CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source); +#if defined(WIN32) && defined(UNICODE) +CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line, + const char *source); +#endif + +CURL_EXTERN void curl_memdebug(const char *logname); +CURL_EXTERN void curl_memlimit(long limit); +CURL_EXTERN void curl_memlog(const char *format, ...); + +/* file descriptor manipulators */ +CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol, + int line , const char *source); +CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd, + int line , const char *source); +CURL_EXTERN int curl_sclose(curl_socket_t sockfd, + int line , const char *source); +CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen, + int line, const char *source); +#ifdef HAVE_SOCKETPAIR +CURL_EXTERN int curl_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line , const char *source); +#endif + +/* FILE functions */ +CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line, + const char *source); +#ifdef HAVE_FDOPEN +CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line, + const char *source); +#endif +CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); + +#ifndef MEMDEBUG_NODEFINES + +/* Set this symbol on the command-line, recompile all lib-sources */ +#undef strdup +#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__) +#define malloc(size) curl_domalloc(size, __LINE__, __FILE__) +#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__) +#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__) +#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__) + +#ifdef WIN32 +# ifdef UNICODE +# undef wcsdup +# define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# undef _wcsdup +# define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# undef _tcsdup +# define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# else +# undef _tcsdup +# define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__) +# endif +#endif + +#define socket(domain,type,protocol)\ + curl_socket(domain, type, protocol, __LINE__, __FILE__) +#undef accept /* for those with accept as a macro */ +#define accept(sock,addr,len)\ + curl_accept(sock, addr, len, __LINE__, __FILE__) +#ifdef HAVE_SOCKETPAIR +#define socketpair(domain,type,protocol,socket_vector)\ + curl_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) +#endif + +#ifdef HAVE_GETADDRINFO +#if defined(getaddrinfo) && defined(__osf__) +/* OSF/1 and Tru64 have getaddrinfo as a define already, so we cannot define + our macro as for other platforms. Instead, we redefine the new name they + define getaddrinfo to become! */ +#define ogetaddrinfo(host,serv,hint,res) \ + curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__) +#else +#undef getaddrinfo +#define getaddrinfo(host,serv,hint,res) \ + curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__) +#endif +#endif /* HAVE_GETADDRINFO */ + +#ifdef HAVE_GETNAMEINFO +#undef getnameinfo +#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \ + curl_dogetnameinfo(sa, salen, host, hostlen, serv, servlen, flags, \ + __LINE__, __FILE__) +#endif /* HAVE_GETNAMEINFO */ + +#ifdef HAVE_FREEADDRINFO +#undef freeaddrinfo +#define freeaddrinfo(data) \ + curl_dofreeaddrinfo(data, __LINE__, __FILE__) +#endif /* HAVE_FREEADDRINFO */ + +/* sclose is probably already defined, redefine it! */ +#undef sclose +#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__) + +#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__) + +#undef fopen +#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__) +#undef fdopen +#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__) +#define fclose(file) curl_fclose(file,__LINE__,__FILE__) + +#endif /* MEMDEBUG_NODEFINES */ + +#endif /* CURLDEBUG */ + +/* +** Following section applies even when CURLDEBUG is not defined. +*/ + +#ifndef fake_sclose +#define fake_sclose(x) Curl_nop_stmt +#endif + +/* + * Curl_safefree defined as a macro to allow MemoryTracking feature + * to log free() calls at same location where Curl_safefree is used. + * This macro also assigns NULL to given pointer when free'd. + */ + +#define Curl_safefree(ptr) \ + do { free((ptr)); (ptr) = NULL;} WHILE_FALSE + +#endif /* HEADER_CURL_MEMDEBUG_H */ diff --git a/libcurl/src/lib/mprintf.c b/libcurl/src/lib/mprintf.c new file mode 100644 index 0000000..23070a7 --- /dev/null +++ b/libcurl/src/lib/mprintf.c @@ -0,0 +1,1142 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1999 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * + * Purpose: + * A merge of Bjorn Reese's format() function and Daniel's dsprintf() + * 1.0. A full blooded printf() clone with full support for $ + * everywhere (parameters, widths and precisions) including variabled + * sized parameters (like doubles, long longs, long doubles and even + * void * in 64-bit architectures). + * + * Current restrictions: + * - Max 128 parameters + * - No 'long double' support. + * + * If you ever want truly portable and good *printf() clones, the project that + * took on from here is named 'Trio' and you find more details on the trio web + * page at http://daniel.haxx.se/trio/ + */ + +#include "curl_setup.h" + +#if defined(DJGPP) && (DJGPP_MINOR < 4) +#undef _MPRINTF_REPLACE /* don't use x_was_used() here */ +#endif + +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef SIZEOF_LONG_DOUBLE +#define SIZEOF_LONG_DOUBLE 0 +#endif + +/* + * If SIZEOF_SIZE_T has not been defined, default to the size of long. + */ + +#ifndef SIZEOF_SIZE_T +# define SIZEOF_SIZE_T CURL_SIZEOF_LONG +#endif + +#ifdef HAVE_LONGLONG +# define LONG_LONG_TYPE long long +# define HAVE_LONG_LONG_TYPE +#else +# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define LONG_LONG_TYPE __int64 +# define HAVE_LONG_LONG_TYPE +# else +# undef LONG_LONG_TYPE +# undef HAVE_LONG_LONG_TYPE +# endif +#endif + +/* + * Non-ANSI integer extensions + */ + +#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \ + (defined(__WATCOMC__) && defined(__386__)) || \ + (defined(__POCC__) && defined(_MSC_VER)) || \ + (defined(_WIN32_WCE)) || \ + (defined(__MINGW32__)) || \ + (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)) +# define MP_HAVE_INT_EXTENSIONS +#endif + +/* + * Max integer data types that mprintf.c is capable + */ + +#ifdef HAVE_LONG_LONG_TYPE +# define mp_intmax_t LONG_LONG_TYPE +# define mp_uintmax_t unsigned LONG_LONG_TYPE +#else +# define mp_intmax_t long +# define mp_uintmax_t unsigned long +#endif + +#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */ +#define MAX_PARAMETERS 128 /* lame static limit */ + +#ifdef __AMIGA__ +# undef FORMAT_INT +#endif + +/* Lower-case digits. */ +static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +/* Upper-case digits. */ +static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +#define OUTCHAR(x) \ + do{ \ + if(stream((unsigned char)(x), (FILE *)data) != -1) \ + done++; \ + else \ + return done; /* return immediately on failure */ \ + } WHILE_FALSE + +/* Data type to read from the arglist */ +typedef enum { + FORMAT_UNKNOWN = 0, + FORMAT_STRING, + FORMAT_PTR, + FORMAT_INT, + FORMAT_INTPTR, + FORMAT_LONG, + FORMAT_LONGLONG, + FORMAT_DOUBLE, + FORMAT_LONGDOUBLE, + FORMAT_WIDTH /* For internal use */ +} FormatType; + +/* conversion and display flags */ +enum { + FLAGS_NEW = 0, + FLAGS_SPACE = 1<<0, + FLAGS_SHOWSIGN = 1<<1, + FLAGS_LEFT = 1<<2, + FLAGS_ALT = 1<<3, + FLAGS_SHORT = 1<<4, + FLAGS_LONG = 1<<5, + FLAGS_LONGLONG = 1<<6, + FLAGS_LONGDOUBLE = 1<<7, + FLAGS_PAD_NIL = 1<<8, + FLAGS_UNSIGNED = 1<<9, + FLAGS_OCTAL = 1<<10, + FLAGS_HEX = 1<<11, + FLAGS_UPPER = 1<<12, + FLAGS_WIDTH = 1<<13, /* '*' or '*$' used */ + FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */ + FLAGS_PREC = 1<<15, /* precision was specified */ + FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */ + FLAGS_CHAR = 1<<17, /* %c story */ + FLAGS_FLOATE = 1<<18, /* %e or %E */ + FLAGS_FLOATG = 1<<19 /* %g or %G */ +}; + +typedef struct { + FormatType type; + int flags; + long width; /* width OR width parameter number */ + long precision; /* precision OR precision parameter number */ + union { + char *str; + void *ptr; + union { + mp_intmax_t as_signed; + mp_uintmax_t as_unsigned; + } num; + double dnum; + } data; +} va_stack_t; + +struct nsprintf { + char *buffer; + size_t length; + size_t max; +}; + +struct asprintf { + char *buffer; /* allocated buffer */ + size_t len; /* length of string */ + size_t alloc; /* length of alloc */ + int fail; /* (!= 0) if an alloc has failed and thus + the output is not the complete data */ +}; + +static long dprintf_DollarString(char *input, char **end) +{ + int number=0; + while(ISDIGIT(*input)) { + number *= 10; + number += *input-'0'; + input++; + } + if(number && ('$'==*input++)) { + *end = input; + return number; + } + return 0; +} + +static bool dprintf_IsQualifierNoDollar(const char *fmt) +{ +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) { + return TRUE; + } +#endif + + switch(*fmt) { + case '-': case '+': case ' ': case '#': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'h': case 'l': case 'L': case 'z': case 'q': + case '*': case 'O': +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#endif + return TRUE; + + default: + return FALSE; + } +} + +/****************************************************************** + * + * Pass 1: + * Create an index with the type of each parameter entry and its + * value (may vary in size) + * + ******************************************************************/ + +static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, + va_list arglist) +{ + char *fmt = (char *)format; + int param_num = 0; + long this_param; + long width; + long precision; + int flags; + long max_param=0; + long i; + + while(*fmt) { + if(*fmt++ == '%') { + if(*fmt == '%') { + fmt++; + continue; /* while */ + } + + flags = FLAGS_NEW; + + /* Handle the positional case (N$) */ + + param_num++; + + this_param = dprintf_DollarString(fmt, &fmt); + if(0 == this_param) + /* we got no positional, get the next counter */ + this_param = param_num; + + if(this_param > max_param) + max_param = this_param; + + /* + * The parameter with number 'i' should be used. Next, we need + * to get SIZE and TYPE of the parameter. Add the information + * to our array. + */ + + width = 0; + precision = 0; + + /* Handle the flags */ + + while(dprintf_IsQualifierNoDollar(fmt)) { +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3)) { + flags |= FLAGS_LONG; + fmt += 3; + } + else if(!strncmp(fmt, "I64", 3)) { + flags |= FLAGS_LONGLONG; + fmt += 3; + } + else +#endif + + switch(*fmt++) { + case ' ': + flags |= FLAGS_SPACE; + break; + case '+': + flags |= FLAGS_SHOWSIGN; + break; + case '-': + flags |= FLAGS_LEFT; + flags &= ~FLAGS_PAD_NIL; + break; + case '#': + flags |= FLAGS_ALT; + break; + case '.': + flags |= FLAGS_PREC; + if('*' == *fmt) { + /* The precision is picked from a specified parameter */ + + flags |= FLAGS_PRECPARAM; + fmt++; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + precision = i; + else + precision = param_num; + + if(precision > max_param) + max_param = precision; + } + else { + flags |= FLAGS_PREC; + precision = strtol(fmt, &fmt, 10); + } + break; + case 'h': + flags |= FLAGS_SHORT; + break; +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; +#endif + case 'l': + if(flags & FLAGS_LONG) + flags |= FLAGS_LONGLONG; + else + flags |= FLAGS_LONG; + break; + case 'L': + flags |= FLAGS_LONGDOUBLE; + break; + case 'q': + flags |= FLAGS_LONGLONG; + break; + case 'z': + /* the code below generates a warning if -Wunreachable-code is + used */ +#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case 'O': +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case '0': + if(!(flags & FLAGS_LEFT)) + flags |= FLAGS_PAD_NIL; + /* FALLTHROUGH */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + flags |= FLAGS_WIDTH; + width = strtol(fmt-1, &fmt, 10); + break; + case '*': /* Special case */ + flags |= FLAGS_WIDTHPARAM; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + width = i; + else + width = param_num; + if(width > max_param) + max_param=width; + break; + default: + break; + } + } /* switch */ + + /* Handle the specifier */ + + i = this_param - 1; + + switch (*fmt) { + case 'S': + flags |= FLAGS_ALT; + /* FALLTHROUGH */ + case 's': + vto[i].type = FORMAT_STRING; + break; + case 'n': + vto[i].type = FORMAT_INTPTR; + break; + case 'p': + vto[i].type = FORMAT_PTR; + break; + case 'd': case 'i': + vto[i].type = FORMAT_INT; + break; + case 'u': + vto[i].type = FORMAT_INT; + flags |= FLAGS_UNSIGNED; + break; + case 'o': + vto[i].type = FORMAT_INT; + flags |= FLAGS_OCTAL; + break; + case 'x': + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UNSIGNED; + break; + case 'X': + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED; + break; + case 'c': + vto[i].type = FORMAT_INT; + flags |= FLAGS_CHAR; + break; + case 'f': + vto[i].type = FORMAT_DOUBLE; + break; + case 'e': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE; + break; + case 'E': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE|FLAGS_UPPER; + break; + case 'g': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG; + break; + case 'G': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG|FLAGS_UPPER; + break; + default: + vto[i].type = FORMAT_UNKNOWN; + break; + } /* switch */ + + vto[i].flags = flags; + vto[i].width = width; + vto[i].precision = precision; + + if(flags & FLAGS_WIDTHPARAM) { + /* we have the width specified from a parameter, so we make that + parameter's info setup properly */ + vto[i].width = width - 1; + i = width - 1; + vto[i].type = FORMAT_WIDTH; + vto[i].flags = FLAGS_NEW; + vto[i].precision = vto[i].width = 0; /* can't use width or precision + of width! */ + } + if(flags & FLAGS_PRECPARAM) { + /* we have the precision specified from a parameter, so we make that + parameter's info setup properly */ + vto[i].precision = precision - 1; + i = precision - 1; + vto[i].type = FORMAT_WIDTH; + vto[i].flags = FLAGS_NEW; + vto[i].precision = vto[i].width = 0; /* can't use width or precision + of width! */ + } + *endpos++ = fmt + 1; /* end of this sequence */ + } + } + + /* Read the arg list parameters into our data list */ + for(i=0; i$ sequence */ + param=dprintf_DollarString(f, &f); + + if(!param) + param = param_num; + else + --param; + + param_num++; /* increase this always to allow "%2$s %1$s %s" and then the + third %s will pick the 3rd argument */ + + p = &vto[param]; + + /* pick up the specified width */ + if(p->flags & FLAGS_WIDTHPARAM) + width = (long)vto[p->width].data.num.as_signed; + else + width = p->width; + + /* pick up the specified precision */ + if(p->flags & FLAGS_PRECPARAM) { + prec = (long)vto[p->precision].data.num.as_signed; + param_num++; /* since the precision is extraced from a parameter, we + must skip that to get to the next one properly */ + } + else if(p->flags & FLAGS_PREC) + prec = p->precision; + else + prec = -1; + + is_alt = (p->flags & FLAGS_ALT) ? 1 : 0; + + switch (p->type) { + case FORMAT_INT: + num = p->data.num.as_unsigned; + if(p->flags & FLAGS_CHAR) { + /* Character. */ + if(!(p->flags & FLAGS_LEFT)) + while(--width > 0) + OUTCHAR(' '); + OUTCHAR((char) num); + if(p->flags & FLAGS_LEFT) + while(--width > 0) + OUTCHAR(' '); + break; + } + if(p->flags & FLAGS_OCTAL) { + /* Octal unsigned integer. */ + base = 8; + goto unsigned_number; + } + else if(p->flags & FLAGS_HEX) { + /* Hexadecimal unsigned integer. */ + + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + base = 16; + goto unsigned_number; + } + else if(p->flags & FLAGS_UNSIGNED) { + /* Decimal unsigned integer. */ + base = 10; + goto unsigned_number; + } + + /* Decimal integer. */ + base = 10; + + is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0; + if(is_neg) { + /* signed_num might fail to hold absolute negative minimum by 1 */ + signed_num = p->data.num.as_signed + (mp_intmax_t)1; + signed_num = -signed_num; + num = (mp_uintmax_t)signed_num; + num += (mp_uintmax_t)1; + } + + goto number; + + unsigned_number: + /* Unsigned number of base BASE. */ + is_neg = 0; + + number: + /* Number of base BASE. */ + { + char *workend = &work[sizeof(work) - 1]; + char *w; + + /* Supply a default precision if none was given. */ + if(prec == -1) + prec = 1; + + /* Put the number in WORK. */ + w = workend; + while(num > 0) { + *w-- = digits[num % base]; + num /= base; + } + width -= (long)(workend - w); + prec -= (long)(workend - w); + + if(is_alt && base == 8 && prec <= 0) { + *w-- = '0'; + --width; + } + + if(prec > 0) { + width -= prec; + while(prec-- > 0) + *w-- = '0'; + } + + if(is_alt && base == 16) + width -= 2; + + if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) + --width; + + if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR(' '); + + if(is_neg) + OUTCHAR('-'); + else if(p->flags & FLAGS_SHOWSIGN) + OUTCHAR('+'); + else if(p->flags & FLAGS_SPACE) + OUTCHAR(' '); + + if(is_alt && base == 16) { + OUTCHAR('0'); + if(p->flags & FLAGS_UPPER) + OUTCHAR('X'); + else + OUTCHAR('x'); + } + + if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR('0'); + + /* Write the number. */ + while(++w <= workend) { + OUTCHAR(*w); + } + + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + } + break; + + case FORMAT_STRING: + /* String. */ + { + static const char null[] = "(nil)"; + const char *str; + size_t len; + + str = (char *) p->data.str; + if(str == NULL) { + /* Write null[] if there's space. */ + if(prec == -1 || prec >= (long) sizeof(null) - 1) { + str = null; + len = sizeof(null) - 1; + /* Disable quotes around (nil) */ + p->flags &= (~FLAGS_ALT); + } + else { + str = ""; + len = 0; + } + } + else if(prec != -1) + len = (size_t)prec; + else + len = strlen(str); + + width -= (long)len; + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + + if(!(p->flags&FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + + while((len-- > 0) && *str) + OUTCHAR(*str++); + if(p->flags&FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + } + break; + + case FORMAT_PTR: + /* Generic pointer. */ + { + void *ptr; + ptr = (void *) p->data.ptr; + if(ptr != NULL) { + /* If the pointer is not NULL, write it as a %#x spec. */ + base = 16; + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + is_alt = 1; + num = (size_t) ptr; + is_neg = 0; + goto number; + } + else { + /* Write "(nil)" for a nil pointer. */ + static const char strnil[] = "(nil)"; + const char *point; + + width -= (long)(sizeof(strnil) - 1); + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + for(point = strnil; *point != '\0'; ++point) + OUTCHAR(*point); + if(! (p->flags & FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + } + } + break; + + case FORMAT_DOUBLE: + { + char formatbuf[32]="%"; + char *fptr = &formatbuf[1]; + size_t left = sizeof(formatbuf)-strlen(formatbuf); + int len; + + width = -1; + if(p->flags & FLAGS_WIDTH) + width = p->width; + else if(p->flags & FLAGS_WIDTHPARAM) + width = (long)vto[p->width].data.num.as_signed; + + prec = -1; + if(p->flags & FLAGS_PREC) + prec = p->precision; + else if(p->flags & FLAGS_PRECPARAM) + prec = (long)vto[p->precision].data.num.as_signed; + + if(p->flags & FLAGS_LEFT) + *fptr++ = '-'; + if(p->flags & FLAGS_SHOWSIGN) + *fptr++ = '+'; + if(p->flags & FLAGS_SPACE) + *fptr++ = ' '; + if(p->flags & FLAGS_ALT) + *fptr++ = '#'; + + *fptr = 0; + + if(width >= 0) { + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, "%ld", width); + fptr += len; + left -= len; + } + if(prec >= 0) { + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, ".%ld", prec); + fptr += len; + } + if(p->flags & FLAGS_LONG) + *fptr++ = 'l'; + + if(p->flags & FLAGS_FLOATE) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e'); + else if(p->flags & FLAGS_FLOATG) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g'); + else + *fptr++ = 'f'; + + *fptr = 0; /* and a final zero termination */ + + /* NOTE NOTE NOTE!! Not all sprintf implementations return number of + output characters */ + (sprintf)(work, formatbuf, p->data.dnum); + + for(fptr=work; *fptr; fptr++) + OUTCHAR(*fptr); + } + break; + + case FORMAT_INTPTR: + /* Answer the count of characters written. */ +#ifdef HAVE_LONG_LONG_TYPE + if(p->flags & FLAGS_LONGLONG) + *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done; + else +#endif + if(p->flags & FLAGS_LONG) + *(long *) p->data.ptr = (long)done; + else if(!(p->flags & FLAGS_SHORT)) + *(int *) p->data.ptr = (int)done; + else + *(short *) p->data.ptr = (short)done; + break; + + default: + break; + } + f = *end++; /* goto end of %-code */ + + } + return done; +} + +/* fputc() look-alike */ +static int addbyter(int output, FILE *data) +{ + struct nsprintf *infop=(struct nsprintf *)data; + unsigned char outc = (unsigned char)output; + + if(infop->length < infop->max) { + /* only do this if we haven't reached max length yet */ + infop->buffer[0] = outc; /* store */ + infop->buffer++; /* increase pointer */ + infop->length++; /* we are now one byte larger */ + return outc; /* fputc() returns like this on success */ + } + return -1; +} + +int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, + va_list ap_save) +{ + int retcode; + struct nsprintf info; + + info.buffer = buffer; + info.length = 0; + info.max = maxlength; + + retcode = dprintf_formatf(&info, addbyter, format, ap_save); + if(info.max) { + /* we terminate this with a zero byte */ + if(info.max == info.length) + /* we're at maximum, scrap the last letter */ + info.buffer[-1] = 0; + else + info.buffer[0] = 0; + } + return retcode; +} + +int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save); + va_end(ap_save); + return retcode; +} + +/* fputc() look-alike */ +static int alloc_addbyter(int output, FILE *data) +{ + struct asprintf *infop=(struct asprintf *)data; + unsigned char outc = (unsigned char)output; + + if(!infop->buffer) { + infop->buffer = malloc(32); + if(!infop->buffer) { + infop->fail = 1; + return -1; /* fail */ + } + infop->alloc = 32; + infop->len =0; + } + else if(infop->len+1 >= infop->alloc) { + char *newptr; + + newptr = realloc(infop->buffer, infop->alloc*2); + + if(!newptr) { + infop->fail = 1; + return -1; /* fail */ + } + infop->buffer = newptr; + infop->alloc *= 2; + } + + infop->buffer[ infop->len ] = outc; + + infop->len++; + + return outc; /* fputc() returns like this on success */ +} + +char *curl_maprintf(const char *format, ...) +{ + va_list ap_save; /* argument pointer */ + int retcode; + struct asprintf info; + + info.buffer = NULL; + info.len = 0; + info.alloc = 0; + info.fail = 0; + + va_start(ap_save, format); + retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); + va_end(ap_save); + if((-1 == retcode) || info.fail) { + if(info.alloc) + free(info.buffer); + return NULL; + } + if(info.alloc) { + info.buffer[info.len] = 0; /* we terminate this with a zero byte */ + return info.buffer; + } + else + return strdup(""); +} + +char *curl_mvaprintf(const char *format, va_list ap_save) +{ + int retcode; + struct asprintf info; + + info.buffer = NULL; + info.len = 0; + info.alloc = 0; + info.fail = 0; + + retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); + if((-1 == retcode) || info.fail) { + if(info.alloc) + free(info.buffer); + return NULL; + } + + if(info.alloc) { + info.buffer[info.len] = 0; /* we terminate this with a zero byte */ + return info.buffer; + } + else + return strdup(""); +} + +static int storebuffer(int output, FILE *data) +{ + char **buffer = (char **)data; + unsigned char outc = (unsigned char)output; + **buffer = outc; + (*buffer)++; + return outc; /* act like fputc() ! */ +} + +int curl_msprintf(char *buffer, const char *format, ...) +{ + va_list ap_save; /* argument pointer */ + int retcode; + va_start(ap_save, format); + retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); + va_end(ap_save); + *buffer=0; /* we terminate this with a zero byte */ + return retcode; +} + +int curl_mprintf(const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + + retcode = dprintf_formatf(stdout, fputc, format, ap_save); + va_end(ap_save); + return retcode; +} + +int curl_mfprintf(FILE *whereto, const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + retcode = dprintf_formatf(whereto, fputc, format, ap_save); + va_end(ap_save); + return retcode; +} + +int curl_mvsprintf(char *buffer, const char *format, va_list ap_save) +{ + int retcode; + retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); + *buffer=0; /* we terminate this with a zero byte */ + return retcode; +} + +int curl_mvprintf(const char *format, va_list ap_save) +{ + return dprintf_formatf(stdout, fputc, format, ap_save); +} + +int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save) +{ + return dprintf_formatf(whereto, fputc, format, ap_save); +} diff --git a/libcurl/src/lib/multi.c b/libcurl/src/lib/multi.c new file mode 100644 index 0000000..cdba5a9 --- /dev/null +++ b/libcurl/src/lib/multi.c @@ -0,0 +1,2815 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "transfer.h" +#include "url.h" +#include "connect.h" +#include "progress.h" +#include "easyif.h" +#include "share.h" +#include "multiif.h" +#include "sendf.h" +#include "timeval.h" +#include "http.h" +#include "select.h" +#include "warnless.h" +#include "speedcheck.h" +#include "conncache.h" +#include "bundles.h" +#include "multihandle.h" +#include "pipeline.h" +#include "sigpipe.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97 + to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every + CURL handle takes 45-50 K memory, therefore this 3K are not significant. +*/ +#ifndef CURL_SOCKET_HASH_TABLE_SIZE +#define CURL_SOCKET_HASH_TABLE_SIZE 911 +#endif + +#define CURL_CONNECTION_HASH_SIZE 97 + +#define CURL_MULTI_HANDLE 0x000bab1e + +#define GOOD_MULTI_HANDLE(x) \ + ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE)) +#define GOOD_EASY_HANDLE(x) \ + ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER)) + +static void singlesocket(struct Curl_multi *multi, + struct SessionHandle *data); +static int update_timer(struct Curl_multi *multi); + +static bool isHandleAtHead(struct SessionHandle *handle, + struct curl_llist *pipeline); +static CURLMcode add_next_timeout(struct timeval now, + struct Curl_multi *multi, + struct SessionHandle *d); +static CURLMcode multi_timeout(struct Curl_multi *multi, + long *timeout_ms); + +#ifdef DEBUGBUILD +static const char * const statename[]={ + "INIT", + "CONNECT_PEND", + "CONNECT", + "WAITRESOLVE", + "WAITCONNECT", + "WAITPROXYCONNECT", + "SENDPROTOCONNECT", + "PROTOCONNECT", + "WAITDO", + "DO", + "DOING", + "DO_MORE", + "DO_DONE", + "WAITPERFORM", + "PERFORM", + "TOOFAST", + "DONE", + "COMPLETED", + "MSGSENT", +}; +#endif + +static void multi_freetimeout(void *a, void *b); + +/* always use this function to change state, to make debugging easier */ +static void mstate(struct SessionHandle *data, CURLMstate state +#ifdef DEBUGBUILD + , int lineno +#endif +) +{ + CURLMstate oldstate = data->mstate; + +#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) lineno; +#endif + + if(oldstate == state) + /* don't bother when the new state is the same as the old state */ + return; + + data->mstate = state; + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + if(data->mstate >= CURLM_STATE_CONNECT_PEND && + data->mstate < CURLM_STATE_COMPLETED) { + long connection_id = -5000; + + if(data->easy_conn) + connection_id = data->easy_conn->connection_id; + + infof(data, + "STATE: %s => %s handle %p; line %d (connection #%ld) \n", + statename[oldstate], statename[data->mstate], + (void *)data, lineno, connection_id); + } +#endif + + if(state == CURLM_STATE_COMPLETED) + /* changing to COMPLETED means there's one less easy handle 'alive' */ + data->multi->num_alive--; +} + +#ifndef DEBUGBUILD +#define multistate(x,y) mstate(x,y) +#else +#define multistate(x,y) mstate(x,y, __LINE__) +#endif + +/* + * We add one of these structs to the sockhash for a particular socket + */ + +struct Curl_sh_entry { + struct SessionHandle *easy; + int action; /* what action READ/WRITE this socket waits for */ + curl_socket_t socket; /* mainly to ease debugging */ + void *socketp; /* settable by users with curl_multi_assign() */ +}; +/* bits for 'action' having no bits means this socket is not expecting any + action */ +#define SH_READ 1 +#define SH_WRITE 2 + +/* make sure this socket is present in the hash for this handle */ +static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh, + curl_socket_t s, + struct SessionHandle *data) +{ + struct Curl_sh_entry *there = + Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t)); + struct Curl_sh_entry *check; + + if(there) + /* it is present, return fine */ + return there; + + /* not present, add it */ + check = calloc(1, sizeof(struct Curl_sh_entry)); + if(!check) + return NULL; /* major failure */ + + check->easy = data; + check->socket = s; + + /* make/add new hash entry */ + if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) { + free(check); + return NULL; /* major failure */ + } + + return check; /* things are good in sockhash land */ +} + + +/* delete the given socket + handle from the hash */ +static void sh_delentry(struct curl_hash *sh, curl_socket_t s) +{ + struct Curl_sh_entry *there = + Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t)); + + if(there) { + /* this socket is in the hash */ + /* We remove the hash entry. (This'll end up in a call to + sh_freeentry().) */ + Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t)); + } +} + +/* + * free a sockhash entry + */ +static void sh_freeentry(void *freethis) +{ + struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis; + + free(p); +} + +static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len) +{ + (void) k1_len; (void) k2_len; + + return (*((int *) k1)) == (*((int *) k2)); +} + +static size_t hash_fd(void *key, size_t key_length, size_t slots_num) +{ + int fd = *((int *) key); + (void) key_length; + + return (fd % (int)slots_num); +} + +/* + * sh_init() creates a new socket hash and returns the handle for it. + * + * Quote from README.multi_socket: + * + * "Some tests at 7000 and 9000 connections showed that the socket hash lookup + * is somewhat of a bottle neck. Its current implementation may be a bit too + * limiting. It simply has a fixed-size array, and on each entry in the array + * it has a linked list with entries. So the hash only checks which list to + * scan through. The code I had used so for used a list with merely 7 slots + * (as that is what the DNS hash uses) but with 7000 connections that would + * make an average of 1000 nodes in each list to run through. I upped that to + * 97 slots (I believe a prime is suitable) and noticed a significant speed + * increase. I need to reconsider the hash implementation or use a rather + * large default value like this. At 9000 connections I was still below 10us + * per call." + * + */ +static struct curl_hash *sh_init(int hashsize) +{ + return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare, + sh_freeentry); +} + +/* + * multi_addmsg() + * + * Called when a transfer is completed. Adds the given msg pointer to + * the list kept in the multi handle. + */ +static CURLMcode multi_addmsg(struct Curl_multi *multi, + struct Curl_message *msg) +{ + if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg)) + return CURLM_OUT_OF_MEMORY; + + return CURLM_OK; +} + +/* + * multi_freeamsg() + * + * Callback used by the llist system when a single list entry is destroyed. + */ +static void multi_freeamsg(void *a, void *b) +{ + (void)a; + (void)b; +} + +struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ + int chashsize) /* connection hash */ +{ + struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi)); + + if(!multi) + return NULL; + + multi->type = CURL_MULTI_HANDLE; + + multi->hostcache = Curl_mk_dnscache(); + if(!multi->hostcache) + goto error; + + multi->sockhash = sh_init(hashsize); + if(!multi->sockhash) + goto error; + + multi->conn_cache = Curl_conncache_init(chashsize); + if(!multi->conn_cache) + goto error; + + multi->msglist = Curl_llist_alloc(multi_freeamsg); + if(!multi->msglist) + 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 */ + multi->closure_handle = curl_easy_init(); + if(!multi->closure_handle) + goto error; + + multi->closure_handle->multi = multi; + multi->closure_handle->state.conn_cache = multi->conn_cache; + + multi->max_pipeline_length = 5; + + /* -1 means it not set by user, use the default value */ + multi->maxconnects = -1; + return (CURLM *) multi; + + error: + + Curl_hash_destroy(multi->sockhash); + multi->sockhash = NULL; + Curl_hash_destroy(multi->hostcache); + multi->hostcache = NULL; + Curl_conncache_destroy(multi->conn_cache); + multi->conn_cache = NULL; + Curl_close(multi->closure_handle); + multi->closure_handle = NULL; + Curl_llist_destroy(multi->msglist, NULL); + Curl_llist_destroy(multi->pending, NULL); + + free(multi); + return NULL; +} + +CURLM *curl_multi_init(void) +{ + return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE, + CURL_CONNECTION_HASH_SIZE); +} + +CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *easy_handle) +{ + struct curl_llist *timeoutlist; + struct Curl_multi *multi = (struct Curl_multi *)multi_handle; + struct SessionHandle *data = (struct SessionHandle *)easy_handle; + + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + /* Verify that we got a somewhat good easy handle too */ + if(!GOOD_EASY_HANDLE(easy_handle)) + return CURLM_BAD_EASY_HANDLE; + + /* Prevent users from adding same easy handle more than once and prevent + adding to more than one multi stack */ + if(data->multi) + return CURLM_ADDED_ALREADY; + + /* Allocate and initialize timeout list for easy handle */ + timeoutlist = Curl_llist_alloc(multi_freetimeout); + if(!timeoutlist) + return CURLM_OUT_OF_MEMORY; + + /* + * No failure allowed in this function beyond this point. And no + * modification of easy nor multi handle allowed before this except for + * potential multi's connection cache growing which won't be undone in this + * function no matter what. + */ + + /* Make easy handle use timeout list initialized above */ + data->state.timeoutlist = timeoutlist; + timeoutlist = NULL; + + /* set the easy handle */ + multistate(data, CURLM_STATE_INIT); + + if((data->set.global_dns_cache) && + (data->dns.hostcachetype != HCACHE_GLOBAL)) { + /* global dns cache was requested but still isn't */ + struct curl_hash *global = Curl_global_host_cache_init(); + if(global) { + /* only do this if the global cache init works */ + data->dns.hostcache = global; + data->dns.hostcachetype = HCACHE_GLOBAL; + } + } + /* for multi interface connections, we share DNS cache automatically if the + easy handle's one is currently not set. */ + else if(!data->dns.hostcache || + (data->dns.hostcachetype == HCACHE_NONE)) { + data->dns.hostcache = multi->hostcache; + data->dns.hostcachetype = HCACHE_MULTI; + } + + /* Point to the multi's connection cache */ + data->state.conn_cache = multi->conn_cache; + + data->state.infilesize = data->set.filesize; + + /* This adds the new entry at the 'end' of the doubly-linked circular + list of SessionHandle structs to try and maintain a FIFO queue so + the pipelined requests are in order. */ + + /* We add this new entry last in the list. */ + + data->next = NULL; /* end of the line */ + if(multi->easyp) { + struct SessionHandle *last = multi->easylp; + last->next = data; + data->prev = last; + multi->easylp = data; /* the new last node */ + } + else { + /* first node, make both prev and next be NULL! */ + data->next = NULL; + data->prev = NULL; + multi->easylp = multi->easyp = data; /* both first and last */ + } + + /* make the SessionHandle refer back to this multi handle */ + data->multi = multi_handle; + + /* Set the timeout for this handle to expire really soon so that it will + be taken care of even when this handle is added in the midst of operation + when only the curl_multi_socket() API is used. During that flow, only + sockets that time-out or have actions will be dealt with. Since this + handle has no action yet, we make sure it times out to get things to + happen. */ + Curl_expire(data, 1); + + /* increase the node-counter */ + multi->num_easy++; + + /* increase the alive-counter */ + multi->num_alive++; + + /* A somewhat crude work-around for a little glitch in update_timer() that + happens if the lastcall time is set to the same time when the handle is + removed as when the next handle is added, as then the check in + update_timer() that prevents calling the application multiple times with + the same timer infor will not trigger and then the new handle's timeout + will not be notified to the app. + + The work-around is thus simply to clear the 'lastcall' variable to force + update_timer() to always trigger a callback to the app when a new easy + handle is added */ + memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); + + update_timer(multi); + return CURLM_OK; +} + +#if 0 +/* Debug-function, used like this: + * + * Curl_hash_print(multi->sockhash, debug_print_sock_hash); + * + * Enable the hash print function first by editing hash.c + */ +static void debug_print_sock_hash(void *p) +{ + struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p; + + fprintf(stderr, " [easy %p/magic %x/socket %d]", + (void *)sh->data, sh->data->magic, (int)sh->socket); +} +#endif + +CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct SessionHandle *easy = curl_handle; + struct SessionHandle *data = easy; + bool premature; + bool easy_owns_conn; + struct curl_llist_element *e; + + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + /* Verify that we got a somewhat good easy handle too */ + if(!GOOD_EASY_HANDLE(curl_handle)) + return CURLM_BAD_EASY_HANDLE; + + /* Prevent users from trying to remove same easy handle more than once */ + if(!data->multi) + return CURLM_OK; /* it is already removed so let's say it is fine! */ + + premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE; + easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ? + TRUE : FALSE; + + /* If the 'state' is not INIT or COMPLETED, we might need to do something + nice to put the easy_handle in a good known state when this returns. */ + if(premature) { + /* this handle is "alive" so we need to count down the total number of + alive connections when this is removed */ + multi->num_alive--; + + /* When this handle gets removed, other handles may be able to get the + connection */ + Curl_multi_process_pending_handles(multi); + } + + if(data->easy_conn && + data->mstate > CURLM_STATE_DO && + data->mstate < CURLM_STATE_COMPLETED) { + /* If the handle is in a pipeline and has started sending off its + request but not received its response yet, we need to close + connection. */ + connclose(data->easy_conn, "Removed with partial response"); + /* Set connection owner so that Curl_done() closes it. + We can safely do this here since connection is killed. */ + data->easy_conn->data = easy; + easy_owns_conn = TRUE; + } + + /* The timer must be shut down before data->multi is set to NULL, + else the timenode will remain in the splay tree after + curl_easy_cleanup is called. */ + Curl_expire(data, 0); + + /* destroy the timeout list that is held in the easy handle */ + if(data->state.timeoutlist) { + Curl_llist_destroy(data->state.timeoutlist, NULL); + data->state.timeoutlist = NULL; + } + + if(data->dns.hostcachetype == HCACHE_MULTI) { + /* stop using the multi handle's DNS cache */ + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + + if(data->easy_conn) { + + /* we must call Curl_done() here (if we still "own it") so that we don't + leave a half-baked one around */ + if(easy_owns_conn) { + + /* Curl_done() clears the conn->data field to lose the association + between the easy handle and the connection + + Note that this ignores the return code simply because there's + nothing really useful to do with it anyway! */ + (void)Curl_done(&data->easy_conn, data->result, premature); + } + else + /* Clear connection pipelines, if Curl_done above was not called */ + Curl_getoff_all_pipelines(data, data->easy_conn); + } + + Curl_wildcard_dtor(&data->wildcard); + + /* as this was using a shared connection cache we clear the pointer to that + since we're not part of that multi handle anymore */ + data->state.conn_cache = NULL; + + /* change state without using multistate(), only to make singlesocket() do + what we want */ + data->mstate = CURLM_STATE_COMPLETED; + singlesocket(multi, easy); /* to let the application know what sockets that + vanish with this handle */ + + /* Remove the association between the connection and the handle */ + if(data->easy_conn) { + data->easy_conn->data = NULL; + data->easy_conn = NULL; + } + + data->multi = NULL; /* clear the association to this multi handle */ + + /* make sure there's no pending message in the queue sent from this easy + handle */ + + for(e = multi->msglist->head; e; e = e->next) { + struct Curl_message *msg = e->ptr; + + if(msg->extmsg.easy_handle == easy) { + Curl_llist_remove(multi->msglist, e, NULL); + /* there can only be one from this specific handle */ + break; + } + } + + /* make the previous node point to our next */ + if(data->prev) + data->prev->next = data->next; + else + multi->easyp = data->next; /* point to first node */ + + /* make our next point to our previous node */ + if(data->next) + data->next->prev = data->prev; + else + multi->easylp = data->prev; /* point to last node */ + + /* NOTE NOTE NOTE + We do not touch the easy handle here! */ + multi->num_easy--; /* one less to care about now */ + + update_timer(multi); + return CURLM_OK; +} + +CURL_STATIC bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi) +{ + return (multi && multi->pipelining_enabled) ? TRUE : FALSE; +} + +CURL_STATIC void Curl_multi_handlePipeBreak(struct SessionHandle *data) +{ + data->easy_conn = NULL; +} + +static int waitconnect_getsock(struct connectdata *conn, + curl_socket_t *sock, + int numsocks) +{ + int i; + int s=0; + int rc=0; + + if(!numsocks) + return GETSOCK_BLANK; + + for(i=0; i<2; i++) { + if(conn->tempsock[i] != CURL_SOCKET_BAD) { + sock[s] = conn->tempsock[i]; + rc |= GETSOCK_WRITESOCK(s++); + } + } + + return rc; +} + +static int waitproxyconnect_getsock(struct connectdata *conn, + curl_socket_t *sock, + int numsocks) +{ + if(!numsocks) + return GETSOCK_BLANK; + + sock[0] = conn->sock[FIRSTSOCKET]; + + /* when we've sent a CONNECT to a proxy, we should rather wait for the + socket to become readable to be able to get the response headers */ + if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) + return GETSOCK_READSOCK(0); + + return GETSOCK_WRITESOCK(0); +} + +static int domore_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn && conn->handler->domore_getsock) + return conn->handler->domore_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} + +/* returns bitmapped flags for this handle and its sockets */ +static int multi_getsock(struct SessionHandle *data, + curl_socket_t *socks, /* points to numsocks number + of sockets */ + int numsocks) +{ + /* If the pipe broke, or if there's no connection left for this easy handle, + then we MUST bail out now with no bitmask set. The no connection case can + happen when this is called from curl_multi_remove_handle() => + singlesocket() => multi_getsock(). + */ + if(data->state.pipe_broke || !data->easy_conn) + return 0; + + if(data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_COMPLETED) { + /* Set up ownership correctly */ + data->easy_conn->data = data; + } + + switch(data->mstate) { + default: +#if 0 /* switch back on these cases to get the compiler to check for all enums + to be present */ + case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */ + case CURLM_STATE_COMPLETED: + case CURLM_STATE_MSGSENT: + case CURLM_STATE_INIT: + case CURLM_STATE_CONNECT: + case CURLM_STATE_WAITDO: + case CURLM_STATE_DONE: + case CURLM_STATE_LAST: + /* this will get called with CURLM_STATE_COMPLETED when a handle is + removed */ +#endif + return 0; + + case CURLM_STATE_WAITRESOLVE: + return Curl_resolver_getsock(data->easy_conn, socks, numsocks); + + case CURLM_STATE_PROTOCONNECT: + case CURLM_STATE_SENDPROTOCONNECT: + return Curl_protocol_getsock(data->easy_conn, socks, numsocks); + + case CURLM_STATE_DO: + case CURLM_STATE_DOING: + return Curl_doing_getsock(data->easy_conn, socks, numsocks); + + case CURLM_STATE_WAITPROXYCONNECT: + return waitproxyconnect_getsock(data->easy_conn, socks, numsocks); + + case CURLM_STATE_WAITCONNECT: + return waitconnect_getsock(data->easy_conn, socks, numsocks); + + case CURLM_STATE_DO_MORE: + return domore_getsock(data->easy_conn, socks, numsocks); + + case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch + to waiting for the same as the *PERFORM + states */ + case CURLM_STATE_PERFORM: + case CURLM_STATE_WAITPERFORM: + return Curl_single_getsock(data->easy_conn, socks, numsocks); + } + +} + +CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, fd_set *write_fd_set, + fd_set *exc_fd_set, int *max_fd) +{ + /* Scan through all the easy handles to get the file descriptors set. + Some easy handles may not have connected to the remote host yet, + and then we must make sure that is done. */ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct SessionHandle *data; + int this_max_fd=-1; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int bitmap; + int i; + (void)exc_fd_set; /* not used */ + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + data=multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) { + FD_SET(sockbunch[i], read_fd_set); + s = sockbunch[i]; + } + if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) { + FD_SET(sockbunch[i], write_fd_set); + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) + /* this socket is unused, break out of loop */ + break; + else { + if((int)s > this_max_fd) + this_max_fd = (int)s; + } + } + + data = data->next; /* check next handle */ + } + + *max_fd = this_max_fd; + + return CURLM_OK; +} + +CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct SessionHandle *data; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int bitmap; + unsigned int i; + unsigned int nfds = 0; + unsigned int curlfds; + struct pollfd *ufds = NULL; + long timeout_internal; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + /* If the internally desired timeout is actually shorter than requested from + the outside, then use the shorter time! But only if the internal timer + is actually larger than -1! */ + (void)multi_timeout(multi, &timeout_internal); + if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms)) + timeout_ms = (int)timeout_internal; + + /* Count up how many fds we have from the multi handle */ + data=multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if(bitmap & GETSOCK_READSOCK(i)) { + ++nfds; + s = sockbunch[i]; + } + if(bitmap & GETSOCK_WRITESOCK(i)) { + ++nfds; + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) { + break; + } + } + + data = data->next; /* check next handle */ + } + + curlfds = nfds; /* number of internal file descriptors */ + nfds += extra_nfds; /* add the externally provided ones */ + + if(nfds || extra_nfds) { + ufds = malloc(nfds * sizeof(struct pollfd)); + if(!ufds) + return CURLM_OUT_OF_MEMORY; + } + nfds = 0; + + /* only do the second loop if we found descriptors in the first stage run + above */ + + if(curlfds) { + /* Add the curl handles to our pollfds first */ + data=multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if(bitmap & GETSOCK_READSOCK(i)) { + ufds[nfds].fd = sockbunch[i]; + ufds[nfds].events = POLLIN; + ++nfds; + s = sockbunch[i]; + } + if(bitmap & GETSOCK_WRITESOCK(i)) { + ufds[nfds].fd = sockbunch[i]; + ufds[nfds].events = POLLOUT; + ++nfds; + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) { + break; + } + } + + data = data->next; /* check next handle */ + } + } + + /* Add external file descriptions from poll-like struct curl_waitfd */ + for(i = 0; i < extra_nfds; i++) { + ufds[nfds].fd = extra_fds[i].fd; + ufds[nfds].events = 0; + if(extra_fds[i].events & CURL_WAIT_POLLIN) + ufds[nfds].events |= POLLIN; + if(extra_fds[i].events & CURL_WAIT_POLLPRI) + ufds[nfds].events |= POLLPRI; + if(extra_fds[i].events & CURL_WAIT_POLLOUT) + ufds[nfds].events |= POLLOUT; + ++nfds; + } + + if(nfds) { + /* wait... */ + infof(data, "Curl_poll(%d ds, %d ms)\n", nfds, timeout_ms); + i = Curl_poll(ufds, nfds, timeout_ms); + + if(i) { + unsigned int j; + /* copy revents results from the poll to the curl_multi_wait poll + struct, the bit values of the actual underlying poll() implementation + may not be the same as the ones in the public libcurl API! */ + for(j = 0; j < extra_nfds; j++) { + unsigned short mask = 0; + unsigned r = ufds[curlfds + j].revents; + + if(r & POLLIN) + mask |= CURL_WAIT_POLLIN; + if(r & POLLOUT) + mask |= CURL_WAIT_POLLOUT; + if(r & POLLPRI) + mask |= CURL_WAIT_POLLPRI; + + extra_fds[j].revents = mask; + } + } + } + else + i = 0; + + free(ufds); + if(ret) + *ret = i; + return CURLM_OK; +} + +static CURLMcode multi_runsingle(struct Curl_multi *multi, + struct timeval now, + struct SessionHandle *data) +{ + struct Curl_message *msg = NULL; + bool connected; + bool async; + bool protocol_connect = FALSE; + bool dophase_done = FALSE; + bool done = FALSE; + CURLMcode rc; + CURLcode result = CURLE_OK; + struct SingleRequest *k; + long timeout_ms; + int control; + + if(!GOOD_EASY_HANDLE(data)) + return CURLM_BAD_EASY_HANDLE; + + do { + bool disconnect_conn = FALSE; + rc = CURLM_OK; + + /* Handle the case when the pipe breaks, i.e., the connection + we're using gets cleaned up and we're left with nothing. */ + if(data->state.pipe_broke) { + infof(data, "Pipe broke: handle %p, url = %s\n", + (void *)data, data->state.path); + + if(data->mstate < CURLM_STATE_COMPLETED) { + /* Head back to the CONNECT state */ + multistate(data, CURLM_STATE_CONNECT); + rc = CURLM_CALL_MULTI_PERFORM; + result = CURLE_OK; + } + + data->state.pipe_broke = FALSE; + data->easy_conn = NULL; + continue; + } + + if(!data->easy_conn && + data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_DONE) { + /* In all these states, the code will blindly access 'data->easy_conn' + so this is precaution that it isn't NULL. And it silences static + analyzers. */ + failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate); + return CURLM_INTERNAL_ERROR; + } + + if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_COMPLETED) + /* Make sure we set the connection's current owner */ + data->easy_conn->data = data; + + if(data->easy_conn && + (data->mstate >= CURLM_STATE_CONNECT) && + (data->mstate < CURLM_STATE_COMPLETED)) { + /* we need to wait for the connect state as only then is the start time + stored, but we must not check already completed handles */ + + timeout_ms = Curl_timeleft(data, &now, + (data->mstate <= CURLM_STATE_WAITDO)? + TRUE:FALSE); + + if(timeout_ms < 0) { + /* Handle timed out */ + if(data->mstate == CURLM_STATE_WAITRESOLVE) + failf(data, "Resolving timed out after %ld milliseconds", + Curl_tvdiff(now, data->progress.t_startsingle)); + else if(data->mstate == CURLM_STATE_WAITCONNECT) + failf(data, "Connection timed out after %ld milliseconds", + Curl_tvdiff(now, data->progress.t_startsingle)); + else { + k = &data->req; + if(k->size != -1) { + failf(data, "Operation timed out after %ld milliseconds with %" + CURL_FORMAT_CURL_OFF_T " out of %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_tvdiff(k->now, data->progress.t_startsingle), + k->bytecount, k->size); + } + else { + failf(data, "Operation timed out after %ld milliseconds with %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_tvdiff(now, data->progress.t_startsingle), + k->bytecount); + } + } + + /* Force connection closed if the connection has indeed been used */ + if(data->mstate > CURLM_STATE_DO) { + connclose(data->easy_conn, "Disconnected with pending data"); + disconnect_conn = TRUE; + } + result = CURLE_OPERATION_TIMEDOUT; + (void)Curl_done(&data->easy_conn, result, TRUE); + /* Skip the statemachine and go directly to error handling section. */ + goto statemachine_end; + } + } + + switch(data->mstate) { + case CURLM_STATE_INIT: + /* init this transfer. */ + result=Curl_pretransfer(data); + + if(!result) { + /* after init, go CONNECT */ + multistate(data, CURLM_STATE_CONNECT); + Curl_pgrsTime(data, TIMER_STARTOP); + rc = CURLM_CALL_MULTI_PERFORM; + } + break; + + case CURLM_STATE_CONNECT_PEND: + /* We will stay here until there is a connection available. Then + we try again in the CURLM_STATE_CONNECT state. */ + break; + + case CURLM_STATE_CONNECT: + /* Connect. We want to get a connection identifier filled in. */ + Curl_pgrsTime(data, TIMER_STARTSINGLE); + result = Curl_connect(data, &data->easy_conn, + &async, &protocol_connect); + if(CURLE_NO_CONNECTION_AVAILABLE == result) { + /* There was no connection available. We will go to the pending + state and wait for an available connection. */ + multistate(data, CURLM_STATE_CONNECT_PEND); + + /* add this handle to the list of connect-pending handles */ + if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data)) + result = CURLE_OUT_OF_MEMORY; + else + result = CURLE_OK; + break; + } + + if(!result) { + /* Add this handle to the send or pend pipeline */ + result = Curl_add_handle_to_pipeline(data, data->easy_conn); + if(result) + disconnect_conn = TRUE; + else { + if(async) + /* We're now waiting for an asynchronous name lookup */ + multistate(data, CURLM_STATE_WAITRESOLVE); + else { + /* after the connect has been sent off, go WAITCONNECT unless the + protocol connect is already done and we can go directly to + WAITDO or DO! */ + rc = CURLM_CALL_MULTI_PERFORM; + + if(protocol_connect) + multistate(data, multi->pipelining_enabled? + CURLM_STATE_WAITDO:CURLM_STATE_DO); + else { +#ifndef CURL_DISABLE_HTTP + if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + else +#endif + multistate(data, CURLM_STATE_WAITCONNECT); + } + } + } + } + break; + + case CURLM_STATE_WAITRESOLVE: + /* awaiting an asynch name resolve to complete */ + { + struct Curl_dns_entry *dns = NULL; + struct connectdata *conn = data->easy_conn; + + /* check if we have the name resolved by now */ + dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port); + + if(dns) { +#ifdef CURLRES_ASYNCH + conn->async.dns = dns; + conn->async.done = TRUE; +#endif + result = CURLE_OK; + infof(data, "Hostname was found in DNS cache\n"); + } + + if(!dns) + result = Curl_resolver_is_resolved(data->easy_conn, &dns); + + /* Update sockets here, because the socket(s) may have been + closed and the application thus needs to be told, even if it + is likely that the same socket(s) will again be used further + down. If the name has not yet been resolved, it is likely + that new sockets have been opened in an attempt to contact + another resolver. */ + singlesocket(multi, data); + + if(dns) { + /* Perform the next step in the connection phase, and then move on + to the WAITCONNECT state */ + result = Curl_async_resolved(data->easy_conn, &protocol_connect); + + if(result) + /* if Curl_async_resolved() returns failure, the connection struct + is already freed and gone */ + data->easy_conn = NULL; /* no more connection */ + else { + /* call again please so that we get the next socket setup */ + rc = CURLM_CALL_MULTI_PERFORM; + if(protocol_connect) + multistate(data, multi->pipelining_enabled? + CURLM_STATE_WAITDO:CURLM_STATE_DO); + else { +#ifndef CURL_DISABLE_HTTP + if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + else +#endif + multistate(data, CURLM_STATE_WAITCONNECT); + } + } + } + + if(result) { + /* failure detected */ + disconnect_conn = TRUE; + break; + } + } + break; + +#ifndef CURL_DISABLE_HTTP + case CURLM_STATE_WAITPROXYCONNECT: + /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ + result = Curl_http_connect(data->easy_conn, &protocol_connect); + + rc = CURLM_CALL_MULTI_PERFORM; + if(data->easy_conn->bits.proxy_connect_closed) { + /* connect back to proxy again */ + result = CURLE_OK; + multistate(data, CURLM_STATE_CONNECT); + } + else if(!result) { + if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE) + /* initiate protocol connect phase */ + multistate(data, CURLM_STATE_SENDPROTOCONNECT); + } + break; +#endif + + case CURLM_STATE_WAITCONNECT: + /* awaiting a completion of an asynch TCP connect */ + result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected); + if(connected && !result) { + rc = CURLM_CALL_MULTI_PERFORM; + multistate(data, data->easy_conn->bits.tunnel_proxy? + CURLM_STATE_WAITPROXYCONNECT: + CURLM_STATE_SENDPROTOCONNECT); + } + else if(result) { + /* failure detected */ + /* Just break, the cleaning up is handled all in one place */ + disconnect_conn = TRUE; + break; + } + break; + + case CURLM_STATE_SENDPROTOCONNECT: + result = Curl_protocol_connect(data->easy_conn, &protocol_connect); + if(!protocol_connect) + /* switch to waiting state */ + multistate(data, CURLM_STATE_PROTOCONNECT); + else if(!result) { + /* protocol connect has completed, go WAITDO or DO */ + multistate(data, multi->pipelining_enabled? + CURLM_STATE_WAITDO:CURLM_STATE_DO); + rc = CURLM_CALL_MULTI_PERFORM; + } + else if(result) { + /* failure detected */ + Curl_posttransfer(data); + Curl_done(&data->easy_conn, result, TRUE); + disconnect_conn = TRUE; + } + break; + + case CURLM_STATE_PROTOCONNECT: + /* protocol-specific connect phase */ + result = Curl_protocol_connecting(data->easy_conn, &protocol_connect); + if(!result && protocol_connect) { + /* after the connect has completed, go WAITDO or DO */ + multistate(data, multi->pipelining_enabled? + CURLM_STATE_WAITDO:CURLM_STATE_DO); + rc = CURLM_CALL_MULTI_PERFORM; + } + else if(result) { + /* failure detected */ + Curl_posttransfer(data); + Curl_done(&data->easy_conn, result, TRUE); + disconnect_conn = TRUE; + } + break; + + case CURLM_STATE_WAITDO: + /* Wait for our turn to DO when we're pipelining requests */ +#ifdef DEBUGBUILD + infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n", + data->easy_conn->connection_id, + data->easy_conn->send_pipe->size, + data->easy_conn->writechannel_inuse?"TRUE":"FALSE", + isHandleAtHead(data, + data->easy_conn->send_pipe)?"TRUE":"FALSE"); +#endif + if(!data->easy_conn->writechannel_inuse && + isHandleAtHead(data, + data->easy_conn->send_pipe)) { + /* Grab the channel */ + data->easy_conn->writechannel_inuse = TRUE; + multistate(data, CURLM_STATE_DO); + rc = CURLM_CALL_MULTI_PERFORM; + } + break; + + case CURLM_STATE_DO: + if(data->set.connect_only) { + /* keep connection open for application to use the socket */ + connkeep(data->easy_conn, "CONNECT_ONLY"); + multistate(data, CURLM_STATE_DONE); + result = CURLE_OK; + rc = CURLM_CALL_MULTI_PERFORM; + } + else { + /* Perform the protocol's DO action */ + result = Curl_do(&data->easy_conn, &dophase_done); + + /* When Curl_do() returns failure, data->easy_conn might be NULL! */ + + if(!result) { + if(!dophase_done) { + /* some steps needed for wildcard matching */ + if(data->set.wildcardmatch) { + struct WildcardData *wc = &data->wildcard; + if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) { + /* skip some states if it is important */ + Curl_done(&data->easy_conn, CURLE_OK, FALSE); + multistate(data, CURLM_STATE_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + break; + } + } + /* DO was not completed in one function call, we must continue + DOING... */ + multistate(data, CURLM_STATE_DOING); + rc = CURLM_OK; + } + + /* after DO, go DO_DONE... or DO_MORE */ + else if(data->easy_conn->bits.do_more) { + /* we're supposed to do more, but we need to sit down, relax + and wait a little while first */ + multistate(data, CURLM_STATE_DO_MORE); + rc = CURLM_OK; + } + else { + /* we're done with the DO, now DO_DONE */ + multistate(data, CURLM_STATE_DO_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + else if((CURLE_SEND_ERROR == result) && + data->easy_conn->bits.reuse) { + /* + * In this situation, a connection that we were trying to use + * may have unexpectedly died. If possible, send the connection + * back to the CONNECT phase so we can try again. + */ + char *newurl = NULL; + followtype follow=FOLLOW_NONE; + CURLcode drc; + bool retry = FALSE; + + drc = Curl_retry_request(data->easy_conn, &newurl); + if(drc) { + /* a failure here pretty much implies an out of memory */ + result = drc; + disconnect_conn = TRUE; + } + else + retry = (newurl)?TRUE:FALSE; + + Curl_posttransfer(data); + drc = Curl_done(&data->easy_conn, result, FALSE); + + /* When set to retry the connection, we must to go back to + * the CONNECT state */ + if(retry) { + if(!drc || (drc == CURLE_SEND_ERROR)) { + follow = FOLLOW_RETRY; + drc = Curl_follow(data, newurl, follow); + if(!drc) { + multistate(data, CURLM_STATE_CONNECT); + rc = CURLM_CALL_MULTI_PERFORM; + result = CURLE_OK; + } + else { + /* Follow failed */ + result = drc; + free(newurl); + } + } + else { + /* done didn't return OK or SEND_ERROR */ + result = drc; + free(newurl); + } + } + else { + /* Have error handler disconnect conn if we can't retry */ + disconnect_conn = TRUE; + free(newurl); + } + } + else { + /* failure detected */ + Curl_posttransfer(data); + if(data->easy_conn) + Curl_done(&data->easy_conn, result, FALSE); + disconnect_conn = TRUE; + } + } + break; + + case CURLM_STATE_DOING: + /* we continue DOING until the DO phase is complete */ + result = Curl_protocol_doing(data->easy_conn, + &dophase_done); + if(!result) { + if(dophase_done) { + /* after DO, go DO_DONE or DO_MORE */ + multistate(data, data->easy_conn->bits.do_more? + CURLM_STATE_DO_MORE: + CURLM_STATE_DO_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } /* dophase_done */ + } + else { + /* failure detected */ + Curl_posttransfer(data); + Curl_done(&data->easy_conn, result, FALSE); + disconnect_conn = TRUE; + } + break; + + case CURLM_STATE_DO_MORE: + /* + * When we are connected, DO MORE and then go DO_DONE + */ + result = Curl_do_more(data->easy_conn, &control); + + /* No need to remove this handle from the send pipeline here since that + is done in Curl_done() */ + if(!result) { + if(control) { + /* if positive, advance to DO_DONE + if negative, go back to DOING */ + multistate(data, control==1? + CURLM_STATE_DO_DONE: + CURLM_STATE_DOING); + rc = CURLM_CALL_MULTI_PERFORM; + } + else + /* stay in DO_MORE */ + rc = CURLM_OK; + } + else { + /* failure detected */ + Curl_posttransfer(data); + Curl_done(&data->easy_conn, result, FALSE); + disconnect_conn = TRUE; + } + break; + + case CURLM_STATE_DO_DONE: + /* Move ourselves from the send to recv pipeline */ + Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn); + /* Check if we can move pending requests to send pipe */ + Curl_multi_process_pending_handles(multi); + + /* Only perform the transfer if there's a good socket to work with. + Having both BAD is a signal to skip immediately to DONE */ + if((data->easy_conn->sockfd != CURL_SOCKET_BAD) || + (data->easy_conn->writesockfd != CURL_SOCKET_BAD)) + multistate(data, CURLM_STATE_WAITPERFORM); + else + multistate(data, CURLM_STATE_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + break; + + case CURLM_STATE_WAITPERFORM: + /* Wait for our turn to PERFORM */ + if(!data->easy_conn->readchannel_inuse && + isHandleAtHead(data, + data->easy_conn->recv_pipe)) { + /* Grab the channel */ + data->easy_conn->readchannel_inuse = TRUE; + multistate(data, CURLM_STATE_PERFORM); + rc = CURLM_CALL_MULTI_PERFORM; + } +#ifdef DEBUGBUILD + else { + infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n", + data->easy_conn->connection_id, + data->easy_conn->recv_pipe->size, + data->easy_conn->readchannel_inuse?"TRUE":"FALSE", + isHandleAtHead(data, + data->easy_conn->recv_pipe)?"TRUE":"FALSE"); + } +#endif + break; + + case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */ + /* if both rates are within spec, resume transfer */ + if(Curl_pgrsUpdate(data->easy_conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, now); + + if(( (data->set.max_send_speed == 0) || + (data->progress.ulspeed < data->set.max_send_speed )) && + ( (data->set.max_recv_speed == 0) || + (data->progress.dlspeed < data->set.max_recv_speed))) + multistate(data, CURLM_STATE_PERFORM); + break; + + case CURLM_STATE_PERFORM: + { + char *newurl = NULL; + bool retry = FALSE; + + /* check if over send speed */ + if((data->set.max_send_speed > 0) && + (data->progress.ulspeed > data->set.max_send_speed)) { + int buffersize; + + multistate(data, CURLM_STATE_TOOFAST); + + /* calculate upload rate-limitation timeout. */ + buffersize = (int)(data->set.buffer_size ? + data->set.buffer_size : BUFSIZE); + timeout_ms = Curl_sleep_time(data->set.max_send_speed, + data->progress.ulspeed, buffersize); + Curl_expire_latest(data, timeout_ms); + break; + } + + /* check if over recv speed */ + if((data->set.max_recv_speed > 0) && + (data->progress.dlspeed > data->set.max_recv_speed)) { + int buffersize; + + multistate(data, CURLM_STATE_TOOFAST); + + /* Calculate download rate-limitation timeout. */ + buffersize = (int)(data->set.buffer_size ? + data->set.buffer_size : BUFSIZE); + timeout_ms = Curl_sleep_time(data->set.max_recv_speed, + data->progress.dlspeed, buffersize); + Curl_expire_latest(data, timeout_ms); + break; + } + + /* read/write data if it is ready to do so */ + result = Curl_readwrite(data->easy_conn, &done); + + k = &data->req; + + if(!(k->keepon & KEEP_RECV)) { + /* We're done receiving */ + data->easy_conn->readchannel_inuse = FALSE; + } + + if(!(k->keepon & KEEP_SEND)) { + /* We're done sending */ + data->easy_conn->writechannel_inuse = FALSE; + } + + if(done || (result == CURLE_RECV_ERROR)) { + /* If CURLE_RECV_ERROR happens early enough, we assume it was a race + * condition and the server closed the re-used connection exactly when + * we wanted to use it, so figure out if that is indeed the case. + */ + CURLcode ret = Curl_retry_request(data->easy_conn, &newurl); + if(!ret) + retry = (newurl)?TRUE:FALSE; + + if(retry) { + /* if we are to retry, set the result to OK and consider the + request as done */ + result = CURLE_OK; + done = TRUE; + } + } + + if(result) { + /* + * The transfer phase returned error, we mark the connection to get + * closed to prevent being re-used. This is because we can't possibly + * know if the connection is in a good shape or not now. Unless it is + * a protocol which uses two "channels" like FTP, as then the error + * happened in the data connection. + */ + + if(!(data->easy_conn->handler->flags & PROTOPT_DUAL)) + connclose(data->easy_conn, "Transfer returned error"); + + Curl_posttransfer(data); + Curl_done(&data->easy_conn, result, FALSE); + } + else if(done) { + followtype follow=FOLLOW_NONE; + + /* call this even if the readwrite function returned error */ + Curl_posttransfer(data); + + /* we're no longer receiving */ + Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe); + + /* expire the new receiving pipeline head */ + if(data->easy_conn->recv_pipe->head) + Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1); + + /* Check if we can move pending requests to send pipe */ + Curl_multi_process_pending_handles(multi); + + /* When we follow redirects or is set to retry the connection, we must + to go back to the CONNECT state */ + if(data->req.newurl || retry) { + if(!retry) { + /* if the URL is a follow-location and not just a retried request + then figure out the URL here */ + free(newurl); + newurl = data->req.newurl; + data->req.newurl = NULL; + follow = FOLLOW_REDIR; + } + else + follow = FOLLOW_RETRY; + result = Curl_done(&data->easy_conn, CURLE_OK, FALSE); + if(!result) { + result = Curl_follow(data, newurl, follow); + if(!result) { + multistate(data, CURLM_STATE_CONNECT); + rc = CURLM_CALL_MULTI_PERFORM; + newurl = NULL; /* handed over the memory ownership to + Curl_follow(), make sure we don't free() it + here */ + } + } + } + else { + /* after the transfer is done, go DONE */ + + /* but first check to see if we got a location info even though we're + not following redirects */ + if(data->req.location) { + free(newurl); + newurl = data->req.location; + data->req.location = NULL; + result = Curl_follow(data, newurl, FOLLOW_FAKE); + if(!result) + newurl = NULL; /* allocation was handed over Curl_follow() */ + else + disconnect_conn = TRUE; + } + + multistate(data, CURLM_STATE_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + + free(newurl); + break; + } + + case CURLM_STATE_DONE: + /* this state is highly transient, so run another loop after this */ + rc = CURLM_CALL_MULTI_PERFORM; + + if(data->easy_conn) { + CURLcode res; + + /* Remove ourselves from the receive pipeline, if we are there. */ + Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe); + /* Check if we can move pending requests to send pipe */ + Curl_multi_process_pending_handles(multi); + + /* post-transfer command */ + res = Curl_done(&data->easy_conn, result, FALSE); + + /* allow a previously set error code take precedence */ + if(!result) + result = res; + + /* + * If there are other handles on the pipeline, Curl_done won't set + * easy_conn to NULL. In such a case, curl_multi_remove_handle() can + * access free'd data, if the connection is free'd and the handle + * removed before we perform the processing in CURLM_STATE_COMPLETED + */ + if(data->easy_conn) + data->easy_conn = NULL; + } + + if(data->set.wildcardmatch) { + if(data->wildcard.state != CURLWC_DONE) { + /* if a wildcard is set and we are not ending -> lets start again + with CURLM_STATE_INIT */ + multistate(data, CURLM_STATE_INIT); + break; + } + } + + /* after we have DONE what we're supposed to do, go COMPLETED, and + it doesn't matter what the Curl_done() returned! */ + multistate(data, CURLM_STATE_COMPLETED); + break; + + case CURLM_STATE_COMPLETED: + /* this is a completed transfer, it is likely to still be connected */ + + /* This node should be delinked from the list now and we should post + an information message that we are complete. */ + + /* Important: reset the conn pointer so that we don't point to memory + that could be freed anytime */ + data->easy_conn = NULL; + + Curl_expire(data, 0); /* stop all timers */ + break; + + case CURLM_STATE_MSGSENT: + data->result = result; + return CURLM_OK; /* do nothing */ + + default: + return CURLM_INTERNAL_ERROR; + } + statemachine_end: + + if(data->mstate < CURLM_STATE_COMPLETED) { + if(result) { + /* + * If an error was returned, and we aren't in completed state now, + * then we go to completed and consider this transfer aborted. + */ + + /* NOTE: no attempt to disconnect connections must be made + in the case blocks above - cleanup happens only here */ + + data->state.pipe_broke = FALSE; + + /* Check if we can move pending requests to send pipe */ + Curl_multi_process_pending_handles(multi); + + if(data->easy_conn) { + /* if this has a connection, unsubscribe from the pipelines */ + data->easy_conn->writechannel_inuse = FALSE; + data->easy_conn->readchannel_inuse = FALSE; + Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe); + Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe); + + if(disconnect_conn) { + /* Don't attempt to send data over a connection that timed out */ + bool dead_connection = result == CURLE_OPERATION_TIMEDOUT; + /* disconnect properly */ + Curl_disconnect(data->easy_conn, dead_connection); + + /* This is where we make sure that the easy_conn pointer is reset. + We don't have to do this in every case block above where a + failure is detected */ + data->easy_conn = NULL; + } + } + else if(data->mstate == CURLM_STATE_CONNECT) { + /* Curl_connect() failed */ + (void)Curl_posttransfer(data); + } + + multistate(data, CURLM_STATE_COMPLETED); + } + /* if there's still a connection to use, call the progress function */ + else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) { + /* aborted due to progress callback return code must close the + connection */ + result = CURLE_ABORTED_BY_CALLBACK; + connclose(data->easy_conn, "Aborted by callback"); + + /* if not yet in DONE state, go there, otherwise COMPLETED */ + multistate(data, (data->mstate < CURLM_STATE_DONE)? + CURLM_STATE_DONE: CURLM_STATE_COMPLETED); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + + if(CURLM_STATE_COMPLETED == data->mstate) { + /* now fill in the Curl_message with this info */ + msg = &data->msg; + + msg->extmsg.msg = CURLMSG_DONE; + msg->extmsg.easy_handle = data; + msg->extmsg.data.result = result; + + rc = multi_addmsg(multi, msg); + + multistate(data, CURLM_STATE_MSGSENT); + } + } while(rc == CURLM_CALL_MULTI_PERFORM); + + data->result = result; + + + return rc; +} + + +CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct SessionHandle *data; + CURLMcode returncode=CURLM_OK; + struct Curl_tree *t; + struct timeval now = Curl_tvnow(); + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + data=multi->easyp; + while(data) { + CURLMcode result; + struct WildcardData *wc = &data->wildcard; + SIGPIPE_VARIABLE(pipe_st); + + if(data->set.wildcardmatch) { + if(!wc->filelist) { + CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */ + if(ret) + return CURLM_OUT_OF_MEMORY; + } + } + + sigpipe_ignore(data, &pipe_st); + result = multi_runsingle(multi, now, data); + sigpipe_restore(&pipe_st); + + if(data->set.wildcardmatch) { + /* destruct wildcard structures if it is needed */ + if(wc->state == CURLWC_DONE || result) + Curl_wildcard_dtor(wc); + } + + if(result) + returncode = result; + + data = data->next; /* operate on next handle */ + } + + /* + * Simply remove all expired timers from the splay since handles are dealt + * with unconditionally by this function and curl_multi_timeout() requires + * that already passed/handled expire times are removed from the splay. + * + * It is important that the 'now' value is set at the entry of this function + * and not for the current time as it may have ticked a little while since + * then and then we risk this loop to remove timers that actually have not + * been handled! + */ + do { + multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); + if(t) + /* the removed may have another timeout in queue */ + (void)add_next_timeout(now, multi, t->payload); + + } while(t); + + *running_handles = multi->num_alive; + + if(CURLM_OK >= returncode) + update_timer(multi); + + return returncode; +} + +static void close_all_connections(struct Curl_multi *multi) +{ + struct connectdata *conn; + + conn = Curl_conncache_find_first_connection(multi->conn_cache); + while(conn) { + SIGPIPE_VARIABLE(pipe_st); + conn->data = multi->closure_handle; + + sigpipe_ignore(conn->data, &pipe_st); + /* This will remove the connection from the cache */ + (void)Curl_disconnect(conn, FALSE); + sigpipe_restore(&pipe_st); + + conn = Curl_conncache_find_first_connection(multi->conn_cache); + } +} + +CURLMcode curl_multi_cleanup(CURLM *multi_handle) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct SessionHandle *data; + struct SessionHandle *nextdata; + + if(GOOD_MULTI_HANDLE(multi)) { + bool restore_pipe = FALSE; + SIGPIPE_VARIABLE(pipe_st); + + multi->type = 0; /* not good anymore */ + + /* Close all the connections in the connection cache */ + close_all_connections(multi); + + if(multi->closure_handle) { + sigpipe_ignore(multi->closure_handle, &pipe_st); + restore_pipe = TRUE; + + multi->closure_handle->dns.hostcache = multi->hostcache; + Curl_hostcache_clean(multi->closure_handle, + multi->closure_handle->dns.hostcache); + + Curl_close(multi->closure_handle); + } + + Curl_hash_destroy(multi->sockhash); + Curl_conncache_destroy(multi->conn_cache); + Curl_llist_destroy(multi->msglist, NULL); + Curl_llist_destroy(multi->pending, NULL); + + /* remove all easy handles */ + data = multi->easyp; + while(data) { + nextdata=data->next; + if(data->dns.hostcachetype == HCACHE_MULTI) { + /* clear out the usage of the shared DNS cache */ + Curl_hostcache_clean(data, data->dns.hostcache); + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + + /* Clear the pointer to the connection cache */ + data->state.conn_cache = NULL; + data->multi = NULL; /* clear the association */ + + data = nextdata; + } + + Curl_hash_destroy(multi->hostcache); + + /* Free the blacklists by setting them to NULL */ + Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl); + Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl); + + free(multi); + if(restore_pipe) + sigpipe_restore(&pipe_st); + + return CURLM_OK; + } + else + return CURLM_BAD_HANDLE; +} + +/* + * curl_multi_info_read() + * + * This function is the primary way for a multi/multi_socket application to + * figure out if a transfer has ended. We MUST make this function as fast as + * possible as it will be polled frequently and we MUST NOT scan any lists in + * here to figure out things. We must scale fine to thousands of handles and + * beyond. The current design is fully O(1). + */ + +CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct Curl_message *msg; + + *msgs_in_queue = 0; /* default to none */ + + if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) { + /* there is one or more messages in the list */ + struct curl_llist_element *e; + + /* extract the head of the list to return */ + e = multi->msglist->head; + + msg = e->ptr; + + /* remove the extracted entry */ + Curl_llist_remove(multi->msglist, e, NULL); + + *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist)); + + return &msg->extmsg; + } + else + return NULL; +} + +/* + * singlesocket() checks what sockets we deal with and their "action state" + * and if we have a different state in any of those sockets from last time we + * call the callback accordingly. + */ +static void singlesocket(struct Curl_multi *multi, + struct SessionHandle *data) +{ + curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; + int i; + struct Curl_sh_entry *entry; + curl_socket_t s; + int num; + unsigned int curraction; + bool remove_sock_from_hash; + + for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) + socks[i] = CURL_SOCKET_BAD; + + /* Fill in the 'current' struct with the state as it is now: what sockets to + supervise and for what actions */ + curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE); + + /* We have 0 .. N sockets already and we get to know about the 0 .. M + sockets we should have from now on. Detect the differences, remove no + longer supervised ones and add new ones */ + + /* walk over the sockets we got right now */ + for(i=0; (i< MAX_SOCKSPEREASYHANDLE) && + (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))); + i++) { + int action = CURL_POLL_NONE; + + s = socks[i]; + + /* get it from the hash */ + entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); + + if(curraction & GETSOCK_READSOCK(i)) + action |= CURL_POLL_IN; + if(curraction & GETSOCK_WRITESOCK(i)) + action |= CURL_POLL_OUT; + + if(entry) { + /* yeps, already present so check if it has the same action set */ + if(entry->action == action) + /* same, continue */ + continue; + } + else { + /* this is a socket we didn't have before, add it! */ + entry = sh_addentry(multi->sockhash, s, data); + if(!entry) + /* fatal */ + return; + } + + /* we know (entry != NULL) at this point, see the logic above */ + if(multi->socket_cb) + multi->socket_cb(data, + s, + action, + multi->socket_userp, + entry->socketp); + + entry->action = action; /* store the current action state */ + } + + num = i; /* number of sockets */ + + /* when we've walked over all the sockets we should have right now, we must + make sure to detect sockets that are removed */ + for(i=0; i< data->numsocks; i++) { + int j; + s = data->sockets[i]; + for(j=0; jsockhash, (char *)&s, sizeof(s)); + if(entry) { + /* check if the socket to be removed serves a connection which has + other easy-s in a pipeline. In this case the socket should not be + removed. */ + struct connectdata *easy_conn = data->easy_conn; + if(easy_conn) { + if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) { + /* the handle should not be removed from the pipe yet */ + remove_sock_from_hash = FALSE; + + /* Update the sockhash entry to instead point to the next in line + for the recv_pipe, or the first (in case this particular easy + isn't already) */ + if(entry->easy == data) { + if(isHandleAtHead(data, easy_conn->recv_pipe)) + entry->easy = easy_conn->recv_pipe->head->next->ptr; + else + entry->easy = easy_conn->recv_pipe->head->ptr; + } + } + if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) { + /* the handle should not be removed from the pipe yet */ + remove_sock_from_hash = FALSE; + + /* Update the sockhash entry to instead point to the next in line + for the send_pipe, or the first (in case this particular easy + isn't already) */ + if(entry->easy == data) { + if(isHandleAtHead(data, easy_conn->send_pipe)) + entry->easy = easy_conn->send_pipe->head->next->ptr; + else + entry->easy = easy_conn->send_pipe->head->ptr; + } + } + /* Don't worry about overwriting recv_pipe head with send_pipe_head, + when action will be asked on the socket (see multi_socket()), the + head of the correct pipe will be taken according to the + action. */ + } + } + else + /* just a precaution, this socket really SHOULD be in the hash already + but in case it isn't, we don't have to tell the app to remove it + either since it never got to know about it */ + remove_sock_from_hash = FALSE; + + if(remove_sock_from_hash) { + /* in this case 'entry' is always non-NULL */ + if(multi->socket_cb) + multi->socket_cb(data, + s, + CURL_POLL_REMOVE, + multi->socket_userp, + entry->socketp); + sh_delentry(multi->sockhash, s); + } + + } + } + + memcpy(data->sockets, socks, num*sizeof(curl_socket_t)); + data->numsocks = num; +} + +/* + * Curl_multi_closed() + * + * Used by the connect code to tell the multi_socket code that one of the + * sockets we were using is about to be closed. This function will then + * remove it from the sockethash for this handle to make the multi_socket API + * behave properly, especially for the case when libcurl will create another + * socket again and it gets the same file descriptor number. + */ + +CURL_STATIC void Curl_multi_closed(struct connectdata *conn, curl_socket_t s) +{ + struct Curl_multi *multi = conn->data->multi; + if(multi) { + /* this is set if this connection is part of a handle that is added to + a multi handle, and only then this is necessary */ + struct Curl_sh_entry *entry = + Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); + + if(entry) { + if(multi->socket_cb) + multi->socket_cb(conn->data, s, CURL_POLL_REMOVE, + multi->socket_userp, + entry->socketp); + + /* now remove it from the socket hash */ + sh_delentry(multi->sockhash, s); + } + } +} + + + +/* + * add_next_timeout() + * + * Each SessionHandle has a list of timeouts. The add_next_timeout() is called + * when it has just been removed from the splay tree because the timeout has + * expired. This function is then to advance in the list to pick the next + * timeout to use (skip the already expired ones) and add this node back to + * the splay tree again. + * + * The splay tree only has each sessionhandle as a single node and the nearest + * timeout is used to sort it on. + */ +static CURLMcode add_next_timeout(struct timeval now, + struct Curl_multi *multi, + struct SessionHandle *d) +{ + struct timeval *tv = &d->state.expiretime; + struct curl_llist *list = d->state.timeoutlist; + struct curl_llist_element *e; + + /* move over the timeout list for this specific handle and remove all + timeouts that are now passed tense and store the next pending + timeout in *tv */ + for(e = list->head; e; ) { + struct curl_llist_element *n = e->next; + long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now); + if(diff <= 0) + /* remove outdated entry */ + Curl_llist_remove(list, e, NULL); + else + /* the list is sorted so get out on the first mismatch */ + break; + e = n; + } + e = list->head; + if(!e) { + /* clear the expire times within the handles that we remove from the + splay tree */ + tv->tv_sec = 0; + tv->tv_usec = 0; + } + else { + /* copy the first entry to 'tv' */ + memcpy(tv, e->ptr, sizeof(*tv)); + + /* remove first entry from list */ + Curl_llist_remove(list, e, NULL); + + /* insert this node again into the splay */ + multi->timetree = Curl_splayinsert(*tv, multi->timetree, + &d->state.timenode); + } + return CURLM_OK; +} + +static CURLMcode multi_socket(struct Curl_multi *multi, + bool checkall, + curl_socket_t s, + int ev_bitmask, + int *running_handles) +{ + CURLMcode result = CURLM_OK; + struct SessionHandle *data = NULL; + struct Curl_tree *t; + struct timeval now = Curl_tvnow(); + + if(checkall) { + /* *perform() deals with running_handles on its own */ + result = curl_multi_perform(multi, running_handles); + + /* walk through each easy handle and do the socket state change magic + and callbacks */ + if(result != CURLM_BAD_HANDLE) { + data=multi->easyp; + while(data) { + singlesocket(multi, data); + data = data->next; + } + } + + /* or should we fall-through and do the timer-based stuff? */ + return result; + } + else if(s != CURL_SOCKET_TIMEOUT) { + + struct Curl_sh_entry *entry = + Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); + + if(!entry) + /* Unmatched socket, we can't act on it but we ignore this fact. In + real-world tests it has been proved that libevent can in fact give + the application actions even though the socket was just previously + asked to get removed, so thus we better survive stray socket actions + and just move on. */ + ; + else { + SIGPIPE_VARIABLE(pipe_st); + + data = entry->easy; + + if(data->magic != CURLEASY_MAGIC_NUMBER) + /* bad bad bad bad bad bad bad */ + return CURLM_INTERNAL_ERROR; + + /* If the pipeline is enabled, take the handle which is in the head of + the pipeline. If we should write into the socket, take the send_pipe + head. If we should read from the socket, take the recv_pipe head. */ + if(data->easy_conn) { + if((ev_bitmask & CURL_POLL_OUT) && + data->easy_conn->send_pipe && + data->easy_conn->send_pipe->head) + data = data->easy_conn->send_pipe->head->ptr; + else if((ev_bitmask & CURL_POLL_IN) && + data->easy_conn->recv_pipe && + data->easy_conn->recv_pipe->head) + data = data->easy_conn->recv_pipe->head->ptr; + } + + if(data->easy_conn && + !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK)) + /* set socket event bitmask if they're not locked */ + data->easy_conn->cselect_bits = ev_bitmask; + + sigpipe_ignore(data, &pipe_st); + result = multi_runsingle(multi, now, data); + sigpipe_restore(&pipe_st); + + if(data->easy_conn && + !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK)) + /* clear the bitmask only if not locked */ + data->easy_conn->cselect_bits = 0; + + if(CURLM_OK >= result) + /* get the socket(s) and check if the state has been changed since + last */ + singlesocket(multi, data); + + /* Now we fall-through and do the timer-based stuff, since we don't want + to force the user to have to deal with timeouts as long as at least + one connection in fact has traffic. */ + + data = NULL; /* set data to NULL again to avoid calling + multi_runsingle() in case there's no need to */ + now = Curl_tvnow(); /* get a newer time since the multi_runsingle() loop + may have taken some time */ + } + } + else { + /* Asked to run due to time-out. Clear the 'lastcall' variable to force + update_timer() to trigger a callback to the app again even if the same + timeout is still the one to run after this call. That handles the case + when the application asks libcurl to run the timeout prematurely. */ + memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); + } + + /* + * The loop following here will go on as long as there are expire-times left + * to process in the splay and 'data' will be re-assigned for every expired + * handle we deal with. + */ + do { + /* the first loop lap 'data' can be NULL */ + if(data) { + SIGPIPE_VARIABLE(pipe_st); + + sigpipe_ignore(data, &pipe_st); + result = multi_runsingle(multi, now, data); + sigpipe_restore(&pipe_st); + + if(CURLM_OK >= result) + /* get the socket(s) and check if the state has been changed since + last */ + singlesocket(multi, data); + } + + /* Check if there's one (more) expired timer to deal with! This function + extracts a matching node if there is one */ + + multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); + if(t) { + data = t->payload; /* assign this for next loop */ + (void)add_next_timeout(now, multi, t->payload); + } + + } while(t); + + *running_handles = multi->num_alive; + return result; +} + +//#undef curl_multi_setopt +CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + CURLMcode res = CURLM_OK; + va_list param; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + va_start(param, option); + + switch(option) { + case CURLMOPT_SOCKETFUNCTION: + multi->socket_cb = va_arg(param, curl_socket_callback); + break; + case CURLMOPT_SOCKETDATA: + multi->socket_userp = va_arg(param, void *); + break; + case CURLMOPT_PIPELINING: + multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLMOPT_TIMERFUNCTION: + multi->timer_cb = va_arg(param, curl_multi_timer_callback); + break; + case CURLMOPT_TIMERDATA: + multi->timer_userp = va_arg(param, void *); + break; + case CURLMOPT_MAXCONNECTS: + multi->maxconnects = va_arg(param, long); + break; + case CURLMOPT_MAX_HOST_CONNECTIONS: + multi->max_host_connections = va_arg(param, long); + break; + case CURLMOPT_MAX_PIPELINE_LENGTH: + multi->max_pipeline_length = va_arg(param, long); + break; + case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE: + multi->content_length_penalty_size = va_arg(param, long); + break; + case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE: + multi->chunk_length_penalty_size = va_arg(param, long); + break; + case CURLMOPT_PIPELINING_SITE_BL: + res = Curl_pipeline_set_site_blacklist(va_arg(param, char **), + &multi->pipelining_site_bl); + break; + case CURLMOPT_PIPELINING_SERVER_BL: + res = Curl_pipeline_set_server_blacklist(va_arg(param, char **), + &multi->pipelining_server_bl); + break; + case CURLMOPT_MAX_TOTAL_CONNECTIONS: + multi->max_total_connections = va_arg(param, long); + break; + default: + res = CURLM_UNKNOWN_OPTION; + break; + } + va_end(param); + return res; +} + +/* we define curl_multi_socket() in the public multi.h header */ +//#undef curl_multi_socket + +CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles) +{ + CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s, + 0, running_handles); + if(CURLM_OK >= result) + update_timer((struct Curl_multi *)multi_handle); + return result; +} + +CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s, + int ev_bitmask, int *running_handles) +{ + CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s, + ev_bitmask, running_handles); + if(CURLM_OK >= result) + update_timer((struct Curl_multi *)multi_handle); + return result; +} + +CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles) + +{ + CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, + TRUE, CURL_SOCKET_BAD, 0, running_handles); + if(CURLM_OK >= result) + update_timer((struct Curl_multi *)multi_handle); + return result; +} + +static CURLMcode multi_timeout(struct Curl_multi *multi, + long *timeout_ms) +{ + static struct timeval tv_zero = {0, 0}; + + if(multi->timetree) { + /* we have a tree of expire times */ + struct timeval now = Curl_tvnow(); + + /* splay the lowest to the bottom */ + multi->timetree = Curl_splay(tv_zero, multi->timetree); + + if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) { + /* some time left before expiration */ + *timeout_ms = curlx_tvdiff(multi->timetree->key, now); + if(!*timeout_ms) + /* + * Since we only provide millisecond resolution on the returned value + * and the diff might be less than one millisecond here, we don't + * return zero as that may cause short bursts of busyloops on fast + * processors while the diff is still present but less than one + * millisecond! instead we return 1 until the time is ripe. + */ + *timeout_ms=1; + } + else + /* 0 means immediately */ + *timeout_ms = 0; + } + else + *timeout_ms = -1; + + return CURLM_OK; +} + +CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *timeout_ms) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + return multi_timeout(multi, timeout_ms); +} + +/* + * Tell the application it should update its timers, if it subscribes to the + * update timer callback. + */ +static int update_timer(struct Curl_multi *multi) +{ + long timeout_ms; + + if(!multi->timer_cb) + return 0; + if(multi_timeout(multi, &timeout_ms)) { + return -1; + } + if(timeout_ms < 0) { + static const struct timeval none={0, 0}; + if(Curl_splaycomparekeys(none, multi->timer_lastcall)) { + multi->timer_lastcall = none; + /* there's no timeout now but there was one previously, tell the app to + disable it */ + return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp); + } + return 0; + } + + /* When multi_timeout() is done, multi->timetree points to the node with the + * timeout we got the (relative) time-out time for. We can thus easily check + * if this is the same (fixed) time as we got in a previous call and then + * avoid calling the callback again. */ + if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0) + return 0; + + multi->timer_lastcall = multi->timetree->key; + + return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp); +} + +static bool isHandleAtHead(struct SessionHandle *handle, + struct curl_llist *pipeline) +{ + struct curl_llist_element *curr = pipeline->head; + if(curr) + return (curr->ptr == handle) ? TRUE : FALSE; + + return FALSE; +} + +/* + * multi_freetimeout() + * + * Callback used by the llist system when a single timeout list entry is + * destroyed. + */ +static void multi_freetimeout(void *user, void *entryptr) +{ + (void)user; + + /* the entry was plain malloc()'ed */ + free(entryptr); +} + +/* + * multi_addtimeout() + * + * Add a timestamp to the list of timeouts. Keep the list sorted so that head + * of list is always the timeout nearest in time. + * + */ +static CURLMcode +multi_addtimeout(struct curl_llist *timeoutlist, + struct timeval *stamp) +{ + struct curl_llist_element *e; + struct timeval *timedup; + struct curl_llist_element *prev = NULL; + + timedup = malloc(sizeof(*timedup)); + if(!timedup) + return CURLM_OUT_OF_MEMORY; + + /* copy the timestamp */ + memcpy(timedup, stamp, sizeof(*timedup)); + + if(Curl_llist_count(timeoutlist)) { + /* find the correct spot in the list */ + for(e = timeoutlist->head; e; e = e->next) { + struct timeval *checktime = e->ptr; + long diff = curlx_tvdiff(*checktime, *timedup); + if(diff > 0) + break; + prev = e; + } + + } + /* else + this is the first timeout on the list */ + + if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) { + free(timedup); + return CURLM_OUT_OF_MEMORY; + } + + return CURLM_OK; +} + +/* + * Curl_expire() + * + * given a number of milliseconds from now to use to set the 'act before + * this'-time for the transfer, to be extracted by curl_multi_timeout() + * + * Note that the timeout will be added to a queue of timeouts if it defines a + * moment in time that is later than the current head of queue. + * + * Pass zero to clear all timeout values for this handle. +*/ +CURL_STATIC void Curl_expire(struct SessionHandle *data, long milli) +{ + struct Curl_multi *multi = data->multi; + struct timeval *nowp = &data->state.expiretime; + int rc; + + /* this is only interesting while there is still an associated multi struct + remaining! */ + if(!multi) + return; + + if(!milli) { + /* No timeout, clear the time data. */ + if(nowp->tv_sec || nowp->tv_usec) { + /* Since this is an cleared time, we must remove the previous entry from + the splay tree */ + struct curl_llist *list = data->state.timeoutlist; + + rc = Curl_splayremovebyaddr(multi->timetree, + &data->state.timenode, + &multi->timetree); + if(rc) + infof(data, "Internal error clearing splay node = %d\n", rc); + + /* flush the timeout list too */ + while(list->size > 0) + Curl_llist_remove(list, list->tail, NULL); + +#ifdef DEBUGBUILD + infof(data, "Expire cleared\n"); +#endif + nowp->tv_sec = 0; + nowp->tv_usec = 0; + } + } + else { + 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(nowp->tv_sec || nowp->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, *nowp); + if(diff > 0) { + /* the new expire time was later so just add it to the queue + and get out */ + multi_addtimeout(data->state.timeoutlist, &set); + return; + } + + /* the new time is newer than the presently set one, so add the current + to the queue and update the head */ + multi_addtimeout(data->state.timeoutlist, nowp); + + /* Since this is an updated time, we must remove the previous entry from + the splay tree first and then re-add the new value */ + rc = Curl_splayremovebyaddr(multi->timetree, + &data->state.timenode, + &multi->timetree); + if(rc) + infof(data, "Internal error removing splay node = %d\n", rc); + } + + *nowp = set; + data->state.timenode.payload = data; + multi->timetree = Curl_splayinsert(*nowp, + multi->timetree, + &data->state.timenode); + } +#if 0 + Curl_splayprint(multi->timetree, 0, TRUE); +#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. + * + */ +CURL_STATIC void Curl_expire_latest(struct SessionHandle *data, long milli) +{ + struct timeval *expire = &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(expire->tv_sec || expire->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, *expire); + 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, + curl_socket_t s, void *hashp) +{ + struct Curl_sh_entry *there = NULL; + struct Curl_multi *multi = (struct Curl_multi *)multi_handle; + + if(s != CURL_SOCKET_BAD) + there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t)); + + if(!there) + return CURLM_BAD_SOCKET; + + there->socketp = hashp; + + return CURLM_OK; +} + +CURL_STATIC size_t Curl_multi_max_host_connections(struct Curl_multi *multi) +{ + return multi ? multi->max_host_connections : 0; +} + +CURL_STATIC size_t Curl_multi_max_total_connections(struct Curl_multi *multi) +{ + return multi ? multi->max_total_connections : 0; +} + +CURL_STATIC size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi) +{ + return multi ? multi->max_pipeline_length : 0; +} + +CURL_STATIC curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi) +{ + return multi ? multi->content_length_penalty_size : 0; +} + +CURL_STATIC curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi) +{ + return multi ? multi->chunk_length_penalty_size : 0; +} + +CURL_STATIC struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi) +{ + return multi->pipelining_site_bl; +} + +CURL_STATIC struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi) +{ + return multi->pipelining_server_bl; +} + +CURL_STATIC void Curl_multi_process_pending_handles(struct Curl_multi *multi) +{ + struct curl_llist_element *e = multi->pending->head; + + while(e) { + struct SessionHandle *data = e->ptr; + struct curl_llist_element *next = e->next; + + if(data->mstate == CURLM_STATE_CONNECT_PEND) { + 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. */ + Curl_expire_latest(data, 1); + } + + e = next; /* operate on next handle */ + } +} + +#ifdef DEBUGBUILD +CURL_STATIC void Curl_multi_dump(const struct Curl_multi *multi_handle) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct SessionHandle *data; + int i; + fprintf(stderr, "* Multi status: %d handles, %d alive\n", + multi->num_easy, multi->num_alive); + for(data=multi->easyp; data; data = data->next) { + if(data->mstate < CURLM_STATE_COMPLETED) { + /* only display handles that are not completed */ + fprintf(stderr, "handle %p, state %s, %d sockets\n", + (void *)data, + statename[data->mstate], data->numsocks); + for(i=0; i < data->numsocks; i++) { + curl_socket_t s = data->sockets[i]; + struct Curl_sh_entry *entry = + Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); + + fprintf(stderr, "%d ", (int)s); + if(!entry) { + fprintf(stderr, "INTERNAL CONFUSION\n"); + continue; + } + fprintf(stderr, "[%s %s] ", + entry->action&CURL_POLL_IN?"RECVING":"", + entry->action&CURL_POLL_OUT?"SENDING":""); + } + if(data->numsocks) + fprintf(stderr, "\n"); + } + } +} +#endif diff --git a/libcurl/src/lib/multihandle.h b/libcurl/src/lib/multihandle.h new file mode 100644 index 0000000..d8b9d88 --- /dev/null +++ b/libcurl/src/lib/multihandle.h @@ -0,0 +1,143 @@ +#ifndef HEADER_CURL_MULTIHANDLE_H +#define HEADER_CURL_MULTIHANDLE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +struct Curl_message { + /* the 'CURLMsg' is the part that is visible to the external user */ + struct CURLMsg extmsg; +}; + +/* NOTE: if you add a state here, add the name to the statename[] array as + well! +*/ +typedef enum { + CURLM_STATE_INIT, /* 0 - start in this state */ + CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */ + CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */ + CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */ + CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */ + CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */ + CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */ + CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect + phase */ + CURLM_STATE_WAITDO, /* 8 - wait for our turn to send the request */ + CURLM_STATE_DO, /* 9 - start send off the request (part 1) */ + CURLM_STATE_DOING, /* 10 - sending off the request (part 1) */ + CURLM_STATE_DO_MORE, /* 11 - send off the request (part 2) */ + CURLM_STATE_DO_DONE, /* 12 - done sending off request */ + CURLM_STATE_WAITPERFORM, /* 13 - wait for our turn to read the response */ + CURLM_STATE_PERFORM, /* 14 - transfer data */ + CURLM_STATE_TOOFAST, /* 15 - wait because limit-rate exceeded */ + CURLM_STATE_DONE, /* 16 - post data transfer operation */ + CURLM_STATE_COMPLETED, /* 17 - operation complete */ + CURLM_STATE_MSGSENT, /* 18 - the operation complete message is sent */ + CURLM_STATE_LAST /* 19 - not a true state, never use this */ +} CURLMstate; + +/* we support N sockets per easy handle. Set the corresponding bit to what + action we should wait for */ +#define MAX_SOCKSPEREASYHANDLE 5 +#define GETSOCK_READABLE (0x00ff) +#define GETSOCK_WRITABLE (0xff00) + +/* This is the struct known as CURLM on the outside */ +struct Curl_multi { + /* First a simple identifier to easier detect if a user mix up + this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */ + long type; + + /* We have a doubly-linked circular list with easy handles */ + struct SessionHandle *easyp; + struct SessionHandle *easylp; /* last node */ + + int num_easy; /* amount of entries in the linked list above. */ + int num_alive; /* amount of easy handles that are added but have not yet + reached COMPLETE state */ + + 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 */ + curl_socket_callback socket_cb; + void *socket_userp; + + /* Hostname cache */ + struct curl_hash *hostcache; + + /* timetree points to the splay-tree of time nodes to figure out expire + times of all currently set timers */ + struct Curl_tree *timetree; + + /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note + the pluralis form, there can be more than one easy handle waiting on the + same actual socket) */ + struct curl_hash *sockhash; + + /* Whether pipelining is enabled for this multi handle */ + bool pipelining_enabled; + + /* Shared connection cache (bundles)*/ + struct conncache *conn_cache; + + /* This handle will be used for closing the cached connections in + curl_multi_cleanup() */ + struct SessionHandle *closure_handle; + + long maxconnects; /* if >0, a fixed limit of the maximum number of entries + we're allowed to grow the connection cache to */ + + long max_host_connections; /* if >0, a fixed limit of the maximum number + of connections per host */ + + long max_total_connections; /* if >0, a fixed limit of the maximum number + of connections in total */ + + long max_pipeline_length; /* if >0, maximum number of requests in a + pipeline */ + + long content_length_penalty_size; /* a connection with a + content-length bigger than + this is not considered + for pipelining */ + + long chunk_length_penalty_size; /* a connection with a chunk length + bigger than this is not + considered for pipelining */ + + struct curl_llist *pipelining_site_bl; /* List of sites that are blacklisted + from pipelining */ + + struct curl_llist *pipelining_server_bl; /* List of server types that are + blacklisted from pipelining */ + + /* timer callback and user data pointer for the *socket() API */ + curl_multi_timer_callback timer_cb; + void *timer_userp; + struct timeval timer_lastcall; /* the fixed time for the timeout for the + previous callback */ +}; + +#endif /* HEADER_CURL_MULTIHANDLE_H */ + diff --git a/libcurl/src/lib/multiif.h b/libcurl/src/lib/multiif.h new file mode 100644 index 0000000..10aab3e --- /dev/null +++ b/libcurl/src/lib/multiif.h @@ -0,0 +1,93 @@ +#ifndef HEADER_CURL_MULTIIF_H +#define HEADER_CURL_MULTIIF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by multi.c + */ +CURL_STATIC void Curl_expire(struct SessionHandle *data, long milli); +CURL_STATIC void Curl_expire_latest(struct SessionHandle *data, long milli); + +CURL_STATIC bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi); +CURL_STATIC void Curl_multi_handlePipeBreak(struct SessionHandle *data); + +/* Internal version of curl_multi_init() accepts size parameters for the + socket and connection hashes */ +CURL_STATIC struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize); + +/* the write bits start at bit 16 for the *getsock() bitmap */ +#define GETSOCK_WRITEBITSTART 16 + +#define GETSOCK_BLANK 0 /* no bits set */ + +/* set the bit for the given sock number to make the bitmap for writable */ +#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x))) + +/* set the bit for the given sock number to make the bitmap for readable */ +#define GETSOCK_READSOCK(x) (1 << (x)) + +#ifdef DEBUGBUILD + /* + * Curl_multi_dump is not a stable public function, this is only meant to + * allow easier tracking of the internal handle's state and what sockets + * they use. Only for research and development DEBUGBUILD enabled builds. + */ +CURL_STATIC void Curl_multi_dump(const struct Curl_multi *multi_handle); +#endif + +CURL_STATIC void Curl_multi_process_pending_handles(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */ +CURL_STATIC size_t Curl_multi_max_host_connections(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_MAX_PIPELINE_LENGTH option */ +CURL_STATIC size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */ +CURL_STATIC curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE option */ +CURL_STATIC curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_PIPELINING_SITE_BL option */ +CURL_STATIC struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_PIPELINING_SERVER_BL option */ +CURL_STATIC struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */ +CURL_STATIC size_t Curl_multi_max_total_connections(struct Curl_multi *multi); + +/* + * Curl_multi_closed() + * + * Used by the connect code to tell the multi_socket code that one of the + * sockets we were using is about to be closed. This function will then + * remove it from the sockethash for this handle to make the multi_socket API + * behave properly, especially for the case when libcurl will create another + * socket again and it gets the same file descriptor number. + */ + +CURL_STATIC void Curl_multi_closed(struct connectdata *conn, curl_socket_t s); + +#endif /* HEADER_CURL_MULTIIF_H */ diff --git a/libcurl/src/lib/netrc.c b/libcurl/src/lib/netrc.c new file mode 100644 index 0000000..ce907c6 --- /dev/null +++ b/libcurl/src/lib/netrc.c @@ -0,0 +1,199 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_PWD_H +#include +#endif + +#include +#include "netrc.h" + +#include "strequal.h" +#include "strtok.h" +#include "rawstr.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Get user and password from .netrc when given a machine name */ + +enum host_lookup_state { + NOTHING, + HOSTFOUND, /* the 'machine' keyword was found */ + HOSTVALID /* this is "our" machine! */ +}; + +/* + * @unittest: 1304 + * + * *loginp and *passwordp MUST be allocated if they aren't NULL when passed + * in. + */ +CURL_STATIC int Curl_parsenetrc(const char *host, + char **loginp, + char **passwordp, + char *netrcfile) +{ + FILE *file; + int retcode=1; + int specific_login = (*loginp && **loginp != 0); + bool netrc_alloc = FALSE; + enum host_lookup_state state=NOTHING; + + char state_login=0; /* Found a login keyword */ + char state_password=0; /* Found a password keyword */ + int state_our_login=FALSE; /* With specific_login, found *our* login name */ + +#define NETRC DOT_CHAR "netrc" + + if(!netrcfile) { + bool home_alloc = FALSE; + char *home = curl_getenv("HOME"); /* portable environment reader */ + if(home) { + home_alloc = TRUE; +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + } + else { + struct passwd pw, *pw_res; + char pwbuf[1024]; + if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) + && pw_res) { + home = strdup(pw.pw_dir); + if(!home) + return CURLE_OUT_OF_MEMORY; + home_alloc = TRUE; + } +#elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID) + } + else { + struct passwd *pw; + pw= getpwuid(geteuid()); + if(pw) { + home = pw->pw_dir; + } +#endif + } + + if(!home) + return retcode; /* no home directory found (or possibly out of memory) */ + + netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC); + if(home_alloc) + free(home); + if(!netrcfile) { + return -1; + } + netrc_alloc = TRUE; + } + + file = fopen(netrcfile, "r"); + if(netrc_alloc) + free(netrcfile); + if(file) { + char *tok; + char *tok_buf; + bool done=FALSE; + char netrcbuffer[256]; + int netrcbuffsize = (int)sizeof(netrcbuffer); + + while(!done && fgets(netrcbuffer, netrcbuffsize, file)) { + tok=strtok_r(netrcbuffer, " \t\n", &tok_buf); + while(!done && tok) { + + if((*loginp && **loginp) && (*passwordp && **passwordp)) { + done=TRUE; + break; + } + + switch(state) { + case NOTHING: + if(Curl_raw_equal("machine", tok)) { + /* the next tok is the machine name, this is in itself the + delimiter that starts the stuff entered for this machine, + after this we need to search for 'login' and + 'password'. */ + state=HOSTFOUND; + } + break; + case HOSTFOUND: + if(Curl_raw_equal(host, tok)) { + /* and yes, this is our host! */ + state=HOSTVALID; + retcode=0; /* we did find our host */ + } + else + /* not our host */ + state=NOTHING; + break; + case HOSTVALID: + /* we are now parsing sub-keywords concerning "our" host */ + if(state_login) { + if(specific_login) { + state_our_login = Curl_raw_equal(*loginp, tok); + } + else { + free(*loginp); + *loginp = strdup(tok); + if(!*loginp) { + retcode = -1; /* allocation failed */ + goto out; + } + } + state_login=0; + } + else if(state_password) { + if(state_our_login || !specific_login) { + free(*passwordp); + *passwordp = strdup(tok); + if(!*passwordp) { + retcode = -1; /* allocation failed */ + goto out; + } + } + state_password=0; + } + else if(Curl_raw_equal("login", tok)) + state_login=1; + else if(Curl_raw_equal("password", tok)) + state_password=1; + else if(Curl_raw_equal("machine", tok)) { + /* ok, there's machine here go => */ + state = HOSTFOUND; + state_our_login = FALSE; + } + break; + } /* switch (state) */ + + tok = strtok_r(NULL, " \t\n", &tok_buf); + } /* while(tok) */ + } /* while fgets() */ + + out: + fclose(file); + } + + return retcode; +} diff --git a/libcurl/src/lib/netrc.h b/libcurl/src/lib/netrc.h new file mode 100644 index 0000000..6bd54dd --- /dev/null +++ b/libcurl/src/lib/netrc.h @@ -0,0 +1,36 @@ +#ifndef HEADER_CURL_NETRC_H +#define HEADER_CURL_NETRC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */ +CURL_STATIC int Curl_parsenetrc(const char *host, + char **loginp, + char **passwordp, + char *filename); + /* Assume: (*passwordp)[0]=0, host[0] != 0. + * If (*loginp)[0] = 0, search for login and password within a machine + * section in the netrc. + * If (*loginp)[0] != 0, search for password within machine and login. + */ + +#endif /* HEADER_CURL_NETRC_H */ diff --git a/libcurl/src/lib/non-ascii.c b/libcurl/src/lib/non-ascii.c new file mode 100644 index 0000000..d4673c5 --- /dev/null +++ b/libcurl/src/lib/non-ascii.c @@ -0,0 +1,338 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +#include + +#include "non-ascii.h" +#include "formdata.h" +#include "sendf.h" +#include "urldata.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifdef HAVE_ICONV +#include +/* set default codesets for iconv */ +#ifndef CURL_ICONV_CODESET_OF_NETWORK +#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1" +#endif +#ifndef CURL_ICONV_CODESET_FOR_UTF8 +#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8" +#endif +#define ICONV_ERROR (size_t)-1 +#endif /* HAVE_ICONV */ + +/* + * Curl_convert_clone() returns a malloced copy of the source string (if + * returning CURLE_OK), with the data converted to network format. + */ +CURL_STATIC CURLcode Curl_convert_clone(struct SessionHandle *data, + const char *indata, + size_t insize, + char **outbuf) +{ + char *convbuf; + CURLcode result; + + convbuf = malloc(insize); + if(!convbuf) + return CURLE_OUT_OF_MEMORY; + + memcpy(convbuf, indata, insize); + result = Curl_convert_to_network(data, convbuf, insize); + if(result) { + free(convbuf); + return result; + } + + *outbuf = convbuf; /* return the converted buffer */ + + return CURLE_OK; +} + +/* + * Curl_convert_to_network() is an internal function for performing ASCII + * conversions on non-ASCII platforms. It convers the buffer _in place_. + */ +CURL_STATIC CURLcode Curl_convert_to_network(struct SessionHandle *data, + char *buffer, size_t length) +{ + if(data->set.convtonetwork) { + /* use translation callback */ + CURLcode result = data->set.convtonetwork(buffer, length); + if(result) { + failf(data, + "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + char *input_ptr, *output_ptr; + size_t in_bytes, out_bytes, rc; + int error; + + /* open an iconv conversion descriptor if necessary */ + if(data->outbound_cd == (iconv_t)-1) { + data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST); + if(data->outbound_cd == (iconv_t)-1) { + error = ERRNO; + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST, + error, strerror(error)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + error = ERRNO; + failf(data, + "The Curl_convert_to_network iconv call failed with errno %i: %s", + error, strerror(error)); + return CURLE_CONV_FAILED; + } +#else + failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Curl_convert_from_network() is an internal function for performing ASCII + * conversions on non-ASCII platforms. It convers the buffer _in place_. + */ +CURL_STATIC CURLcode Curl_convert_from_network(struct SessionHandle *data, + char *buffer, size_t length) +{ + if(data->set.convfromnetwork) { + /* use translation callback */ + CURLcode result = data->set.convfromnetwork(buffer, length); + if(result) { + failf(data, + "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + char *input_ptr, *output_ptr; + size_t in_bytes, out_bytes, rc; + int error; + + /* open an iconv conversion descriptor if necessary */ + if(data->inbound_cd == (iconv_t)-1) { + data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK); + if(data->inbound_cd == (iconv_t)-1) { + error = ERRNO; + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK, + error, strerror(error)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + error = ERRNO; + failf(data, + "Curl_convert_from_network iconv call failed with errno %i: %s", + error, strerror(error)); + return CURLE_CONV_FAILED; + } +#else + failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Curl_convert_from_utf8() is an internal function for performing UTF-8 + * conversions on non-ASCII platforms. + */ +CURL_STATIC CURLcode Curl_convert_from_utf8(struct SessionHandle *data, + char *buffer, size_t length) +{ + if(data->set.convfromutf8) { + /* use translation callback */ + CURLcode result = data->set.convfromutf8(buffer, length); + if(result) { + failf(data, + "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + const char *input_ptr; + char *output_ptr; + size_t in_bytes, out_bytes, rc; + int error; + + /* open an iconv conversion descriptor if necessary */ + if(data->utf8_cd == (iconv_t)-1) { + data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8); + if(data->utf8_cd == (iconv_t)-1) { + error = ERRNO; + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8, + error, strerror(error)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(data->utf8_cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + error = ERRNO; + failf(data, + "The Curl_convert_from_utf8 iconv call failed with errno %i: %s", + error, strerror(error)); + return CURLE_CONV_FAILED; + } + if(output_ptr < input_ptr) { + /* null terminate the now shorter output string */ + *output_ptr = 0x00; + } +#else + failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Init conversion stuff for a SessionHandle + */ +CURL_STATIC void Curl_convert_init(struct SessionHandle *data) +{ +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) + /* conversion descriptors for iconv calls */ + data->outbound_cd = (iconv_t)-1; + data->inbound_cd = (iconv_t)-1; + data->utf8_cd = (iconv_t)-1; +#else + (void)data; +#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ +} + +/* + * Setup conversion stuff for a SessionHandle + */ +CURL_STATIC void Curl_convert_setup(struct SessionHandle *data) +{ + data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK); + data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST); + data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8); +} + +/* + * Close conversion stuff for a SessionHandle + */ + +CURL_STATIC void Curl_convert_close(struct SessionHandle *data) +{ +#ifdef HAVE_ICONV + /* close iconv conversion descriptors */ + if(data->inbound_cd != (iconv_t)-1) { + iconv_close(data->inbound_cd); + } + if(data->outbound_cd != (iconv_t)-1) { + iconv_close(data->outbound_cd); + } + if(data->utf8_cd != (iconv_t)-1) { + iconv_close(data->utf8_cd); + } +#else + (void)data; +#endif /* HAVE_ICONV */ +} + +/* + * Curl_convert_form() is used from http.c, this converts any form items that + need to be sent in the network encoding. Returns CURLE_OK on success. + */ +CURL_STATIC CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form) +{ + CURLcode result; + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + while(form) { + if(form->type == FORM_DATA) { + result = Curl_convert_to_network(data, form->line, form->length); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + } + + form = form->next; + } + + return CURLE_OK; +} + +#endif /* CURL_DOES_CONVERSIONS */ diff --git a/libcurl/src/lib/non-ascii.h b/libcurl/src/lib/non-ascii.h new file mode 100644 index 0000000..fa0bf7b --- /dev/null +++ b/libcurl/src/lib/non-ascii.h @@ -0,0 +1,63 @@ +#ifndef HEADER_CURL_NON_ASCII_H +#define HEADER_CURL_NON_ASCII_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +#include "urldata.h" + +/* + * Curl_convert_clone() returns a malloced copy of the source string (if + * returning CURLE_OK), with the data converted to network format. + * + * If no conversion was needed *outbuf may be NULL. + */ +CURL_STATIC CURLcode Curl_convert_clone(struct SessionHandle *data, + const char *indata, + size_t insize, + char **outbuf); + +CURL_STATIC void Curl_convert_init(struct SessionHandle *data); +CURL_STATIC void Curl_convert_setup(struct SessionHandle *data); +CURL_STATIC void Curl_convert_close(struct SessionHandle *data); + +CURL_STATIC CURLcode Curl_convert_to_network(struct SessionHandle *data, + char *buffer, size_t length); +CURL_STATIC CURLcode Curl_convert_from_network(struct SessionHandle *data, + char *buffer, size_t length); +CURL_STATIC CURLcode Curl_convert_from_utf8(struct SessionHandle *data, + char *buffer, size_t length); +CURL_STATIC CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form); +#else +#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK) +#define Curl_convert_init(x) Curl_nop_stmt +#define Curl_convert_setup(x) Curl_nop_stmt +#define Curl_convert_close(x) Curl_nop_stmt +#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_form(a,b) CURLE_OK +#endif + +#endif /* HEADER_CURL_NON_ASCII_H */ diff --git a/libcurl/src/lib/nonblock.c b/libcurl/src/lib/nonblock.c new file mode 100644 index 0000000..dd5237a --- /dev/null +++ b/libcurl/src/lib/nonblock.c @@ -0,0 +1,91 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#include "nonblock.h" + +/* + * curlx_nonblock() set the given socket to either blocking or non-blocking + * mode based on the 'nonblock' boolean argument. This function is highly + * portable. + */ +CURL_STATIC int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ + int nonblock /* TRUE or FALSE */) +{ +#if defined(USE_BLOCKING_SOCKETS) + + return 0; /* returns success */ + +#elif defined(HAVE_FCNTL_O_NONBLOCK) + + /* most recent unix versions */ + int flags; + flags = sfcntl(sockfd, F_GETFL, 0); + if(nonblock) + return sfcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + else + return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); + +#elif defined(HAVE_IOCTL_FIONBIO) + + /* older unix versions */ + int flags = nonblock ? 1 : 0; + return ioctl(sockfd, FIONBIO, &flags); + +#elif defined(HAVE_IOCTLSOCKET_FIONBIO) + + /* Windows */ + unsigned long flags = nonblock ? 1UL : 0UL; + return ioctlsocket(sockfd, FIONBIO, &flags); + +#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) + + /* Amiga */ + long flags = nonblock ? 1L : 0L; + return IoctlSocket(sockfd, FIONBIO, flags); + +#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) + + /* BeOS */ + long b = nonblock ? 1L : 0L; + return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); + +#else +# error "no non-blocking method was found/used/set" +#endif +} diff --git a/libcurl/src/lib/nonblock.h b/libcurl/src/lib/nonblock.h new file mode 100644 index 0000000..52e0390 --- /dev/null +++ b/libcurl/src/lib/nonblock.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_NONBLOCK_H +#define HEADER_CURL_NONBLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include /* for curl_socket_t */ + +CURL_STATIC int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ + int nonblock /* TRUE or FALSE */); + +#endif /* HEADER_CURL_NONBLOCK_H */ + diff --git a/libcurl/src/lib/nwlib.c b/libcurl/src/lib/nwlib.c new file mode 100644 index 0000000..bd3f27e --- /dev/null +++ b/libcurl/src/lib/nwlib.c @@ -0,0 +1,325 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef NETWARE /* Novell NetWare */ + +#ifdef __NOVELL_LIBC__ +/* For native LibC-based NLM we need to register as a real lib. */ +#include +#include +#include +#include +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct +{ + int _errno; + void *twentybytes; +} libthreaddata_t; + +typedef struct +{ + int x; + int y; + int z; + void *tenbytes; + NXKey_t perthreadkey; /* if -1, no key obtained... */ + NXMutex_t *lock; +} libdata_t; + +int gLibId = -1; +void *gLibHandle = (void *) NULL; +rtag_t gAllocTag = (rtag_t) NULL; +NXMutex_t *gLibLock = (NXMutex_t *) NULL; + +/* internal library function prototypes... */ +int DisposeLibraryData( void * ); +void DisposeThreadData( void * ); +int GetOrSetUpData( int id, libdata_t **data, libthreaddata_t **threaddata ); + + +int _NonAppStart( void *NLMHandle, + void *errorScreen, + const char *cmdLine, + const char *loadDirPath, + size_t uninitializedDataLength, + void *NLMFileHandle, + int (*readRoutineP)( int conn, + void *fileHandle, size_t offset, + size_t nbytes, + size_t *bytesRead, + void *buffer ), + size_t customDataOffset, + size_t customDataSize, + int messageCount, + const char **messages ) +{ + NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0); + +#ifndef __GNUC__ +#pragma unused(cmdLine) +#pragma unused(loadDirPath) +#pragma unused(uninitializedDataLength) +#pragma unused(NLMFileHandle) +#pragma unused(readRoutineP) +#pragma unused(customDataOffset) +#pragma unused(customDataSize) +#pragma unused(messageCount) +#pragma unused(messages) +#endif + + /* + * Here we process our command line, post errors (to the error screen), + * perform initializations and anything else we need to do before being able + * to accept calls into us. If we succeed, we return non-zero and the NetWare + * Loader will leave us up, otherwise we fail to load and get dumped. + */ + gAllocTag = AllocateResourceTag(NLMHandle, + " memory allocations", + AllocSignature); + + if(!gAllocTag) { + OutputToScreen(errorScreen, "Unable to allocate resource tag for " + "library memory allocations.\n"); + return -1; + } + + gLibId = register_library(DisposeLibraryData); + + if(gLibId < -1) { + OutputToScreen(errorScreen, "Unable to register library with kernel.\n"); + return -1; + } + + gLibHandle = NLMHandle; + + gLibLock = NXMutexAlloc(0, 0, &liblock); + + if(!gLibLock) { + OutputToScreen(errorScreen, "Unable to allocate library data lock.\n"); + return -1; + } + + return 0; +} + +/* + * Here we clean up any resources we allocated. Resource tags is a big part + * of what we created, but NetWare doesn't ask us to free those. + */ +void _NonAppStop( void ) +{ + (void) unregister_library(gLibId); + NXMutexFree(gLibLock); +} + +/* + * This function cannot be the first in the file for if the file is linked + * first, then the check-unload function's offset will be nlmname.nlm+0 + * which is how to tell that there isn't one. When the check function is + * first in the linked objects, it is ambiguous. For this reason, we will + * put it inside this file after the stop function. + * + * Here we check to see if it's alright to ourselves to be unloaded. If not, + * we return a non-zero value. Right now, there isn't any reason not to allow + * it. + */ +int _NonAppCheckUnload( void ) +{ + return 0; +} + +int GetOrSetUpData(int id, libdata_t **appData, + libthreaddata_t **threadData ) +{ + int err; + libdata_t *app_data; + libthreaddata_t *thread_data; + NXKey_t key; + NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0); + + err = 0; + thread_data = (libthreaddata_t *) NULL; + + /* + * Attempt to get our data for the application calling us. This is where we + * store whatever application-specific information we need to carry in + * support of calling applications. + */ + app_data = (libdata_t *) get_app_data(id); + + if(!app_data) { + /* + * This application hasn't called us before; set up application AND + * per-thread data. Of course, just in case a thread from this same + * application is calling us simultaneously, we better lock our application + * data-creation mutex. We also need to recheck for data after we acquire + * the lock because WE might be that other thread that was too late to + * create the data and the first thread in will have created it. + */ + NXLock(gLibLock); + + if(!(app_data = (libdata_t *) get_app_data(id))) { + app_data = malloc(sizeof(libdata_t)); + + if(app_data) { + memset(app_data, 0, sizeof(libdata_t)); + + app_data->tenbytes = malloc(10); + app_data->lock = NXMutexAlloc(0, 0, &liblock); + + if(!app_data->tenbytes || !app_data->lock) { + if(app_data->lock) + NXMutexFree(app_data->lock); + + free(app_data); + app_data = (libdata_t *) NULL; + err = ENOMEM; + } + + if(app_data) { + /* + * Here we burn in the application data that we were trying to get + * by calling get_app_data(). Next time we call the first function, + * we'll get this data we're just now setting. We also go on here to + * establish the per-thread data for the calling thread, something + * we'll have to do on each application thread the first time + * it calls us. + */ + err = set_app_data(gLibId, app_data); + + if(err) { + free(app_data); + app_data = (libdata_t *) NULL; + err = ENOMEM; + } + else { + /* create key for thread-specific data... */ + err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key); + + if(err) /* (no more keys left?) */ + key = -1; + + app_data->perthreadkey = key; + } + } + } + } + + NXUnlock(gLibLock); + } + + if(app_data) { + key = app_data->perthreadkey; + + if(key != -1 /* couldn't create a key? no thread data */ + && !(err = NXKeyGetValue(key, (void **) &thread_data)) + && !thread_data) { + /* + * Allocate the per-thread data for the calling thread. Regardless of + * whether there was already application data or not, this may be the + * first call by a new thread. The fact that we allocation 20 bytes on + * a pointer is not very important, this just helps to demonstrate that + * we can have arbitrarily complex per-thread data. + */ + thread_data = malloc(sizeof(libthreaddata_t)); + + if(thread_data) { + thread_data->_errno = 0; + thread_data->twentybytes = malloc(20); + + if(!thread_data->twentybytes) { + free(thread_data); + thread_data = (libthreaddata_t *) NULL; + err = ENOMEM; + } + + if((err = NXKeySetValue(key, thread_data))) { + free(thread_data->twentybytes); + free(thread_data); + thread_data = (libthreaddata_t *) NULL; + } + } + } + } + + if(appData) + *appData = app_data; + + if(threadData) + *threadData = thread_data; + + return err; +} + +int DisposeLibraryData( void *data ) +{ + if(data) { + void *tenbytes = ((libdata_t *) data)->tenbytes; + + free(tenbytes); + free(data); + } + + return 0; +} + +void DisposeThreadData( void *data ) +{ + if(data) { + void *twentybytes = ((libthreaddata_t *) data)->twentybytes; + + free(twentybytes); + free(data); + } +} + +#else /* __NOVELL_LIBC__ */ +/* For native CLib-based NLM seems we can do a bit more simple. */ +#include + +int main ( void ) +{ + /* initialize any globals here... */ + + /* do this if any global initializing was done + SynchronizeStart(); + */ + ExitThread (TSR_THREAD, 0); + return 0; +} + +#endif /* __NOVELL_LIBC__ */ + +#else /* NETWARE */ + +#ifdef __POCC__ +# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */ +#endif + +#endif /* NETWARE */ diff --git a/libcurl/src/lib/nwos.c b/libcurl/src/lib/nwos.c new file mode 100644 index 0000000..23ff2a7 --- /dev/null +++ b/libcurl/src/lib/nwos.c @@ -0,0 +1,88 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef NETWARE /* Novell NetWare */ + +#ifdef __NOVELL_LIBC__ +/* For native LibC-based NLM we need to do nothing. */ +int netware_init ( void ) +{ + return 0; +} + +#else /* __NOVELL_LIBC__ */ + +/* For native CLib-based NLM we need to initialize the LONG namespace. */ +#include +#include +#include +/* Make the CLIB Ctx stuff link */ +#include +NETDB_DEFINE_CONTEXT +/* Make the CLIB Inet stuff link */ +#include +#include +NETINET_DEFINE_CONTEXT + +int netware_init ( void ) +{ + int rc = 0; + unsigned int myHandle = GetNLMHandle(); + /* import UnAugmentAsterisk dynamically for NW4.x compatibility */ + void (*pUnAugmentAsterisk)(int) = (void(*)(int)) + ImportSymbol(myHandle, "UnAugmentAsterisk"); + /* import UseAccurateCaseForPaths dynamically for NW3.x compatibility */ + void (*pUseAccurateCaseForPaths)(int) = (void(*)(int)) + ImportSymbol(myHandle, "UseAccurateCaseForPaths"); + if(pUnAugmentAsterisk) + pUnAugmentAsterisk(1); + if(pUseAccurateCaseForPaths) + pUseAccurateCaseForPaths(1); + UnimportSymbol(myHandle, "UnAugmentAsterisk"); + UnimportSymbol(myHandle, "UseAccurateCaseForPaths"); + /* set long name space */ + if((SetCurrentNameSpace(4) == 255)) { + rc = 1; + } + if((SetTargetNameSpace(4) == 255)) { + rc = rc + 2; + } + return rc; +} + +/* dummy function to satisfy newer prelude */ +int __init_environment ( void ) +{ + return 0; +} + +/* dummy function to satisfy newer prelude */ +int __deinit_environment ( void ) +{ + return 0; +} + +#endif /* __NOVELL_LIBC__ */ + +#endif /* NETWARE */ diff --git a/libcurl/src/lib/openldap.c b/libcurl/src/lib/openldap.c new file mode 100644 index 0000000..bee552f --- /dev/null +++ b/libcurl/src/lib/openldap.c @@ -0,0 +1,684 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Howard Chu, + * Copyright (C) 2011 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP) + +/* + * Notice that USE_OPENLDAP is only a source code selection switch. When + * libcurl is built with USE_OPENLDAP defined the libcurl source code that + * gets compiled is the code from openldap.c, otherwise the code that gets + * compiled is the code from ldap.c. + * + * When USE_OPENLDAP is defined a recent version of the OpenLDAP library + * might be required for compilation and runtime. In order to use ancient + * OpenLDAP library versions, USE_OPENLDAP shall not be defined. + */ + +#include + +#include "urldata.h" +#include +#include "sendf.h" +#include "vtls/vtls.h" +#include "transfer.h" +#include "curl_ldap.h" +#include "curl_base64.h" +#include "connect.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef _LDAP_PVT_H +extern int ldap_pvt_url_scheme2proto(const char *); +extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, + LDAP **ld); +#endif + +static CURLcode ldap_setup_connection(struct connectdata *conn); +static CURLcode ldap_do(struct connectdata *conn, bool *done); +static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); +static CURLcode ldap_connect(struct connectdata *conn, bool *done); +static CURLcode ldap_connecting(struct connectdata *conn, bool *done); +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead); + +static Curl_recv ldap_recv; + +/* + * LDAP protocol handler. + */ + +const struct Curl_handler Curl_handler_ldap = { + "LDAP", /* scheme */ + ldap_setup_connection, /* setup_connection */ + ldap_do, /* do_it */ + ldap_done, /* done */ + ZERO_NULL, /* do_more */ + ldap_connect, /* connect_it */ + ldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * LDAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ldaps = { + "LDAPS", /* scheme */ + ldap_setup_connection, /* setup_connection */ + ldap_do, /* do_it */ + ldap_done, /* done */ + ZERO_NULL, /* do_more */ + ldap_connect, /* connect_it */ + ldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + +static const char *url_errs[] = { + "success", + "out of memory", + "bad parameter", + "unrecognized scheme", + "unbalanced delimiter", + "bad URL", + "bad host or port", + "bad or missing attributes", + "bad or missing scope", + "bad or missing filter", + "bad or missing extensions" +}; + +typedef struct ldapconninfo { + LDAP *ld; + Curl_recv *recv; /* for stacking SSL handler */ + Curl_send *send; + int proto; + int msgid; + bool ssldone; + bool sslinst; + bool didbind; +} ldapconninfo; + +typedef struct ldapreqinfo { + int msgid; + int nument; +} ldapreqinfo; + +static CURLcode ldap_setup_connection(struct connectdata *conn) +{ + ldapconninfo *li; + LDAPURLDesc *lud; + struct SessionHandle *data=conn->data; + int rc, proto; + CURLcode status; + + rc = ldap_url_parse(data->change.url, &lud); + if(rc != LDAP_URL_SUCCESS) { + const char *msg = "url parsing problem"; + status = CURLE_URL_MALFORMAT; + if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if(rc == LDAP_URL_ERR_MEM) + status = CURLE_OUT_OF_MEMORY; + msg = url_errs[rc]; + } + failf(conn->data, "LDAP local: %s", msg); + return status; + } + proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); + ldap_free_urldesc(lud); + + li = calloc(1, sizeof(ldapconninfo)); + if(!li) + return CURLE_OUT_OF_MEMORY; + li->proto = proto; + conn->proto.generic = li; + connkeep(conn, "OpenLDAP default"); + /* TODO: + * - provide option to choose SASL Binds instead of Simple + */ + return CURLE_OK; +} + +#ifdef USE_SSL +static Sockbuf_IO ldapsb_tls; +#endif + +static CURLcode ldap_connect(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + struct SessionHandle *data = conn->data; + int rc, proto = LDAP_VERSION3; + char hosturl[1024]; + char *ptr; + + (void)done; + + strcpy(hosturl, "ldap"); + ptr = hosturl+4; + if(conn->handler->flags & PROTOPT_SSL) + *ptr++ = 's'; + snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", + conn->host.name, conn->remote_port); + + rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); + if(rc) { + failf(data, "LDAP local: Cannot connect to %s, %s", + hosturl, ldap_err2string(rc)); + return CURLE_COULDNT_CONNECT; + } + + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + +#ifdef USE_SSL + if(conn->handler->flags & PROTOPT_SSL) { + CURLcode result; + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); + if(result) + return result; + } +#endif + + return CURLE_OK; +} + +static CURLcode ldap_connecting(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + struct SessionHandle *data = conn->data; + LDAPMessage *msg = NULL; + struct timeval tv = {0, 1}, *tvp; + int rc, err; + char *info = NULL; + +#ifdef USE_SSL + if(conn->handler->flags & PROTOPT_SSL) { + /* Is the SSL handshake complete yet? */ + if(!li->ssldone) { + CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + &li->ssldone); + if(result || !li->ssldone) + return result; + } + + /* Have we installed the libcurl SSL handlers into the sockbuf yet? */ + if(!li->sslinst) { + Sockbuf *sb; + ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); + ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn); + li->sslinst = TRUE; + li->recv = conn->recv[FIRSTSOCKET]; + li->send = conn->send[FIRSTSOCKET]; + } + } +#endif + + tvp = &tv; + +retry: + if(!li->didbind) { + char *binddn; + struct berval passwd; + + if(conn->bits.user_passwd) { + binddn = conn->user; + passwd.bv_val = conn->passwd; + passwd.bv_len = strlen(passwd.bv_val); + } + else { + binddn = NULL; + passwd.bv_val = NULL; + passwd.bv_len = 0; + } + rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd, + NULL, NULL, &li->msgid); + if(rc) + return CURLE_LDAP_CANNOT_BIND; + li->didbind = TRUE; + if(tvp) + return CURLE_OK; + } + + rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &msg); + if(rc < 0) { + failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc)); + return CURLE_LDAP_CANNOT_BIND; + } + if(rc == 0) { + /* timed out */ + return CURLE_OK; + } + + rc = ldap_parse_result(li->ld, msg, &err, NULL, &info, NULL, NULL, 1); + if(rc) { + failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc)); + return CURLE_LDAP_CANNOT_BIND; + } + + /* Try to fallback to LDAPv2? */ + if(err == LDAP_PROTOCOL_ERROR) { + int proto; + ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + if(proto == LDAP_VERSION3) { + if(info) { + ldap_memfree(info); + info = NULL; + } + proto = LDAP_VERSION2; + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + li->didbind = FALSE; + goto retry; + } + } + + if(err) { + failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc), + info ? info : ""); + if(info) + ldap_memfree(info); + return CURLE_LOGIN_DENIED; + } + + if(info) + ldap_memfree(info); + conn->recv[FIRSTSOCKET] = ldap_recv; + *done = TRUE; + + return CURLE_OK; +} + +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) +{ + ldapconninfo *li = conn->proto.generic; + (void) dead_connection; + + if(li) { + if(li->ld) { + ldap_unbind_ext(li->ld, NULL, NULL); + li->ld = NULL; + } + conn->proto.generic = NULL; + free(li); + } + return CURLE_OK; +} + +static CURLcode ldap_do(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + ldapreqinfo *lr; + CURLcode status = CURLE_OK; + int rc = 0; + LDAPURLDesc *ludp = NULL; + int msgid; + struct SessionHandle *data=conn->data; + + connkeep(conn, "OpenLDAP do"); + + infof(data, "LDAP local: %s\n", data->change.url); + + rc = ldap_url_parse(data->change.url, &ludp); + if(rc != LDAP_URL_SUCCESS) { + const char *msg = "url parsing problem"; + status = CURLE_URL_MALFORMAT; + if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if(rc == LDAP_URL_ERR_MEM) + status = CURLE_OUT_OF_MEMORY; + msg = url_errs[rc]; + } + failf(conn->data, "LDAP local: %s", msg); + return status; + } + + rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope, + ludp->lud_filter, ludp->lud_attrs, 0, + NULL, NULL, NULL, 0, &msgid); + ldap_free_urldesc(ludp); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); + return CURLE_LDAP_SEARCH_FAILED; + } + lr = calloc(1, sizeof(ldapreqinfo)); + if(!lr) + return CURLE_OUT_OF_MEMORY; + lr->msgid = msgid; + data->req.protop = lr; + Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + *done = TRUE; + return CURLE_OK; +} + +static CURLcode ldap_done(struct connectdata *conn, CURLcode res, + bool premature) +{ + ldapreqinfo *lr = conn->data->req.protop; + + (void)res; + (void)premature; + + if(lr) { + /* if there was a search in progress, abandon it */ + if(lr->msgid) { + ldapconninfo *li = conn->proto.generic; + ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); + lr->msgid = 0; + } + conn->data->req.protop = NULL; + free(lr); + } + + return CURLE_OK; +} + +static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, + size_t len, CURLcode *err) +{ + ldapconninfo *li = conn->proto.generic; + struct SessionHandle *data = conn->data; + ldapreqinfo *lr = data->req.protop; + int rc, ret; + LDAPMessage *msg = NULL; + LDAPMessage *ent; + BerElement *ber = NULL; + struct timeval tv = {0, 1}; + + (void)len; + (void)buf; + (void)sockindex; + + rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg); + if(rc < 0) { + failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); + *err = CURLE_RECV_ERROR; + return -1; + } + + *err = CURLE_AGAIN; + ret = -1; + + /* timed out */ + if(!msg) + return ret; + + for(ent = ldap_first_message(li->ld, msg); ent; + ent = ldap_next_message(li->ld, ent)) { + struct berval bv, *bvals, **bvp = &bvals; + int binary = 0, msgtype; + + msgtype = ldap_msgtype(ent); + if(msgtype == LDAP_RES_SEARCH_RESULT) { + int code; + char *info = NULL; + rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); + if(rc) { + failf(data, "LDAP local: search ldap_parse_result %s", + ldap_err2string(rc)); + *err = CURLE_LDAP_SEARCH_FAILED; + } + else if(code && code != LDAP_SIZELIMIT_EXCEEDED) { + failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), + info ? info : ""); + *err = CURLE_LDAP_SEARCH_FAILED; + } + else { + /* successful */ + if(code == LDAP_SIZELIMIT_EXCEEDED) + infof(data, "There are more than %d entries\n", lr->nument); + data->req.size = data->req.bytecount; + *err = CURLE_OK; + ret = 0; + } + lr->msgid = 0; + ldap_memfree(info); + break; + } + else if(msgtype != LDAP_RES_SEARCH_ENTRY) + continue; + + lr->nument++; + rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); + if(rc < 0) { + /* TODO: verify that this is really how this return code should be + handled */ + *err = CURLE_RECV_ERROR; + return -1; + } + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + if(*err) + return -1; + + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); + if(*err) + return -1; + + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(*err) + return -1; + data->req.bytecount += bv.bv_len + 5; + + for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) { + int i; + + if(bv.bv_val == NULL) break; + + if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) + binary = 1; + else + binary = 0; + + for(i=0; bvals[i].bv_val != NULL; i++) { + int binval = 0; + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + if(*err) + return -1; + + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); + if(*err) + return -1; + + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); + if(*err) + return -1; + data->req.bytecount += bv.bv_len + 2; + + if(!binary) { + /* check for leading or trailing whitespace */ + if(ISSPACE(bvals[i].bv_val[0]) || + ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) + binval = 1; + else { + /* check for unprintable characters */ + unsigned int j; + for(j=0; jreq.bytecount += 2; + if(val_b64_sz > 0) { + *err = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, + val_b64_sz); + if(*err) + return -1; + free(val_b64); + data->req.bytecount += val_b64_sz; + } + } + else { + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); + if(*err) + return -1; + + *err = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, + bvals[i].bv_len); + if(*err) + return -1; + + data->req.bytecount += bvals[i].bv_len + 1; + } + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(*err) + return -1; + + data->req.bytecount++; + } + ber_memfree(bvals); + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(*err) + return -1; + data->req.bytecount++; + } + *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(*err) + return -1; + data->req.bytecount++; + ber_free(ber, 0); + } + ldap_msgfree(msg); + return ret; +} + +#ifdef USE_SSL +static int +ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) +{ + sbiod->sbiod_pvt = arg; + return 0; +} + +static int +ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod) +{ + sbiod->sbiod_pvt = NULL; + return 0; +} + +/* We don't need to do anything because libcurl does it already */ +static int +ldapsb_tls_close(Sockbuf_IO_Desc *sbiod) +{ + (void)sbiod; + return 0; +} + +static int +ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) +{ + (void)arg; + if(opt == LBER_SB_OPT_DATA_READY) { + struct connectdata *conn = sbiod->sbiod_pvt; + return Curl_ssl_data_pending(conn, FIRSTSOCKET); + } + return 0; +} + +static ber_slen_t +ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct connectdata *conn = sbiod->sbiod_pvt; + ldapconninfo *li = conn->proto.generic; + ber_slen_t ret; + CURLcode err = CURLE_RECV_ERROR; + + ret = li->recv(conn, FIRSTSOCKET, buf, len, &err); + if(ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + return ret; +} + +static ber_slen_t +ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct connectdata *conn = sbiod->sbiod_pvt; + ldapconninfo *li = conn->proto.generic; + ber_slen_t ret; + CURLcode err = CURLE_SEND_ERROR; + + ret = li->send(conn, FIRSTSOCKET, buf, len, &err); + if(ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + return ret; +} + +static Sockbuf_IO ldapsb_tls = +{ + ldapsb_tls_setup, + ldapsb_tls_remove, + ldapsb_tls_ctrl, + ldapsb_tls_read, + ldapsb_tls_write, + ldapsb_tls_close +}; +#endif /* USE_SSL */ + +#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ diff --git a/libcurl/src/lib/parsedate.c b/libcurl/src/lib/parsedate.c new file mode 100644 index 0000000..4297696 --- /dev/null +++ b/libcurl/src/lib/parsedate.c @@ -0,0 +1,583 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + A brief summary of the date string formats this parser groks: + + RFC 2616 3.3.1 + + Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 + Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + + we support dates without week day name: + + 06 Nov 1994 08:49:37 GMT + 06-Nov-94 08:49:37 GMT + Nov 6 08:49:37 1994 + + without the time zone: + + 06 Nov 1994 08:49:37 + 06-Nov-94 08:49:37 + + weird order: + + 1994 Nov 6 08:49:37 (GNU date fails) + GMT 08:49:37 06-Nov-94 Sunday + 94 6 Nov 08:49:37 (GNU date fails) + + time left out: + + 1994 Nov 6 + 06-Nov-94 + Sun Nov 6 94 + + unusual separators: + + 1994.Nov.6 + Sun/Nov/6/94/GMT + + commonly used time zone names: + + Sun, 06 Nov 1994 08:49:37 CET + 06 Nov 1994 08:49:37 EST + + time zones specified using RFC822 style: + + Sun, 12 Sep 2004 15:05:58 -0700 + Sat, 11 Sep 2004 21:32:11 +0200 + + compact numerical date strings: + + 20040912 15:05:58 -0700 + 20040911 +0200 + +*/ + +#include "curl_setup.h" + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include +#include "rawstr.h" +#include "warnless.h" +#include "parsedate.h" + +static const char * const Curl_wkday[] = +{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; +static const char * const weekday[] = +{ "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; +static const char * const Curl_month[]= +{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +struct tzinfo { + char name[5]; + int offset; /* +/- in minutes */ +}; + +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output); + +#define PARSEDATE_OK 0 +#define PARSEDATE_FAIL -1 +#define PARSEDATE_LATER 1 +#define PARSEDATE_SOONER 2 + +/* Here's a bunch of frequently used time zone names. These were supported + by the old getdate parser. */ +#define tDAYZONE -60 /* offset for daylight savings time */ +static const struct tzinfo tz[]= { + {"GMT", 0}, /* Greenwich Mean */ + {"UTC", 0}, /* Universal (Coordinated) */ + {"WET", 0}, /* Western European */ + {"BST", 0 tDAYZONE}, /* British Summer */ + {"WAT", 60}, /* West Africa */ + {"AST", 240}, /* Atlantic Standard */ + {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */ + {"EST", 300}, /* Eastern Standard */ + {"EDT", 300 tDAYZONE}, /* Eastern Daylight */ + {"CST", 360}, /* Central Standard */ + {"CDT", 360 tDAYZONE}, /* Central Daylight */ + {"MST", 420}, /* Mountain Standard */ + {"MDT", 420 tDAYZONE}, /* Mountain Daylight */ + {"PST", 480}, /* Pacific Standard */ + {"PDT", 480 tDAYZONE}, /* Pacific Daylight */ + {"YST", 540}, /* Yukon Standard */ + {"YDT", 540 tDAYZONE}, /* Yukon Daylight */ + {"HST", 600}, /* Hawaii Standard */ + {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */ + {"CAT", 600}, /* Central Alaska */ + {"AHST", 600}, /* Alaska-Hawaii Standard */ + {"NT", 660}, /* Nome */ + {"IDLW", 720}, /* International Date Line West */ + {"CET", -60}, /* Central European */ + {"MET", -60}, /* Middle European */ + {"MEWT", -60}, /* Middle European Winter */ + {"MEST", -60 tDAYZONE}, /* Middle European Summer */ + {"CEST", -60 tDAYZONE}, /* Central European Summer */ + {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ + {"FWT", -60}, /* French Winter */ + {"FST", -60 tDAYZONE}, /* French Summer */ + {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ + {"WAST", -420}, /* West Australian Standard */ + {"WADT", -420 tDAYZONE}, /* West Australian Daylight */ + {"CCT", -480}, /* China Coast, USSR Zone 7 */ + {"JST", -540}, /* Japan Standard, USSR Zone 8 */ + {"EAST", -600}, /* Eastern Australian Standard */ + {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */ + {"GST", -600}, /* Guam Standard, USSR Zone 9 */ + {"NZT", -720}, /* New Zealand */ + {"NZST", -720}, /* New Zealand Standard */ + {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ + {"IDLE", -720}, /* International Date Line East */ + /* Next up: Military timezone names. RFC822 allowed these, but (as noted in + RFC 1123) had their signs wrong. Here we use the correct signs to match + actual military usage. + */ + {"A", +1 * 60}, /* Alpha */ + {"B", +2 * 60}, /* Bravo */ + {"C", +3 * 60}, /* Charlie */ + {"D", +4 * 60}, /* Delta */ + {"E", +5 * 60}, /* Echo */ + {"F", +6 * 60}, /* Foxtrot */ + {"G", +7 * 60}, /* Golf */ + {"H", +8 * 60}, /* Hotel */ + {"I", +9 * 60}, /* India */ + /* "J", Juliet is not used as a timezone, to indicate the observer's local + time */ + {"K", +10 * 60}, /* Kilo */ + {"L", +11 * 60}, /* Lima */ + {"M", +12 * 60}, /* Mike */ + {"N", -1 * 60}, /* November */ + {"O", -2 * 60}, /* Oscar */ + {"P", -3 * 60}, /* Papa */ + {"Q", -4 * 60}, /* Quebec */ + {"R", -5 * 60}, /* Romeo */ + {"S", -6 * 60}, /* Sierra */ + {"T", -7 * 60}, /* Tango */ + {"U", -8 * 60}, /* Uniform */ + {"V", -9 * 60}, /* Victor */ + {"W", -10 * 60}, /* Whiskey */ + {"X", -11 * 60}, /* X-ray */ + {"Y", -12 * 60}, /* Yankee */ + {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */ +}; + +/* returns: + -1 no day + 0 monday - 6 sunday +*/ + +static int checkday(const char *check, size_t len) +{ + int i; + const char * const *what; + bool found= FALSE; + if(len > 3) + what = &weekday[0]; + else + what = &Curl_wkday[0]; + for(i=0; i<7; i++) { + if(Curl_raw_equal(check, what[0])) { + found=TRUE; + break; + } + what++; + } + return found?i:-1; +} + +static int checkmonth(const char *check) +{ + int i; + const char * const *what; + bool found= FALSE; + + what = &Curl_month[0]; + for(i=0; i<12; i++) { + if(Curl_raw_equal(check, what[0])) { + found=TRUE; + break; + } + what++; + } + return found?i:-1; /* return the offset or -1, no real offset is -1 */ +} + +/* return the time zone offset between GMT and the input one, in number + of seconds or -1 if the timezone wasn't found/legal */ + +static int checktz(const char *check) +{ + unsigned int i; + const struct tzinfo *what; + bool found= FALSE; + + what = tz; + for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) { + if(Curl_raw_equal(check, what->name)) { + found=TRUE; + break; + } + what++; + } + return found?what->offset*60:-1; +} + +static void skip(const char **date) +{ + /* skip everything that aren't letters or digits */ + while(**date && !ISALNUM(**date)) + (*date)++; +} + +enum assume { + DATE_MDAY, + DATE_YEAR, + DATE_TIME +}; + +/* this is a clone of 'struct tm' but with all fields we don't need or use + cut out */ +struct my_tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; +}; + +/* struct tm to time since epoch in GMT time zone. + * This is similar to the standard mktime function but for GMT only, and + * doesn't suffer from the various bugs and portability problems that + * some systems' implementations have. + */ +static time_t my_timegm(struct my_tm *tm) +{ + static const int month_days_cumulative [12] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + int month, year, leap_days; + + if(tm->tm_year < 70) + /* we don't support years before 1970 as they will cause this function + to return a negative value */ + return -1; + + year = tm->tm_year + 1900; + month = tm->tm_mon; + if(month < 0) { + year += (11 - month) / 12; + month = 11 - (11 - month) % 12; + } + else if(month >= 12) { + year -= month / 12; + month = month % 12; + } + + leap_days = year - (tm->tm_mon <= 1); + leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) + - (1969 / 4) + (1969 / 100) - (1969 / 400)); + + return ((((time_t) (year - 1970) * 365 + + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24 + + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec; +} + +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output) +{ + time_t t = 0; + int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ + int monnum=-1; /* month of the year number, 0-11 */ + int mdaynum=-1; /* day of month, 1 - 31 */ + int hournum=-1; + int minnum=-1; + int secnum=-1; + int yearnum=-1; + int tzoff=-1; + struct my_tm tm; + enum assume dignext = DATE_MDAY; + const char *indate = date; /* save the original pointer */ + int part = 0; /* max 6 parts */ + + while(*date && (part < 6)) { + bool found=FALSE; + + skip(&date); + + if(ISALPHA(*date)) { + /* a name coming up */ + char buf[32]=""; + size_t len; + if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz]", buf)) + len = strlen(buf); + else + len = 0; + + if(wdaynum == -1) { + wdaynum = checkday(buf, len); + if(wdaynum != -1) + found = TRUE; + } + if(!found && (monnum == -1)) { + monnum = checkmonth(buf); + if(monnum != -1) + found = TRUE; + } + + if(!found && (tzoff == -1)) { + /* this just must be a time zone string */ + tzoff = checktz(buf); + if(tzoff != -1) + found = TRUE; + } + + if(!found) + return PARSEDATE_FAIL; /* bad string */ + + date += len; + } + else if(ISDIGIT(*date)) { + /* a digit */ + int val; + char *end; + if((secnum == -1) && + (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) { + /* time stamp! */ + date += 8; + } + else if((secnum == -1) && + (2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) { + /* time stamp without seconds */ + date += 5; + secnum = 0; + } + else { + long lval; + int error; + int old_errno; + + old_errno = ERRNO; + SET_ERRNO(0); + lval = strtol(date, &end, 10); + error = ERRNO; + if(error != old_errno) + SET_ERRNO(old_errno); + + if(error) + return PARSEDATE_FAIL; + +#if LONG_MAX != INT_MAX + if((lval > (long)INT_MAX) || (lval < (long)INT_MIN)) + return PARSEDATE_FAIL; +#endif + + val = curlx_sltosi(lval); + + if((tzoff == -1) && + ((end - date) == 4) && + (val <= 1400) && + (indate< date) && + ((date[-1] == '+' || date[-1] == '-'))) { + /* four digits and a value less than or equal to 1400 (to take into + account all sorts of funny time zone diffs) and it is preceded + with a plus or minus. This is a time zone indication. 1400 is + picked since +1300 is frequently used and +1400 is mentioned as + an edge number in the document "ISO C 200X Proposal: Timezone + Functions" at http://david.tribble.com/text/c0xtimezone.html If + anyone has a more authoritative source for the exact maximum time + zone offsets, please speak up! */ + found = TRUE; + tzoff = (val/100 * 60 + val%100)*60; + + /* the + and - prefix indicates the local time compared to GMT, + this we need ther reversed math to get what we want */ + tzoff = date[-1]=='+'?-tzoff:tzoff; + } + + if(((end - date) == 8) && + (yearnum == -1) && + (monnum == -1) && + (mdaynum == -1)) { + /* 8 digits, no year, month or day yet. This is YYYYMMDD */ + found = TRUE; + yearnum = val/10000; + monnum = (val%10000)/100-1; /* month is 0 - 11 */ + mdaynum = val%100; + } + + if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { + if((val > 0) && (val<32)) { + mdaynum = val; + found = TRUE; + } + dignext = DATE_YEAR; + } + + if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { + yearnum = val; + found = TRUE; + if(yearnum < 1900) { + if(yearnum > 70) + yearnum += 1900; + else + yearnum += 2000; + } + if(mdaynum == -1) + dignext = DATE_MDAY; + } + + if(!found) + return PARSEDATE_FAIL; + + date = end; + } + } + + part++; + } + + if(-1 == secnum) + secnum = minnum = hournum = 0; /* no time, make it zero */ + + if((-1 == mdaynum) || + (-1 == monnum) || + (-1 == yearnum)) + /* lacks vital info, fail */ + return PARSEDATE_FAIL; + +#if SIZEOF_TIME_T < 5 + /* 32 bit time_t can only hold dates to the beginning of 2038 */ + if(yearnum > 2037) { + *output = 0x7fffffff; + return PARSEDATE_LATER; + } +#endif + + if(yearnum < 1970) { + *output = 0; + return PARSEDATE_SOONER; + } + + if((mdaynum > 31) || (monnum > 11) || + (hournum > 23) || (minnum > 59) || (secnum > 60)) + return PARSEDATE_FAIL; /* clearly an illegal date */ + + tm.tm_sec = secnum; + tm.tm_min = minnum; + tm.tm_hour = hournum; + tm.tm_mday = mdaynum; + tm.tm_mon = monnum; + tm.tm_year = yearnum - 1900; + + /* my_timegm() returns a time_t. time_t is often 32 bits, even on many + architectures that feature 64 bit 'long'. + + Some systems have 64 bit time_t and deal with years beyond 2038. However, + even on some of the systems with 64 bit time_t mktime() returns -1 for + dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06) + */ + t = my_timegm(&tm); + + /* time zone adjust (cast t to int to compare to negative one) */ + if(-1 != (int)t) { + + /* Add the time zone diff between local time zone and GMT. */ + long delta = (long)(tzoff!=-1?tzoff:0); + + if((delta>0) && (t > LONG_MAX - delta)) { + *output = 0x7fffffff; + return PARSEDATE_LATER; /* time_t overflow */ + } + + t += delta; + } + + *output = t; + + return PARSEDATE_OK; +} + +time_t curl_getdate(const char *p, const time_t *now) +{ + time_t parsed = -1; + int rc = parsedate(p, &parsed); + (void)now; /* legacy argument from the past that we ignore */ + + switch(rc) { + case PARSEDATE_OK: + case PARSEDATE_LATER: + case PARSEDATE_SOONER: + return parsed; + } + /* everything else is fail */ + return -1; +} + +/* + * Curl_gmtime() is a gmtime() replacement for portability. Do not use the + * gmtime_r() or gmtime() functions anywhere else but here. + * + */ + +CURL_STATIC CURLcode Curl_gmtime(time_t intime, struct tm *store) +{ + const struct tm *tm; +#ifdef HAVE_GMTIME_R + /* thread-safe version */ + tm = (struct tm *)gmtime_r(&intime, store); +#else + tm = gmtime(&intime); + if(tm) + *store = *tm; /* copy the pointed struct to the local copy */ +#endif + + if(!tm) + return CURLE_BAD_FUNCTION_ARGUMENT; + return CURLE_OK; +} diff --git a/libcurl/src/lib/parsedate.h b/libcurl/src/lib/parsedate.h new file mode 100644 index 0000000..c845e55 --- /dev/null +++ b/libcurl/src/lib/parsedate.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_PARSEDATE_H +#define HEADER_CURL_PARSEDATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +//extern const char * const Curl_wkday[7]; +//extern const char * const Curl_month[12]; + +CURL_STATIC CURLcode Curl_gmtime(time_t intime, struct tm *store); + +#endif /* HEADER_CURL_PARSEDATE_H */ + diff --git a/libcurl/src/lib/pingpong.c b/libcurl/src/lib/pingpong.c new file mode 100644 index 0000000..d521319 --- /dev/null +++ b/libcurl/src/lib/pingpong.c @@ -0,0 +1,507 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * 'pingpong' is for generic back-and-forth support functions used by FTP, + * IMAP, POP3, SMTP and whatever more that likes them. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "progress.h" +#include "speedcheck.h" +#include "pingpong.h" +#include "multiif.h" +#include "non-ascii.h" +#include "vtls/vtls.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifdef USE_PINGPONG + +/* Returns timeout in ms. 0 or negative number means the timeout has already + triggered */ +CURL_STATIC long Curl_pp_state_timeout(struct pingpong *pp) +{ + struct connectdata *conn = pp->conn; + struct SessionHandle *data=conn->data; + long timeout_ms; /* in milliseconds */ + long timeout2_ms; /* in milliseconds */ + long response_time= (data->set.server_response_timeout)? + data->set.server_response_timeout: pp->response_time; + + /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine + remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is + supposed to govern the response for any given server response, not for + the time from connect to the given server response. */ + + /* Without a requested timeout, we only wait 'response_time' seconds for the + full response to arrive before we bail out */ + timeout_ms = response_time - + Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */ + + if(data->set.timeout) { + /* if timeout is requested, find out how much remaining time we have */ + timeout2_ms = data->set.timeout - /* timeout time */ + Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ + + /* pick the lowest number */ + timeout_ms = CURLMIN(timeout_ms, timeout2_ms); + } + + return timeout_ms; +} + +/* + * Curl_pp_statemach() + */ +CURL_STATIC CURLcode Curl_pp_statemach(struct pingpong *pp, bool block) +{ + struct connectdata *conn = pp->conn; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int rc; + long interval_ms; + long timeout_ms = Curl_pp_state_timeout(pp); + struct SessionHandle *data=conn->data; + CURLcode result = CURLE_OK; + + if(timeout_ms <=0 ) { + failf(data, "server response timeout"); + return CURLE_OPERATION_TIMEDOUT; /* already too little time */ + } + + if(block) { + interval_ms = 1000; /* use 1 second timeout intervals */ + if(timeout_ms < interval_ms) + interval_ms = timeout_ms; + } + else + interval_ms = 0; /* immediate */ + + if(Curl_pp_moredata(pp)) + /* We are receiving and there is data in the cache so just read it */ + rc = 1; + else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET)) + /* We are receiving and there is data ready in the SSL library */ + rc = 1; + else + rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ + pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ + interval_ms); + + if(block) { + /* if we didn't wait, we don't have to spend time on this now */ + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, Curl_tvnow()); + + if(result) + return result; + } + + if(rc == -1) { + failf(data, "select/poll error"); + result = CURLE_OUT_OF_MEMORY; + } + else if(rc) + result = pp->statemach_act(conn); + + return result; +} + +/* initialize stuff to prepare for reading a fresh new response */ +CURL_STATIC void Curl_pp_init(struct pingpong *pp) +{ + struct connectdata *conn = pp->conn; + pp->nread_resp = 0; + pp->linestart_resp = conn->data->state.buffer; + pp->pending_resp = TRUE; + pp->response = Curl_tvnow(); /* start response time-out now! */ +} + + + +/*********************************************************************** + * + * Curl_pp_vsendf() + * + * Send the formated string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURL_STATIC CURLcode Curl_pp_vsendf(struct pingpong *pp, + const char *fmt, + va_list args) +{ + ssize_t bytes_written; + size_t write_len; + char *fmt_crlf; + char *s; + CURLcode result; + struct connectdata *conn = pp->conn; + struct SessionHandle *data = conn->data; + +#ifdef HAVE_GSSAPI + enum protection_level data_sec = conn->data_prot; +#endif + + DEBUGASSERT(pp->sendleft == 0); + DEBUGASSERT(pp->sendsize == 0); + DEBUGASSERT(pp->sendthis == NULL); + + fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */ + if(!fmt_crlf) + return CURLE_OUT_OF_MEMORY; + + s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */ + free(fmt_crlf); + if(!s) + return CURLE_OUT_OF_MEMORY; + + bytes_written = 0; + write_len = strlen(s); + + Curl_pp_init(pp); + + result = Curl_convert_to_network(data, s, write_len); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) { + free(s); + return result; + } + +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CMD; +#endif + result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, + &bytes_written); +#ifdef HAVE_GSSAPI + DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); + conn->data_prot = data_sec; +#endif + + if(result) { + free(s); + return result; + } + + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, + s, (size_t)bytes_written, conn); + + if(bytes_written != (ssize_t)write_len) { + /* the whole chunk was not sent, keep it around and adjust sizes */ + pp->sendthis = s; + pp->sendsize = write_len; + pp->sendleft = write_len - bytes_written; + } + else { + free(s); + pp->sendthis = NULL; + pp->sendleft = pp->sendsize = 0; + pp->response = Curl_tvnow(); + } + + return CURLE_OK; +} + + +/*********************************************************************** + * + * Curl_pp_sendf() + * + * Send the formated string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURL_STATIC CURLcode Curl_pp_sendf(struct pingpong *pp, + const char *fmt, ...) +{ + CURLcode result; + va_list ap; + va_start(ap, fmt); + + result = Curl_pp_vsendf(pp, fmt, ap); + + va_end(ap); + + return result; +} + +/* + * Curl_pp_readresp() + * + * Reads a piece of a server response. + */ +CURLcode Curl_pp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *code, /* return the server code if done */ + size_t *size) /* size of the response */ +{ + ssize_t perline; /* count bytes per line */ + bool keepon=TRUE; + ssize_t gotbytes; + char *ptr; + struct connectdata *conn = pp->conn; + struct SessionHandle *data = conn->data; + char * const buf = data->state.buffer; + CURLcode result = CURLE_OK; + + *code = 0; /* 0 for errors or not done */ + *size = 0; + + ptr=buf + pp->nread_resp; + + /* number of bytes in the current line, so far */ + perline = (ssize_t)(ptr-pp->linestart_resp); + + while((pp->nread_respcache) { + /* we had data in the "cache", copy that instead of doing an actual + * read + * + * pp->cache_size is cast to ssize_t here. This should be safe, because + * it would have been populated with something of size int to begin + * with, even though its datatype may be larger than an int. + */ + DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1)); + memcpy(ptr, pp->cache, pp->cache_size); + gotbytes = (ssize_t)pp->cache_size; + free(pp->cache); /* free the cache */ + pp->cache = NULL; /* clear the pointer */ + pp->cache_size = 0; /* zero the size just in case */ + } + else { +#ifdef HAVE_GSSAPI + enum protection_level prot = conn->data_prot; + conn->data_prot = PROT_CLEAR; +#endif + DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1)); + result = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp, + &gotbytes); +#ifdef HAVE_GSSAPI + DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST); + conn->data_prot = prot; +#endif + if(result == CURLE_AGAIN) + return CURLE_OK; /* return */ + + if(!result && (gotbytes > 0)) + /* convert from the network encoding */ + result = Curl_convert_from_network(data, ptr, gotbytes); + /* Curl_convert_from_network calls failf if unsuccessful */ + + if(result) + /* Set outer result variable to this error. */ + keepon = FALSE; + } + + if(!keepon) + ; + else if(gotbytes <= 0) { + keepon = FALSE; + result = CURLE_RECV_ERROR; + failf(data, "response reading failed"); + } + else { + /* we got a whole chunk of data, which can be anything from one + * byte to a set of lines and possible just a piece of the last + * line */ + ssize_t i; + ssize_t clipamount = 0; + bool restart = FALSE; + + data->req.headerbytecount += (long)gotbytes; + + pp->nread_resp += gotbytes; + for(i = 0; i < gotbytes; ptr++, i++) { + perline++; + if(*ptr=='\n') { + /* a newline is CRLF in pp-talk, so the CR is ignored as + the line isn't really terminated until the LF comes */ + + /* output debug output if that is requested */ +#ifdef HAVE_GSSAPI + if(!conn->sec_complete) +#endif + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + pp->linestart_resp, (size_t)perline, conn); + + /* + * We pass all response-lines to the callback function registered + * for "headers". The response lines can be seen as a kind of + * headers. + */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + pp->linestart_resp, perline); + if(result) + return result; + + if(pp->endofresp(conn, pp->linestart_resp, perline, code)) { + /* This is the end of the last line, copy the last line to the + start of the buffer and zero terminate, for old times sake */ + size_t n = ptr - pp->linestart_resp; + memmove(buf, pp->linestart_resp, n); + buf[n]=0; /* zero terminate */ + keepon=FALSE; + pp->linestart_resp = ptr+1; /* advance pointer */ + i++; /* skip this before getting out */ + + *size = pp->nread_resp; /* size of the response */ + pp->nread_resp = 0; /* restart */ + break; + } + perline=0; /* line starts over here */ + pp->linestart_resp = ptr+1; + } + } + + if(!keepon && (i != gotbytes)) { + /* We found the end of the response lines, but we didn't parse the + full chunk of data we have read from the server. We therefore need + to store the rest of the data to be checked on the next invoke as + it may actually contain another end of response already! */ + clipamount = gotbytes - i; + restart = TRUE; + DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing " + "server response left\n", + (int)clipamount)); + } + else if(keepon) { + + if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) { + /* We got an excessive line without newlines and we need to deal + with it. We keep the first bytes of the line then we throw + away the rest. */ + infof(data, "Excessive server response line length received, " + "%zd bytes. Stripping\n", gotbytes); + restart = TRUE; + + /* we keep 40 bytes since all our pingpong protocols are only + interested in the first piece */ + clipamount = 40; + } + else if(pp->nread_resp > BUFSIZE/2) { + /* We got a large chunk of data and there's potentially still + trailing data to take care of, so we put any such part in the + "cache", clear the buffer to make space and restart. */ + clipamount = perline; + restart = TRUE; + } + } + else if(i == gotbytes) + restart = TRUE; + + if(clipamount) { + pp->cache_size = clipamount; + pp->cache = malloc(pp->cache_size); + if(pp->cache) + memcpy(pp->cache, pp->linestart_resp, pp->cache_size); + else + return CURLE_OUT_OF_MEMORY; + } + if(restart) { + /* now reset a few variables to start over nicely from the start of + the big buffer */ + pp->nread_resp = 0; /* start over from scratch in the buffer */ + ptr = pp->linestart_resp = buf; + perline = 0; + } + + } /* there was data */ + + } /* while there's buffer left and loop is requested */ + + pp->pending_resp = FALSE; + + return result; +} + +CURL_STATIC int Curl_pp_getsock(struct pingpong *pp, + curl_socket_t *socks, + int numsocks) +{ + struct connectdata *conn = pp->conn; + + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + + if(pp->sendleft) { + /* write mode */ + return GETSOCK_WRITESOCK(0); + } + + /* read mode */ + return GETSOCK_READSOCK(0); +} + +CURL_STATIC CURLcode Curl_pp_flushsend(struct pingpong *pp) +{ + /* we have a piece of a command still left to send */ + struct connectdata *conn = pp->conn; + ssize_t written; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize - + pp->sendleft, pp->sendleft, &written); + if(result) + return result; + + if(written != (ssize_t)pp->sendleft) { + /* only a fraction was sent */ + pp->sendleft -= written; + } + else { + free(pp->sendthis); + pp->sendthis=NULL; + pp->sendleft = pp->sendsize = 0; + pp->response = Curl_tvnow(); + } + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_pp_disconnect(struct pingpong *pp) +{ + free(pp->cache); + pp->cache = NULL; + return CURLE_OK; +} + +CURL_STATIC bool Curl_pp_moredata(struct pingpong *pp) +{ + return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ? + TRUE : FALSE; +} + +#endif diff --git a/libcurl/src/lib/pingpong.h b/libcurl/src/lib/pingpong.h new file mode 100644 index 0000000..6ee1fe7 --- /dev/null +++ b/libcurl/src/lib/pingpong.h @@ -0,0 +1,150 @@ +#ifndef HEADER_CURL_PINGPONG_H +#define HEADER_CURL_PINGPONG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \ + !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP) +#define USE_PINGPONG +#endif + +/* forward-declaration, this is defined in urldata.h */ +struct connectdata; + +typedef enum { + FTPTRANSFER_BODY, /* yes do transfer a body */ + FTPTRANSFER_INFO, /* do still go through to get info/headers */ + FTPTRANSFER_NONE, /* don't get anything and don't get info */ + FTPTRANSFER_LAST /* end of list marker, never used */ +} curl_pp_transfer; + +/* + * 'pingpong' is the generic struct used for protocols doing server<->client + * conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc. + * + * It holds response cache and non-blocking sending data. + */ +struct pingpong { + char *cache; /* data cache between getresponse()-calls */ + size_t cache_size; /* size of cache in bytes */ + size_t nread_resp; /* number of bytes currently read of a server response */ + char *linestart_resp; /* line start pointer for the server response + reader function */ + bool pending_resp; /* set TRUE when a server response is pending or in + progress, and is cleared once the last response is + read */ + char *sendthis; /* allocated pointer to a buffer that is to be sent to the + server */ + size_t sendleft; /* number of bytes left to send from the sendthis buffer */ + size_t sendsize; /* total size of the sendthis buffer */ + struct timeval response; /* set to Curl_tvnow() when a command has been sent + off, used to time-out response reading */ + long response_time; /* When no timeout is given, this is the amount of + milliseconds we await for a server response. */ + + struct connectdata *conn; /* points to the connectdata struct that this + belongs to */ + + /* Function pointers the protocols MUST implement and provide for the + pingpong layer to function */ + + CURLcode (*statemach_act)(struct connectdata *conn); + + bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len, + int *code); +}; + +/* + * Curl_pp_statemach() + * + * called repeatedly until done. Set 'wait' to make it wait a while on the + * socket if there's no traffic. + */ +CURL_STATIC CURLcode Curl_pp_statemach(struct pingpong *pp, bool block); + +/* initialize stuff to prepare for reading a fresh new response */ +CURL_STATIC void Curl_pp_init(struct pingpong *pp); + +/* Returns timeout in ms. 0 or negative number means the timeout has already + triggered */ +CURL_STATIC long Curl_pp_state_timeout(struct pingpong *pp); + + +/*********************************************************************** + * + * Curl_pp_sendf() + * + * Send the formated string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURL_STATIC CURLcode Curl_pp_sendf(struct pingpong *pp, + const char *fmt, ...); + +/*********************************************************************** + * + * Curl_pp_vsendf() + * + * Send the formated string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURL_STATIC CURLcode Curl_pp_vsendf(struct pingpong *pp, + const char *fmt, + va_list args); + +/* + * Curl_pp_readresp() + * + * Reads a piece of a server response. + */ +CURL_STATIC CURLcode Curl_pp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *code, /* return the server code if done */ + size_t *size); /* size of the response */ + + +CURL_STATIC CURLcode Curl_pp_flushsend(struct pingpong *pp); + +/* call this when a pingpong connection is disconnected */ +CURL_STATIC CURLcode Curl_pp_disconnect(struct pingpong *pp); + +CURL_STATIC int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks, + int numsocks); + + +/*********************************************************************** + * + * Curl_pp_moredata() + * + * Returns whether there are still more data in the cache and so a call + * to Curl_pp_readresp() will not block. + */ +CURL_STATIC bool Curl_pp_moredata(struct pingpong *pp); + +#endif /* HEADER_CURL_PINGPONG_H */ diff --git a/libcurl/src/lib/pipeline.c b/libcurl/src/lib/pipeline.c new file mode 100644 index 0000000..7af5484 --- /dev/null +++ b/libcurl/src/lib/pipeline.c @@ -0,0 +1,338 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013, Linus Nielsen Feltzing, + * Copyright (C) 2013-2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "multiif.h" +#include "pipeline.h" +#include "sendf.h" +#include "rawstr.h" +#include "bundles.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +struct site_blacklist_entry { + char *hostname; + unsigned short port; +}; + +static void site_blacklist_llist_dtor(void *user, void *element) +{ + struct site_blacklist_entry *entry = element; + (void)user; + + Curl_safefree(entry->hostname); + free(entry); +} + +static void server_blacklist_llist_dtor(void *user, void *element) +{ + (void)user; + free(element); +} + +CURL_STATIC bool Curl_pipeline_penalized(struct SessionHandle *data, + struct connectdata *conn) +{ + if(data) { + bool penalized = FALSE; + curl_off_t penalty_size = + Curl_multi_content_length_penalty_size(data->multi); + curl_off_t chunk_penalty_size = + Curl_multi_chunk_length_penalty_size(data->multi); + curl_off_t recv_size = -2; /* Make it easy to spot in the log */ + + /* Find the head of the recv pipe, if any */ + if(conn->recv_pipe && conn->recv_pipe->head) { + struct SessionHandle *recv_handle = conn->recv_pipe->head->ptr; + + recv_size = recv_handle->req.size; + + if(penalty_size > 0 && recv_size > penalty_size) + penalized = TRUE; + } + + if(chunk_penalty_size > 0 && + (curl_off_t)conn->chunk.datasize > chunk_penalty_size) + penalized = TRUE; + + infof(data, "Conn: %ld (%p) Receive pipe weight: (%" + CURL_FORMAT_CURL_OFF_T "/%zu), penalized: %s\n", + conn->connection_id, (void *)conn, recv_size, + conn->chunk.datasize, penalized?"TRUE":"FALSE"); + return penalized; + } + return FALSE; +} + +CURL_STATIC CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle, + struct connectdata *conn) +{ + struct curl_llist_element *sendhead = conn->send_pipe->head; + struct curl_llist *pipeline; + CURLcode result; + + pipeline = conn->send_pipe; + + result = Curl_addHandleToPipeline(handle, pipeline); + + if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) { + /* this is a new one as head, expire it */ + conn->writechannel_inuse = FALSE; /* not in use yet */ + Curl_expire(conn->send_pipe->head->ptr, 1); + } + +#if 0 /* enable for pipeline debugging */ + print_pipeline(conn); +#endif + + return result; +} + +/* Move this transfer from the sending list to the receiving list. + + Pay special attention to the new sending list "leader" as it needs to get + checked to update what sockets it acts on. + +*/ +CURL_STATIC void Curl_move_handle_from_send_to_recv_pipe(struct SessionHandle *handle, + struct connectdata *conn) +{ + struct curl_llist_element *curr; + + curr = conn->send_pipe->head; + while(curr) { + if(curr->ptr == handle) { + Curl_llist_move(conn->send_pipe, curr, + conn->recv_pipe, conn->recv_pipe->tail); + + if(conn->send_pipe->head) { + /* Since there's a new easy handle at the start of the send pipeline, + set its timeout value to 1ms to make it trigger instantly */ + conn->writechannel_inuse = FALSE; /* not used now */ +#ifdef DEBUGBUILD + infof(conn->data, "%p is at send pipe head B!\n", + (void *)conn->send_pipe->head->ptr); +#endif + Curl_expire(conn->send_pipe->head->ptr, 1); + } + + /* The receiver's list is not really interesting here since either this + handle is now first in the list and we'll deal with it soon, or + another handle is already first and thus is already taken care of */ + + break; /* we're done! */ + } + curr = curr->next; + } +} + +CURL_STATIC bool Curl_pipeline_site_blacklisted(struct SessionHandle *handle, + struct connectdata *conn) +{ + if(handle->multi) { + struct curl_llist *blacklist = + Curl_multi_pipelining_site_bl(handle->multi); + + if(blacklist) { + struct curl_llist_element *curr; + + curr = blacklist->head; + while(curr) { + struct site_blacklist_entry *site; + + site = curr->ptr; + if(Curl_raw_equal(site->hostname, conn->host.name) && + site->port == conn->remote_port) { + infof(handle, "Site %s:%d is pipeline blacklisted\n", + conn->host.name, conn->remote_port); + return TRUE; + } + curr = curr->next; + } + } + } + return FALSE; +} + +CURL_STATIC CURLMcode Curl_pipeline_set_site_blacklist(char **sites, + struct curl_llist **list_ptr) +{ + struct curl_llist *old_list = *list_ptr; + struct curl_llist *new_list = NULL; + + if(sites) { + new_list = Curl_llist_alloc((curl_llist_dtor) site_blacklist_llist_dtor); + if(!new_list) + return CURLM_OUT_OF_MEMORY; + + /* Parse the URLs and populate the list */ + while(*sites) { + char *hostname; + char *port; + struct site_blacklist_entry *entry; + + hostname = strdup(*sites); + if(!hostname) { + Curl_llist_destroy(new_list, NULL); + return CURLM_OUT_OF_MEMORY; + } + + entry = malloc(sizeof(struct site_blacklist_entry)); + if(!entry) { + free(hostname); + Curl_llist_destroy(new_list, NULL); + return CURLM_OUT_OF_MEMORY; + } + + port = strchr(hostname, ':'); + if(port) { + *port = '\0'; + port++; + entry->port = (unsigned short)strtol(port, NULL, 10); + } + else { + /* Default port number for HTTP */ + entry->port = 80; + } + + entry->hostname = hostname; + + if(!Curl_llist_insert_next(new_list, new_list->tail, entry)) { + site_blacklist_llist_dtor(NULL, entry); + Curl_llist_destroy(new_list, NULL); + return CURLM_OUT_OF_MEMORY; + } + + sites++; + } + } + + /* Free the old list */ + if(old_list) { + Curl_llist_destroy(old_list, NULL); + } + + /* This might be NULL if sites == NULL, i.e the blacklist is cleared */ + *list_ptr = new_list; + + return CURLM_OK; +} + +CURL_STATIC bool Curl_pipeline_server_blacklisted(struct SessionHandle *handle, + char *server_name) +{ + if(handle->multi && server_name) { + struct curl_llist *blacklist = + Curl_multi_pipelining_server_bl(handle->multi); + + if(blacklist) { + struct curl_llist_element *curr; + + curr = blacklist->head; + while(curr) { + char *bl_server_name; + + bl_server_name = curr->ptr; + if(Curl_raw_nequal(bl_server_name, server_name, + strlen(bl_server_name))) { + infof(handle, "Server %s is blacklisted\n", server_name); + return TRUE; + } + curr = curr->next; + } + } + + DEBUGF(infof(handle, "Server %s is not blacklisted\n", server_name)); + } + return FALSE; +} + +CURL_STATIC CURLMcode Curl_pipeline_set_server_blacklist(char **servers, + struct curl_llist **list_ptr) +{ + struct curl_llist *old_list = *list_ptr; + struct curl_llist *new_list = NULL; + + if(servers) { + new_list = Curl_llist_alloc((curl_llist_dtor) server_blacklist_llist_dtor); + if(!new_list) + return CURLM_OUT_OF_MEMORY; + + /* Parse the URLs and populate the list */ + while(*servers) { + char *server_name; + + server_name = strdup(*servers); + if(!server_name) + return CURLM_OUT_OF_MEMORY; + + if(!Curl_llist_insert_next(new_list, new_list->tail, server_name)) + return CURLM_OUT_OF_MEMORY; + + servers++; + } + } + + /* Free the old list */ + if(old_list) { + Curl_llist_destroy(old_list, NULL); + } + + /* This might be NULL if sites == NULL, i.e the blacklist is cleared */ + *list_ptr = new_list; + + return CURLM_OK; +} + +#if 0 +void print_pipeline(struct connectdata *conn) +{ + struct curl_llist_element *curr; + struct connectbundle *cb_ptr; + struct SessionHandle *data = conn->data; + + cb_ptr = conn->bundle; + + if(cb_ptr) { + curr = cb_ptr->conn_list->head; + while(curr) { + conn = curr->ptr; + infof(data, "- Conn %ld (%p) send_pipe: %zu, recv_pipe: %zu\n", + conn->connection_id, + (void *)conn, + conn->send_pipe->size, + conn->recv_pipe->size); + curr = curr->next; + } + } +} + +#endif diff --git a/libcurl/src/lib/pipeline.h b/libcurl/src/lib/pipeline.h new file mode 100644 index 0000000..a00db79 --- /dev/null +++ b/libcurl/src/lib/pipeline.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_PIPELINE_H +#define HEADER_CURL_PIPELINE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, + * + * 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. + * + ***************************************************************************/ + +CURL_STATIC CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle, + struct connectdata *conn); +CURL_STATIC void Curl_move_handle_from_send_to_recv_pipe(struct SessionHandle *handle, + struct connectdata *conn); +CURL_STATIC bool Curl_pipeline_penalized(struct SessionHandle *data, + struct connectdata *conn); + +CURL_STATIC bool Curl_pipeline_site_blacklisted(struct SessionHandle *handle, + struct connectdata *conn); + +CURL_STATIC CURLMcode Curl_pipeline_set_site_blacklist(char **sites, + struct curl_llist **list_ptr); + +CURL_STATIC bool Curl_pipeline_server_blacklisted(struct SessionHandle *handle, + char *server_name); + +CURL_STATIC CURLMcode Curl_pipeline_set_server_blacklist(char **servers, + struct curl_llist **list_ptr); + +#endif /* HEADER_CURL_PIPELINE_H */ diff --git a/libcurl/src/lib/pop3.c b/libcurl/src/lib/pop3.c new file mode 100644 index 0000000..d676b63 --- /dev/null +++ b/libcurl/src/lib/pop3.c @@ -0,0 +1,1601 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC1734 POP3 Authentication + * RFC1939 POP3 protocol + * RFC2195 CRAM-MD5 authentication + * RFC2384 POP URL Scheme + * RFC2449 POP3 Extension Mechanism + * RFC2595 Using TLS with IMAP, POP3 and ACAP + * RFC2831 DIGEST-MD5 authentication + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC5034 POP3 SASL Authentication Mechanism + * RFC6749 OAuth 2.0 Authorization Framework + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_POP3 + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "pop3.h" + +#include "strtoofft.h" +#include "strequal.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "rawstr.h" +#include "curl_sasl.h" +#include "curl_md5.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* Local API functions */ +static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode pop3_do(struct connectdata *conn, bool *done); +static CURLcode pop3_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode pop3_connect(struct connectdata *conn, bool *done); +static CURLcode pop3_disconnect(struct connectdata *conn, bool dead); +static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done); +static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode pop3_setup_connection(struct connectdata *conn); +static CURLcode pop3_parse_url_options(struct connectdata *conn); +static CURLcode pop3_parse_url_path(struct connectdata *conn); +static CURLcode pop3_parse_custom_request(struct connectdata *conn); +static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, + const char *initresp); +static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp); +static void pop3_get_message(char *buffer, char** outptr); + +/* + * POP3 protocol handler. + */ + +const struct Curl_handler Curl_handler_pop3 = { + "POP3", /* scheme */ + pop3_setup_connection, /* setup_connection */ + pop3_do, /* do_it */ + pop3_done, /* done */ + ZERO_NULL, /* do_more */ + pop3_connect, /* connect_it */ + pop3_multi_statemach, /* connecting */ + pop3_doing, /* doing */ + pop3_getsock, /* proto_getsock */ + pop3_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + pop3_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_POP3, /* defport */ + CURLPROTO_POP3, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */ +}; + +#ifdef USE_SSL +/* + * POP3S protocol handler. + */ + +const struct Curl_handler Curl_handler_pop3s = { + "POP3S", /* scheme */ + pop3_setup_connection, /* setup_connection */ + pop3_do, /* do_it */ + pop3_done, /* done */ + ZERO_NULL, /* do_more */ + pop3_connect, /* connect_it */ + pop3_multi_statemach, /* connecting */ + pop3_doing, /* doing */ + pop3_getsock, /* proto_getsock */ + pop3_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + pop3_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_POP3S, /* defport */ + CURLPROTO_POP3S, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL + | PROTOPT_NOURLQUERY /* flags */ +}; +#endif + +#ifndef CURL_DISABLE_HTTP +/* + * HTTP-proxyed POP3 protocol handler. + */ + +static const struct Curl_handler Curl_handler_pop3_proxy = { + "POP3", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_POP3, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * HTTP-proxyed POP3S protocol handler. + */ + +static const struct Curl_handler Curl_handler_pop3s_proxy = { + "POP3S", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_POP3S, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; +#endif +#endif + +/* SASL parameters for the pop3 protocol */ +static const struct SASLproto saslpop3 = { + "pop", /* The service name */ + '+', /* Code received when continuation is expected */ + '+', /* Code to receive upon authentication success */ + 255 - 8, /* Maximum initial response length (no max) */ + pop3_perform_auth, /* Send authentication command */ + pop3_continue_auth, /* Send authentication continuation */ + pop3_get_message /* Get SASL response message */ +}; + +#ifdef USE_SSL +static void pop3_to_pop3s(struct connectdata *conn) +{ + conn->handler = &Curl_handler_pop3s; +} +#else +#define pop3_to_pop3s(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * pop3_endofresp() + * + * Checks for an ending POP3 status code at the start of the given string, but + * also detects the APOP timestamp from the server greeting and various + * capabilities from the CAPA response including the supported authentication + * types and allowed SASL mechanisms. + */ +static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* Do we have an error response? */ + if(len >= 4 && !memcmp("-ERR", line, 4)) { + *resp = '-'; + + return TRUE; + } + + /* Are we processing CAPA command responses? */ + if(pop3c->state == POP3_CAPA) { + /* Do we have the terminating line? */ + if(len >= 1 && !memcmp(line, ".", 1)) + *resp = '+'; + else + *resp = '*'; + + return TRUE; + } + + /* Do we have a command or continuation response? */ + if((len >= 3 && !memcmp("+OK", line, 3)) || + (len >= 1 && !memcmp("+", line, 1))) { + *resp = '+'; + + return TRUE; + } + + return FALSE; /* Nothing for us */ +} + +/*********************************************************************** + * + * pop3_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void pop3_get_message(char *buffer, char** outptr) +{ + size_t len = 0; + char* message = NULL; + + /* Find the start of the message */ + for(message = buffer + 2; *message == ' ' || *message == '\t'; message++) + ; + + /* Find the end of the message */ + for(len = strlen(message); len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change POP3 state! + */ +static void state(struct connectdata *conn, pop3state newstate) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "STOP", + "SERVERGREET", + "CAPA", + "STARTTLS", + "UPGRADETLS", + "AUTH", + "APOP", + "USER", + "PASS", + "COMMAND", + "QUIT", + /* LAST */ + }; + + if(pop3c->state != newstate) + infof(conn->data, "POP3 %p state change from %s to %s\n", + (void *)pop3c, names[pop3c->state], names[newstate]); +#endif + + pop3c->state = newstate; +} + +/*********************************************************************** + * + * pop3_perform_capa() + * + * Sends the CAPA command in order to obtain a list of server side supported + * capabilities. + */ +static CURLcode pop3_perform_capa(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + pop3c->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */ + pop3c->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */ + pop3c->tls_supported = FALSE; /* Clear the TLS capability */ + + /* Send the CAPA command */ + result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA"); + + if(!result) + state(conn, POP3_CAPA); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_starttls() + * + * Sends the STLS command to start the upgrade to TLS. + */ +static CURLcode pop3_perform_starttls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the STLS command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS"); + + if(!result) + state(conn, POP3_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* Start the SSL connection */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone); + + if(!result) { + if(pop3c->state != POP3_UPGRADETLS) + state(conn, POP3_UPGRADETLS); + + if(pop3c->ssldone) { + pop3_to_pop3s(conn); + result = pop3_perform_capa(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * pop3_perform_user() + * + * Sends a clear text USER command to authenticate with. + */ +static CURLcode pop3_perform_user(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, POP3_STOP); + + return result; + } + + /* Send the USER command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s", + conn->user ? conn->user : ""); + if(!result) + state(conn, POP3_USER); + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +/*********************************************************************** + * + * pop3_perform_apop() + * + * Sends an APOP command to authenticate with. + */ +static CURLcode pop3_perform_apop(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + size_t i; + MD5_context *ctxt; + unsigned char digest[MD5_DIGEST_LEN]; + char secret[2 * MD5_DIGEST_LEN + 1]; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, POP3_STOP); + + return result; + } + + /* Create the digest */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp, + curlx_uztoui(strlen(pop3c->apoptimestamp))); + + Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd, + curlx_uztoui(strlen(conn->passwd))); + + /* Finalise the digest */ + Curl_MD5_final(ctxt, digest); + + /* Convert the calculated 16 octet digest into a 32 byte hex string */ + for(i = 0; i < MD5_DIGEST_LEN; i++) + snprintf(&secret[2 * i], 3, "%02x", digest[i]); + + result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret); + + if(!result) + state(conn, POP3_APOP); + + return result; +} +#endif + +/*********************************************************************** + * + * pop3_perform_auth() + * + * Sends an AUTH command allowing the client to login with the given SASL + * authentication mechanism. + */ +static CURLcode pop3_perform_auth(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + if(initresp) { /* AUTH ... */ + /* Send the AUTH command with the initial response */ + result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp); + } + else { + /* Send the AUTH command */ + result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * pop3_continue_auth() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode pop3_continue_auth(struct connectdata *conn, + const char *resp) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + return Curl_pp_sendf(&pop3c->pp, "%s", resp); +} + +/*********************************************************************** + * + * pop3_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism, falling back to APOP and clear text should a + * common mechanism not be available between the client and server. + */ +static CURLcode pop3_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + saslprogress progress = SASL_IDLE; + + /* Check we have enough data to authenticate with and end the + connect phase if we don't */ + if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) { + state(conn, POP3_STOP); + return result; + } + + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) { + /* Calculate the SASL login details */ + result = Curl_sasl_start(&pop3c->sasl, conn, FALSE, &progress); + + if(!result) + if(progress == SASL_INPROGRESS) + state(conn, POP3_AUTH); + } + + if(!result && progress == SASL_IDLE) { +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) + /* Perform APOP authentication */ + result = pop3_perform_apop(conn); + else +#endif + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) + /* Perform clear text authentication */ + result = pop3_perform_user(conn); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * pop3_perform_command() + * + * Sends a POP3 based command. + */ +static CURLcode pop3_perform_command(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *command = NULL; + + /* Calculate the default command */ + if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) { + command = "LIST"; + + if(pop3->id[0] != '\0') + /* Message specific LIST so skip the BODY transfer */ + pop3->transfer = FTPTRANSFER_INFO; + } + else + command = "RETR"; + + /* Send the command */ + if(pop3->id[0] != '\0') + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s", + (pop3->custom && pop3->custom[0] != '\0' ? + pop3->custom : command), pop3->id); + else + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", + (pop3->custom && pop3->custom[0] != '\0' ? + pop3->custom : command)); + + if(!result) + state(conn, POP3_COMMAND); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_quit() + * + * Performs the quit action prior to sclose() be called. + */ +static CURLcode pop3_perform_quit(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the QUIT command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT"); + + if(!result) + state(conn, POP3_QUIT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode pop3_state_servergreet_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *line = data->state.buffer; + size_t len = strlen(line); + size_t i; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Got unexpected pop3-server response"); + result = CURLE_FTP_WEIRD_SERVER_REPLY; + } + else { + /* Does the server support APOP authentication? */ + if(len >= 4 && line[len - 2] == '>') { + /* Look for the APOP timestamp */ + for(i = 3; i < len - 2; ++i) { + if(line[i] == '<') { + /* Calculate the length of the timestamp */ + size_t timestamplen = len - 1 - i; + if(!timestamplen) + break; + + /* Allocate some memory for the timestamp */ + pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1); + + if(!pop3c->apoptimestamp) + break; + + /* Copy the timestamp */ + memcpy(pop3c->apoptimestamp, line + i, timestamplen); + pop3c->apoptimestamp[timestamplen] = '\0'; + + /* Store the APOP capability */ + pop3c->authtypes |= POP3_TYPE_APOP; + break; + } + } + } + + result = pop3_perform_capa(conn); + } + + return result; +} + +/* For CAPA responses */ +static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *line = data->state.buffer; + size_t len = strlen(line); + size_t wordlen; + + (void)instate; /* no use for this yet */ + + /* Do we have a untagged response? */ + if(pop3code == '*') { + /* Does the server support the STLS capability? */ + if(len >= 4 && !memcmp(line, "STLS", 4)) + pop3c->tls_supported = TRUE; + + /* Does the server support clear text authentication? */ + else if(len >= 4 && !memcmp(line, "USER", 4)) + pop3c->authtypes |= POP3_TYPE_CLEARTEXT; + + /* Does the server support SASL based authentication? */ + else if(len >= 5 && !memcmp(line, "SASL ", 5)) { + pop3c->authtypes |= POP3_TYPE_SASL; + + /* Advance past the SASL keyword */ + line += 5; + len -= 5; + + /* Loop through the data line */ + for(;;) { + size_t llen; + unsigned int mechbit; + + while(len && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + len--; + } + + if(!len) + break; + + /* Extract the word */ + for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Test the word for a matching authentication mechanism */ + if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) && + llen == wordlen) + pop3c->sasl.authmechs |= mechbit; + + line += wordlen; + len -= wordlen; + } + } + } + else if(pop3code == '+') { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(pop3c->tls_supported) + /* Switch to TLS connection now */ + result = pop3_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = pop3_perform_authentication(conn); + else { + failf(data, "STLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = pop3_perform_authentication(conn); + } + else { + /* Clear text is supported when CAPA isn't recognised */ + pop3c->authtypes |= POP3_TYPE_CLEARTEXT; + + result = pop3_perform_authentication(conn); + } + + return result; +} + +/* For STARTTLS responses */ +static CURLcode pop3_state_starttls_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied. %c", pop3code); + result = CURLE_USE_SSL_FAILED; + } + else + result = pop3_perform_authentication(conn); + } + else + result = pop3_perform_upgrade_tls(conn); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode pop3_state_auth_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&pop3c->sasl, conn, pop3code, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, POP3_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) + /* Perform APOP authentication */ + result = pop3_perform_apop(conn); + else +#endif + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) + /* Perform clear text authentication */ + result = pop3_perform_user(conn); + else { + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + } + break; + default: + break; + } + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +/* For APOP responses */ +static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Authentication failed: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, POP3_STOP); + + return result; +} +#endif + +/* For USER responses */ +static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied. %c", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* Send the PASS command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s", + conn->passwd ? conn->passwd : ""); + if(!result) + state(conn, POP3_PASS); + + return result; +} + +/* For PASS responses */ +static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied. %c", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, POP3_STOP); + + return result; +} + +/* For command responses */ +static CURLcode pop3_state_command_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct POP3 *pop3 = data->req.protop; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + state(conn, POP3_STOP); + return CURLE_RECV_ERROR; + } + + /* This 'OK' line ends with a CR LF pair which is the two first bytes of the + EOB string so count this is two matching bytes. This is necessary to make + the code detect the EOB if the only data than comes now is %2e CR LF like + when there is no body to return. */ + pop3c->eob = 2; + + /* But since this initial CR LF pair is not part of the actual body, we set + the strip counter here so that these bytes won't be delivered. */ + pop3c->strip = 2; + + if(pop3->transfer == FTPTRANSFER_BODY) { + /* POP3 download */ + Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + + if(pp->cache) { + /* The header "cache" contains a bunch of data that is actually body + content so send it as such. Note that there may even be additional + "headers" after the body */ + + if(!data->set.opt_no_body) { + result = Curl_pop3_write(conn, pp->cache, pp->cache_size); + if(result) + return result; + } + + /* Free the cache */ + Curl_safefree(pp->cache); + + /* Reset the cache size */ + pp->cache_size = 0; + } + } + + /* End of DO phase */ + state(conn, POP3_STOP); + + return result; +} + +static CURLcode pop3_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int pop3code; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */ + if(pop3c->state == POP3_UPGRADETLS) + return pop3_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &pop3code, &nread); + if(result) + return result; + + if(!pop3code) + break; + + /* We have now received a full POP3 server response */ + switch(pop3c->state) { + case POP3_SERVERGREET: + result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state); + break; + + case POP3_CAPA: + result = pop3_state_capa_resp(conn, pop3code, pop3c->state); + break; + + case POP3_STARTTLS: + result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH: + result = pop3_state_auth_resp(conn, pop3code, pop3c->state); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case POP3_APOP: + result = pop3_state_apop_resp(conn, pop3code, pop3c->state); + break; +#endif + + case POP3_USER: + result = pop3_state_user_resp(conn, pop3code, pop3c->state); + break; + + case POP3_PASS: + result = pop3_state_pass_resp(conn, pop3code, pop3c->state); + break; + + case POP3_COMMAND: + result = pop3_state_command_resp(conn, pop3code, pop3c->state); + break; + + case POP3_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, POP3_STOP); + break; + } + } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone); + if(result || !pop3c->ssldone) + return result; + } + + result = Curl_pp_statemach(&pop3c->pp, FALSE); + *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode pop3_block_statemach(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + while(pop3c->state != POP3_STOP && !result) + result = Curl_pp_statemach(&pop3c->pp, TRUE); + + return result; +} + +/* Allocate and initialize the POP3 struct for the current SessionHandle if + required */ +static CURLcode pop3_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct POP3 *pop3; + + pop3 = data->req.protop = calloc(sizeof(struct POP3), 1); + if(!pop3) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the POP3 "protocol connect" and "doing" phases only */ +static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.pop3c.pp, socks, numsocks); +} + +/*********************************************************************** + * + * pop3_connect() + * + * This function should do everything that is to be considered a part of the + * connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + */ +static CURLcode pop3_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in POP3 */ + connkeep(conn, "POP3 default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = pop3_statemach_act; + pp->endofresp = pop3_endofresp; + pp->conn = conn; + + /* Set the default preferred authentication type and mechanism */ + pop3c->preftype = POP3_TYPE_ANY; + Curl_sasl_init(&pop3c->sasl, &saslpop3); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = pop3_parse_url_options(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, POP3_SERVERGREET); + + result = pop3_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * pop3_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode pop3_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct POP3 *pop3 = data->req.protop; + + (void)premature; + + if(!pop3) + /* When the easy handle is removed from the multi interface while libcurl + is still trying to resolve the host name, the POP3 struct is not yet + initialized. However, the removal action calls Curl_done() which in + turn calls this function, so we simply return success. */ + return CURLE_OK; + + if(status) { + connclose(conn, "POP3 done with bad status"); + result = status; /* use the already set error code */ + } + + /* Cleanup our per-request based variables */ + Curl_safefree(pop3->id); + Curl_safefree(pop3->custom); + + /* Clear the transfer mode for the next request */ + pop3->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * pop3_perform() + * + * This is the actual DO function for POP3. Get a message/listing according to + * the options previously setup. + */ +static CURLcode pop3_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is POP3 and no proxy */ + CURLcode result = CURLE_OK; + struct POP3 *pop3 = conn->data->req.protop; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* Requested no body means no transfer */ + pop3->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Start the first command in the DO phase */ + result = pop3_perform_command(conn); + if(result) + return result; + + /* Run the state-machine */ + result = pop3_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * pop3_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (pop3_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode pop3_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the URL path */ + result = pop3_parse_url_path(conn); + if(result) + return result; + + /* Parse the custom request */ + result = pop3_parse_custom_request(conn); + if(result) + return result; + + result = pop3_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * pop3_disconnect() + * + * Disconnect from an POP3 server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The POP3 session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart) + if(!pop3_perform_quit(conn)) + (void)pop3_block_statemach(conn); /* ignore errors on QUIT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&pop3c->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, pop3c->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(pop3c->apoptimestamp); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected) +{ + (void)conn; + (void)connected; + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = pop3_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = pop3_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * pop3_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode pop3_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct SessionHandle *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = pop3_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = pop3_dophase_done(conn, connected); + + return result; +} + +static CURLcode pop3_setup_connection(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + + /* Initialise the POP3 layer */ + CURLcode result = pop3_init(conn); + if(result) + return result; + + if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { + /* Unless we have asked to tunnel POP3 operations through the proxy, we + switch and use HTTP operations only */ +#ifndef CURL_DISABLE_HTTP + if(conn->handler == &Curl_handler_pop3) + conn->handler = &Curl_handler_pop3_proxy; + else { +#ifdef USE_SSL + conn->handler = &Curl_handler_pop3s_proxy; +#else + failf(data, "POP3S not supported!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + + /* set it up as an HTTP connection instead */ + return conn->handler->setup_connection(conn); +#else + failf(data, "POP3 over http proxy requires HTTP support built-in!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + + data->state.path++; /* don't include the initial slash */ + + return CURLE_OK; +} + +/*********************************************************************** + * + * pop3_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode pop3_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *ptr = conn->options; + + pop3c->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strnequal(key, "AUTH=", 5)) { + result = Curl_sasl_parse_url_auth_option(&pop3c->sasl, + value, ptr - value); + + if(result && strnequal(value, "+APOP", ptr - value)) { + pop3c->preftype = POP3_TYPE_APOP; + pop3c->sasl.prefmech = SASL_AUTH_NONE; + result = CURLE_OK; + } + } + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + if(pop3c->preftype != POP3_TYPE_APOP) + switch(pop3c->sasl.prefmech) { + case SASL_AUTH_NONE: + pop3c->preftype = POP3_TYPE_NONE; + break; + case SASL_AUTH_DEFAULT: + pop3c->preftype = POP3_TYPE_ANY; + break; + default: + pop3c->preftype = POP3_TYPE_SASL; + break; + } + + return result; +} + +/*********************************************************************** + * + * pop3_parse_url_path() + * + * Parse the URL path into separate path components. + */ +static CURLcode pop3_parse_url_path(struct connectdata *conn) +{ + /* The POP3 struct is already initialised in pop3_connect() */ + struct SessionHandle *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *path = data->state.path; + + /* URL decode the path for the message ID */ + return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE); +} + +/*********************************************************************** + * + * pop3_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode pop3_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + /* URL decode the custom request */ + if(custom) + result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE); + + return result; +} + +/*********************************************************************** + * + * Curl_pop3_write() + * + * This function scans the body after the end-of-body and writes everything + * until the end is found. + */ +CURL_STATIC CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) +{ + /* This code could be made into a special function in the handler struct */ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SingleRequest *k = &data->req; + + struct pop3_conn *pop3c = &conn->proto.pop3c; + bool strip_dot = FALSE; + size_t last = 0; + size_t i; + + /* Search through the buffer looking for the end-of-body marker which is + 5 bytes (0d 0a 2e 0d 0a). Note that a line starting with a dot matches + the eob so the server will have prefixed it with an extra dot which we + need to strip out. Additionally the marker could of course be spread out + over 5 different data chunks. */ + for(i = 0; i < nread; i++) { + size_t prev = pop3c->eob; + + switch(str[i]) { + case 0x0d: + if(pop3c->eob == 0) { + pop3c->eob++; + + if(i) { + /* Write out the body part that didn't match */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], + i - last); + + if(result) + return result; + + last = i; + } + } + else if(pop3c->eob == 3) + pop3c->eob++; + else + /* If the character match wasn't at position 0 or 3 then restart the + pattern matching */ + pop3c->eob = 1; + break; + + case 0x0a: + if(pop3c->eob == 1 || pop3c->eob == 4) + pop3c->eob++; + else + /* If the character match wasn't at position 1 or 4 then start the + search again */ + pop3c->eob = 0; + break; + + case 0x2e: + if(pop3c->eob == 2) + pop3c->eob++; + else if(pop3c->eob == 3) { + /* We have an extra dot after the CRLF which we need to strip off */ + strip_dot = TRUE; + pop3c->eob = 0; + } + else + /* If the character match wasn't at position 2 then start the search + again */ + pop3c->eob = 0; + break; + + default: + pop3c->eob = 0; + break; + } + + /* Did we have a partial match which has subsequently failed? */ + if(prev && prev >= pop3c->eob) { + /* Strip can only be non-zero for the very first mismatch after CRLF + and then both prev and strip are equal and nothing will be output + below */ + while(prev && pop3c->strip) { + prev--; + pop3c->strip--; + } + + if(prev) { + /* If the partial match was the CRLF and dot then only write the CRLF + as the server would have inserted the dot */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB, + strip_dot ? prev - 1 : prev); + + if(result) + return result; + + last = i; + strip_dot = FALSE; + } + } + } + + if(pop3c->eob == POP3_EOB_LEN) { + /* We have a full match so the transfer is done, however we must transfer + the CRLF at the start of the EOB as this is considered to be part of the + message as per RFC-1939, sect. 3 */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2); + + k->keepon &= ~KEEP_RECV; + pop3c->eob = 0; + + return result; + } + + if(pop3c->eob) + /* While EOB is matching nothing should be output */ + return CURLE_OK; + + if(nread - last) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], + nread - last); + } + + return result; +} + +#endif /* CURL_DISABLE_POP3 */ diff --git a/libcurl/src/lib/pop3.h b/libcurl/src/lib/pop3.h new file mode 100644 index 0000000..3e65d74 --- /dev/null +++ b/libcurl/src/lib/pop3.h @@ -0,0 +1,95 @@ +#ifndef HEADER_CURL_POP3_H +#define HEADER_CURL_POP3_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * POP3 unique setup + ***************************************************************************/ +typedef enum { + POP3_STOP, /* do nothing state, stops the state machine */ + POP3_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + POP3_CAPA, + POP3_STARTTLS, + POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + POP3_AUTH, + POP3_APOP, + POP3_USER, + POP3_PASS, + POP3_COMMAND, + POP3_QUIT, + POP3_LAST /* never used */ +} pop3state; + +/* This POP3 struct is used in the SessionHandle. All POP3 data that is + connection-oriented must be in pop3_conn to properly deal with the fact that + perhaps the SessionHandle is changed between the times the connection is + used. */ +struct POP3 { + curl_pp_transfer transfer; + char *id; /* Message ID */ + char *custom; /* Custom Request */ +}; + +/* pop3_conn is used for struct connection-oriented data in the connectdata + struct */ +struct pop3_conn { + struct pingpong pp; + pop3state state; /* Always use pop3.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + size_t eob; /* Number of bytes of the EOB (End Of Body) that + have been received so far */ + size_t strip; /* Number of bytes from the start to ignore as + non-body */ + struct SASL sasl; /* SASL-related storage */ + unsigned int authtypes; /* Accepted authentication types */ + unsigned int preftype; /* Preferred authentication type */ + char *apoptimestamp; /* APOP timestamp from the server greeting */ + bool tls_supported; /* StartTLS capability supported by server */ +}; + +extern const struct Curl_handler Curl_handler_pop3; +extern const struct Curl_handler Curl_handler_pop3s; + +/* Authentication type flags */ +#define POP3_TYPE_CLEARTEXT (1 << 0) +#define POP3_TYPE_APOP (1 << 1) +#define POP3_TYPE_SASL (1 << 2) + +/* Authentication type values */ +#define POP3_TYPE_NONE 0 +#define POP3_TYPE_ANY ~0U + +/* This is the 5-bytes End-Of-Body marker for POP3 */ +#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" +#define POP3_EOB_LEN 5 + +/* This function scans the body after the end-of-body and writes everything + * until the end is found */ +CURL_STATIC CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread); + +#endif /* HEADER_CURL_POP3_H */ diff --git a/libcurl/src/lib/progress.c b/libcurl/src/lib/progress.c new file mode 100644 index 0000000..d126237 --- /dev/null +++ b/libcurl/src/lib/progress.c @@ -0,0 +1,492 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "sendf.h" +#include "progress.h" +#include "curl_printf.h" + +/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero + byte) */ +static void time2str(char *r, curl_off_t seconds) +{ + curl_off_t d, h, m, s; + if(seconds <= 0) { + strcpy(r, "--:--:--"); + return; + } + h = seconds / CURL_OFF_T_C(3600); + if(h <= CURL_OFF_T_C(99)) { + m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60); + s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60)); + snprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T + ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s); + } + else { + /* this equals to more than 99 hours, switch to a more suitable output + format to fit within the limits. */ + d = seconds / CURL_OFF_T_C(86400); + h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600); + if(d <= CURL_OFF_T_C(999)) + snprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T + "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h); + else + snprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d); + } +} + +/* The point of this function would be to return a string of the input data, + but never longer than 5 columns (+ one zero byte). + Add suffix k, M, G when suitable... */ +static char *max5data(curl_off_t bytes, char *max5) +{ +#define ONE_KILOBYTE CURL_OFF_T_C(1024) +#define ONE_MEGABYTE (CURL_OFF_T_C(1024) * ONE_KILOBYTE) +#define ONE_GIGABYTE (CURL_OFF_T_C(1024) * ONE_MEGABYTE) +#define ONE_TERABYTE (CURL_OFF_T_C(1024) * ONE_GIGABYTE) +#define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE) + + if(bytes < CURL_OFF_T_C(100000)) + snprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE) + snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE); + + else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE) + /* 'XX.XM' is good as long as we're less than 100 megs */ + snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0" + CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE, + (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) ); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) + + else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE) + /* 'XXXXM' is good until we're at 10000MB or above */ + snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE); + + else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE) + /* 10000 MB - 100 GB, we show it as XX.XG */ + snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0" + CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE, + (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) ); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE) + /* up to 10000GB, display without decimal: XXXXG */ + snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE) + /* up to 10000TB, display without decimal: XXXXT */ + snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE); + + else + /* up to 10000PB, display without decimal: XXXXP */ + snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE); + + /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number + can hold, but our data type is signed so 8192PB will be the maximum. */ + +#else + + else + snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE); + +#endif + + return max5; +} + +/* + + New proposed interface, 9th of February 2000: + + pgrsStartNow() - sets start time + pgrsSetDownloadSize(x) - known expected download size + pgrsSetUploadSize(x) - known expected upload size + pgrsSetDownloadCounter() - amount of data currently downloaded + pgrsSetUploadCounter() - amount of data currently uploaded + pgrsUpdate() - show progress + pgrsDone() - transfer complete + +*/ + +CURL_STATIC int Curl_pgrsDone(struct connectdata *conn) +{ + int rc; + struct SessionHandle *data = conn->data; + data->progress.lastshow=0; + rc = Curl_pgrsUpdate(conn); /* the final (forced) update */ + if(rc) + return rc; + + if(!(data->progress.flags & PGRS_HIDE) && + !data->progress.callback) + /* only output if we don't use a progress callback and we're not + * hidden */ + fprintf(data->set.err, "\n"); + + data->progress.speeder_c = 0; /* reset the progress meter display */ + return 0; +} + +/* reset all times except redirect, and reset the known transfer sizes */ +CURL_STATIC void Curl_pgrsResetTimesSizes(struct SessionHandle *data) +{ + data->progress.t_nslookup = 0.0; + data->progress.t_connect = 0.0; + data->progress.t_pretransfer = 0.0; + data->progress.t_starttransfer = 0.0; + + Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsSetUploadSize(data, -1); +} + +CURL_STATIC void Curl_pgrsTime(struct SessionHandle *data, timerid timer) +{ + struct timeval now = Curl_tvnow(); + + switch(timer) { + default: + case TIMER_NONE: + /* mistake filter */ + break; + case TIMER_STARTOP: + /* This is set at the start of a transfer */ + data->progress.t_startop = now; + break; + case TIMER_STARTSINGLE: + /* This is set at the start of each single fetch */ + data->progress.t_startsingle = now; + break; + + case TIMER_STARTACCEPT: + data->progress.t_acceptdata = Curl_tvnow(); + break; + + case TIMER_NAMELOOKUP: + data->progress.t_nslookup = + Curl_tvdiff_secs(now, data->progress.t_startsingle); + break; + case TIMER_CONNECT: + data->progress.t_connect = + Curl_tvdiff_secs(now, data->progress.t_startsingle); + break; + case TIMER_APPCONNECT: + data->progress.t_appconnect = + Curl_tvdiff_secs(now, data->progress.t_startsingle); + break; + case TIMER_PRETRANSFER: + data->progress.t_pretransfer = + Curl_tvdiff_secs(now, data->progress.t_startsingle); + break; + case TIMER_STARTTRANSFER: + data->progress.t_starttransfer = + Curl_tvdiff_secs(now, data->progress.t_startsingle); + break; + case TIMER_POSTRANSFER: + /* this is the normal end-of-transfer thing */ + break; + case TIMER_REDIRECT: + data->progress.t_redirect = Curl_tvdiff_secs(now, data->progress.start); + break; + } +} + +CURL_STATIC void Curl_pgrsStartNow(struct SessionHandle *data) +{ + data->progress.speeder_c = 0; /* reset the progress meter display */ + data->progress.start = Curl_tvnow(); + /* clear all bits except HIDE and HEADERS_OUT */ + data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT; +} + +CURL_STATIC void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size) +{ + data->progress.downloaded = size; +} + +CURL_STATIC void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size) +{ + data->progress.uploaded = size; +} + +CURL_STATIC void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size) +{ + if(size >= 0) { + data->progress.size_dl = size; + data->progress.flags |= PGRS_DL_SIZE_KNOWN; + } + else { + data->progress.size_dl = 0; + data->progress.flags &= ~PGRS_DL_SIZE_KNOWN; + } +} + +CURL_STATIC void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size) +{ + if(size >= 0) { + data->progress.size_ul = size; + data->progress.flags |= PGRS_UL_SIZE_KNOWN; + } + else { + data->progress.size_ul = 0; + data->progress.flags &= ~PGRS_UL_SIZE_KNOWN; + } +} + +/* + * Curl_pgrsUpdate() returns 0 for success or the value returned by the + * progress callback! + */ +CURL_STATIC int Curl_pgrsUpdate(struct connectdata *conn) +{ + struct timeval now; + int result; + char max5[6][10]; + curl_off_t dlpercen=0; + curl_off_t ulpercen=0; + curl_off_t total_percen=0; + curl_off_t total_transfer; + curl_off_t total_expected_transfer; + curl_off_t timespent; + struct SessionHandle *data = conn->data; + int nowindex = data->progress.speeder_c% CURR_TIME; + int checkindex; + int countindex; /* amount of seconds stored in the speeder array */ + char time_left[10]; + char time_total[10]; + char time_spent[10]; + curl_off_t ulestimate=0; + curl_off_t dlestimate=0; + curl_off_t total_estimate; + bool shownow=FALSE; + + now = Curl_tvnow(); /* what time is it */ + + /* The time spent so far (from the start) */ + data->progress.timespent = + (double)(now.tv_sec - data->progress.start.tv_sec) + + (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0; + timespent = (curl_off_t)data->progress.timespent; + + /* The average download speed this far */ + data->progress.dlspeed = (curl_off_t) + ((double)data->progress.downloaded/ + (data->progress.timespent>0?data->progress.timespent:1)); + + /* The average upload speed this far */ + data->progress.ulspeed = (curl_off_t) + ((double)data->progress.uploaded/ + (data->progress.timespent>0?data->progress.timespent:1)); + + /* Calculations done at most once a second, unless end is reached */ + if(data->progress.lastshow != (long)now.tv_sec) { + shownow = TRUE; + + data->progress.lastshow = now.tv_sec; + + /* Let's do the "current speed" thing, which should use the fastest + of the dl/ul speeds. Store the faster speed at entry 'nowindex'. */ + data->progress.speeder[ nowindex ] = + data->progress.downloaded>data->progress.uploaded? + data->progress.downloaded:data->progress.uploaded; + + /* remember the exact time for this moment */ + data->progress.speeder_time [ nowindex ] = now; + + /* advance our speeder_c counter, which is increased every time we get + here and we expect it to never wrap as 2^32 is a lot of seconds! */ + data->progress.speeder_c++; + + /* figure out how many index entries of data we have stored in our speeder + array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of + transfer. Imagine, after one second we have filled in two entries, + after two seconds we've filled in three entries etc. */ + countindex = ((data->progress.speeder_c>=CURR_TIME)? + CURR_TIME:data->progress.speeder_c) - 1; + + /* first of all, we don't do this if there's no counted seconds yet */ + if(countindex) { + long span_ms; + + /* Get the index position to compare with the 'nowindex' position. + Get the oldest entry possible. While we have less than CURR_TIME + entries, the first entry will remain the oldest. */ + checkindex = (data->progress.speeder_c>=CURR_TIME)? + data->progress.speeder_c%CURR_TIME:0; + + /* Figure out the exact time for the time span */ + span_ms = Curl_tvdiff(now, + data->progress.speeder_time[checkindex]); + if(0 == span_ms) + span_ms=1; /* at least one millisecond MUST have passed */ + + /* Calculate the average speed the last 'span_ms' milliseconds */ + { + curl_off_t amount = data->progress.speeder[nowindex]- + data->progress.speeder[checkindex]; + + if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */) + /* the 'amount' value is bigger than would fit in 32 bits if + multiplied with 1000, so we use the double math for this */ + data->progress.current_speed = (curl_off_t) + ((double)amount/((double)span_ms/1000.0)); + else + /* the 'amount' value is small enough to fit within 32 bits even + when multiplied with 1000 */ + data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms; + } + } + else + /* the first second we use the main average */ + data->progress.current_speed = + (data->progress.ulspeed>data->progress.dlspeed)? + data->progress.ulspeed:data->progress.dlspeed; + + } /* Calculations end */ + + if(!(data->progress.flags & PGRS_HIDE)) { + /* progress meter has not been shut off */ + + if(data->set.fxferinfo) { + /* There's a callback set, call that */ + result= data->set.fxferinfo(data->set.progress_client, + data->progress.size_dl, + data->progress.downloaded, + data->progress.size_ul, + data->progress.uploaded); + if(result) + failf(data, "Callback aborted"); + return result; + } + else if(data->set.fprogress) { + /* The older deprecated callback is set, call that */ + result= data->set.fprogress(data->set.progress_client, + (double)data->progress.size_dl, + (double)data->progress.downloaded, + (double)data->progress.size_ul, + (double)data->progress.uploaded); + if(result) + failf(data, "Callback aborted"); + return result; + } + + if(!shownow) + /* only show the internal progress meter once per second */ + return 0; + + /* If there's no external callback set, use internal code to show + progress */ + + if(!(data->progress.flags & PGRS_HEADERS_OUT)) { + if(data->state.resume_from) { + fprintf(data->set.err, + "** Resuming transfer from byte position %" + CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); + } + fprintf(data->set.err, + " %% Total %% Received %% Xferd Average Speed " + "Time Time Time Current\n" + " Dload Upload " + "Total Spent Left Speed\n"); + data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */ + } + + /* Figure out the estimated time of arrival for the upload */ + if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && + (data->progress.ulspeed > CURL_OFF_T_C(0))) { + ulestimate = data->progress.size_ul / data->progress.ulspeed; + + if(data->progress.size_ul > CURL_OFF_T_C(10000)) + ulpercen = data->progress.uploaded / + (data->progress.size_ul/CURL_OFF_T_C(100)); + else if(data->progress.size_ul > CURL_OFF_T_C(0)) + ulpercen = (data->progress.uploaded*100) / + data->progress.size_ul; + } + + /* ... and the download */ + if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && + (data->progress.dlspeed > CURL_OFF_T_C(0))) { + dlestimate = data->progress.size_dl / data->progress.dlspeed; + + if(data->progress.size_dl > CURL_OFF_T_C(10000)) + dlpercen = data->progress.downloaded / + (data->progress.size_dl/CURL_OFF_T_C(100)); + else if(data->progress.size_dl > CURL_OFF_T_C(0)) + dlpercen = (data->progress.downloaded*100) / + data->progress.size_dl; + } + + /* Now figure out which of them is slower and use that one for the + total estimate! */ + total_estimate = ulestimate>dlestimate?ulestimate:dlestimate; + + /* create the three time strings */ + time2str(time_left, total_estimate > 0?(total_estimate - timespent):0); + time2str(time_total, total_estimate); + time2str(time_spent, timespent); + + /* Get the total amount of data expected to get transferred */ + total_expected_transfer = + (data->progress.flags & PGRS_UL_SIZE_KNOWN? + data->progress.size_ul:data->progress.uploaded)+ + (data->progress.flags & PGRS_DL_SIZE_KNOWN? + data->progress.size_dl:data->progress.downloaded); + + /* We have transferred this much so far */ + total_transfer = data->progress.downloaded + data->progress.uploaded; + + /* Get the percentage of data transferred so far */ + if(total_expected_transfer > CURL_OFF_T_C(10000)) + total_percen = total_transfer / + (total_expected_transfer/CURL_OFF_T_C(100)); + else if(total_expected_transfer > CURL_OFF_T_C(0)) + total_percen = (total_transfer*100) / total_expected_transfer; + + fprintf(data->set.err, + "\r" + "%3" CURL_FORMAT_CURL_OFF_T " %s " + "%3" CURL_FORMAT_CURL_OFF_T " %s " + "%3" CURL_FORMAT_CURL_OFF_T " %s %s %s %s %s %s %s", + total_percen, /* 3 letters */ /* total % */ + max5data(total_expected_transfer, max5[2]), /* total size */ + dlpercen, /* 3 letters */ /* rcvd % */ + max5data(data->progress.downloaded, max5[0]), /* rcvd size */ + ulpercen, /* 3 letters */ /* xfer % */ + max5data(data->progress.uploaded, max5[1]), /* xfer size */ + max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */ + max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */ + time_total, /* 8 letters */ /* total time */ + time_spent, /* 8 letters */ /* time spent */ + time_left, /* 8 letters */ /* time left */ + max5data(data->progress.current_speed, max5[5]) /* current speed */ + ); + + /* we flush the output stream to make it appear as soon as possible */ + fflush(data->set.err); + + } /* !(data->progress.flags & PGRS_HIDE) */ + + return 0; +} diff --git a/libcurl/src/lib/progress.h b/libcurl/src/lib/progress.h new file mode 100644 index 0000000..5a9c99f --- /dev/null +++ b/libcurl/src/lib/progress.h @@ -0,0 +1,73 @@ +#ifndef HEADER_CURL_PROGRESS_H +#define HEADER_CURL_PROGRESS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "timeval.h" + + +typedef enum { + TIMER_NONE, + TIMER_STARTOP, + TIMER_STARTSINGLE, + TIMER_NAMELOOKUP, + TIMER_CONNECT, + TIMER_APPCONNECT, + TIMER_PRETRANSFER, + TIMER_STARTTRANSFER, + TIMER_POSTRANSFER, + TIMER_STARTACCEPT, + TIMER_REDIRECT, + TIMER_LAST /* must be last */ +} timerid; + +CURL_STATIC int Curl_pgrsDone(struct connectdata *); +CURL_STATIC void Curl_pgrsStartNow(struct SessionHandle *data); +CURL_STATIC void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size); +CURL_STATIC void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size); +CURL_STATIC void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size); +CURL_STATIC void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size); +CURL_STATIC int Curl_pgrsUpdate(struct connectdata *); +CURL_STATIC void Curl_pgrsResetTimesSizes(struct SessionHandle *data); +CURL_STATIC void Curl_pgrsTime(struct SessionHandle *data, timerid timer); + + +/* Don't show progress for sizes smaller than: */ +#define LEAST_SIZE_PROGRESS BUFSIZE + +#define PROGRESS_DOWNLOAD (1<<0) +#define PROGRESS_UPLOAD (1<<1) +#define PROGRESS_DOWN_AND_UP (PROGRESS_UPLOAD | PROGRESS_DOWNLOAD) + +#define PGRS_SHOW_DL (1<<0) +#define PGRS_SHOW_UL (1<<1) +#define PGRS_DONE_DL (1<<2) +#define PGRS_DONE_UL (1<<3) +#define PGRS_HIDE (1<<4) +#define PGRS_UL_SIZE_KNOWN (1<<5) +#define PGRS_DL_SIZE_KNOWN (1<<6) + +#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */ + + +#endif /* HEADER_CURL_PROGRESS_H */ + diff --git a/libcurl/src/lib/rawstr.c b/libcurl/src/lib/rawstr.c new file mode 100644 index 0000000..541e3f6 --- /dev/null +++ b/libcurl/src/lib/rawstr.c @@ -0,0 +1,142 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "rawstr.h" + +/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because + its behavior is altered by the current locale. */ +CURL_STATIC char Curl_raw_toupper(char in) +{ + switch (in) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + case 'g': + return 'G'; + case 'h': + return 'H'; + case 'i': + return 'I'; + case 'j': + return 'J'; + case 'k': + return 'K'; + case 'l': + return 'L'; + case 'm': + return 'M'; + case 'n': + return 'N'; + case 'o': + return 'O'; + case 'p': + return 'P'; + case 'q': + return 'Q'; + case 'r': + return 'R'; + case 's': + return 'S'; + case 't': + return 'T'; + case 'u': + return 'U'; + case 'v': + return 'V'; + case 'w': + return 'W'; + case 'x': + return 'X'; + case 'y': + return 'Y'; + case 'z': + return 'Z'; + } + return in; +} + +/* + * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant + * to be locale independent and only compare strings we know are safe for + * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for + * some further explanation to why this function is necessary. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + */ + +CURL_STATIC int Curl_raw_equal(const char *first, const char *second) +{ + while(*first && *second) { + if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) + /* get out of the loop as soon as they don't match */ + break; + first++; + second++; + } + /* we do the comparison here (possibly again), just to make sure that if the + loop above is skipped because one of the strings reached zero, we must not + return this as a successful match */ + return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); +} + +CURL_STATIC int Curl_raw_nequal(const char *first, const char *second, size_t max) +{ + while(*first && *second && max) { + if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) { + break; + } + max--; + first++; + second++; + } + if(0 == max) + return 1; /* they are equal this far */ + + return Curl_raw_toupper(*first) == Curl_raw_toupper(*second); +} + +/* Copy an upper case version of the string from src to dest. The + * strings may overlap. No more than n characters of the string are copied + * (including any NUL) and the destination string will NOT be + * NUL-terminated if that limit is reached. + */ +CURL_STATIC void Curl_strntoupper(char *dest, const char *src, size_t n) +{ + if(n < 1) + return; + + do { + *dest++ = Curl_raw_toupper(*src); + } while(*src++ && --n); +} diff --git a/libcurl/src/lib/rawstr.h b/libcurl/src/lib/rawstr.h new file mode 100644 index 0000000..554e050 --- /dev/null +++ b/libcurl/src/lib/rawstr.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_RAWSTR_H +#define HEADER_CURL_RAWSTR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +/* + * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant + * to be locale independent and only compare strings we know are safe for + * this. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + */ +CURL_STATIC int Curl_raw_equal(const char *first, const char *second); +CURL_STATIC int Curl_raw_nequal(const char *first, const char *second, size_t max); + +CURL_STATIC char Curl_raw_toupper(char in); + +/* checkprefix() is a shorter version of the above, used when the first + argument is zero-byte terminated */ +#define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a)) + +CURL_STATIC void Curl_strntoupper(char *dest, const char *src, size_t n); + +#endif /* HEADER_CURL_RAWSTR_H */ + diff --git a/libcurl/src/lib/rtsp.c b/libcurl/src/lib/rtsp.c new file mode 100644 index 0000000..531d206 --- /dev/null +++ b/libcurl/src/lib/rtsp.c @@ -0,0 +1,807 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_RTSP + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "multiif.h" +#include "http.h" +#include "url.h" +#include "progress.h" +#include "rtsp.h" +#include "rawstr.h" +#include "select.h" +#include "connect.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * TODO (general) + * -incoming server requests + * -server CSeq counter + * -digest authentication + * -connect thru proxy + * -pipelining? + */ + + +#define RTP_PKT_CHANNEL(p) ((int)((unsigned char)((p)[1]))) + +#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \ + ((int)((unsigned char)((p)[3])))) + +/* protocol-specific functions set up to be called by the main engine */ +static CURLcode rtsp_do(struct connectdata *conn, bool *done); +static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature); +static CURLcode rtsp_connect(struct connectdata *conn, bool *done); +static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead); + +static int rtsp_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + +/* + * Parse and write out any available RTP data. + * + * nread: amount of data left after k->str. will be modified if RTP + * data is parsed and k->str is moved up + * readmore: whether or not the RTP parser needs more data right away + */ +static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data, + struct connectdata *conn, + ssize_t *nread, + bool *readmore); + +static CURLcode rtsp_setup_connection(struct connectdata *conn); + + +/* this returns the socket to wait for in the DO and DOING state for the multi + interface and then we're always _sending_ a request and thus we wait for + the single socket to become writable only */ +static int rtsp_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + /* write mode */ + (void)numsocks; /* unused, we trust it to be at least 1 */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); +} + +static +CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len); + + +/* + * RTSP handler interface. + */ +const struct Curl_handler Curl_handler_rtsp = { + "RTSP", /* scheme */ + rtsp_setup_connection, /* setup_connection */ + rtsp_do, /* do_it */ + rtsp_done, /* done */ + ZERO_NULL, /* do_more */ + rtsp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + rtsp_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtsp_disconnect, /* disconnect */ + rtsp_rtp_readwrite, /* readwrite */ + PORT_RTSP, /* defport */ + CURLPROTO_RTSP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + + +static CURLcode rtsp_setup_connection(struct connectdata *conn) +{ + struct RTSP *rtsp; + + conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP)); + if(!rtsp) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + + +/* + * The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not + * want to block the application forever while receiving a stream. Therefore, + * we cannot assume that an RTSP socket is dead just because it is readable. + * + * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket + * and distinguish between closed and data. + */ +CURL_STATIC bool Curl_rtsp_connisdead(struct connectdata *check) +{ + int sval; + bool ret_val = TRUE; + + sval = Curl_socket_ready(check->sock[FIRSTSOCKET], CURL_SOCKET_BAD, 0); + if(sval == 0) { + /* timeout */ + ret_val = FALSE; + } + else if(sval & CURL_CSELECT_ERR) { + /* socket is in an error state */ + ret_val = TRUE; + } + else if((sval & CURL_CSELECT_IN) && check->data) { + /* readable with no error. could be closed or could be alive but we can + only check if we have a proper SessionHandle for the connection */ + curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check); + if(connectinfo != CURL_SOCKET_BAD) + ret_val = FALSE; + } + + return ret_val; +} + +static CURLcode rtsp_connect(struct connectdata *conn, bool *done) +{ + CURLcode httpStatus; + struct SessionHandle *data = conn->data; + + httpStatus = Curl_http_connect(conn, done); + + /* Initialize the CSeq if not already done */ + if(data->state.rtsp_next_client_CSeq == 0) + data->state.rtsp_next_client_CSeq = 1; + if(data->state.rtsp_next_server_CSeq == 0) + data->state.rtsp_next_server_CSeq = 1; + + conn->proto.rtspc.rtp_channel = -1; + + return httpStatus; +} + +static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead) +{ + (void) dead; + Curl_safefree(conn->proto.rtspc.rtp_buf); + return CURLE_OK; +} + + +static CURLcode rtsp_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct SessionHandle *data = conn->data; + struct RTSP *rtsp = data->req.protop; + CURLcode httpStatus; + long CSeq_sent; + long CSeq_recv; + + /* Bypass HTTP empty-reply checks on receive */ + if(data->set.rtspreq == RTSPREQ_RECEIVE) + premature = TRUE; + + httpStatus = Curl_http_done(conn, status, premature); + + if(rtsp) { + /* Check the sequence numbers */ + CSeq_sent = rtsp->CSeq_sent; + CSeq_recv = rtsp->CSeq_recv; + if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) { + failf(data, + "The CSeq of this request %ld did not match the response %ld", + CSeq_sent, CSeq_recv); + return CURLE_RTSP_CSEQ_ERROR; + } + else if(data->set.rtspreq == RTSPREQ_RECEIVE && + (conn->proto.rtspc.rtp_channel == -1)) { + infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv); + /* TODO CPC: Server -> Client logic here */ + } + } + + return httpStatus; +} + +static CURLcode rtsp_do(struct connectdata *conn, bool *done) +{ + struct SessionHandle *data = conn->data; + CURLcode result=CURLE_OK; + Curl_RtspReq rtspreq = data->set.rtspreq; + struct RTSP *rtsp = data->req.protop; + struct HTTP *http; + Curl_send_buffer *req_buffer; + curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */ + curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */ + + const char *p_request = NULL; + const char *p_session_id = NULL; + const char *p_accept = NULL; + const char *p_accept_encoding = NULL; + const char *p_range = NULL; + const char *p_referrer = NULL; + const char *p_stream_uri = NULL; + const char *p_transport = NULL; + const char *p_uagent = NULL; + + *done = TRUE; + + http = &(rtsp->http_wrapper); + /* Assert that no one has changed the RTSP struct in an evil way */ + DEBUGASSERT((void *)http == (void *)rtsp); + + rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq; + rtsp->CSeq_recv = 0; + + /* Setup the 'p_request' pointer to the proper p_request string + * Since all RTSP requests are included here, there is no need to + * support custom requests like HTTP. + **/ + DEBUGASSERT((rtspreq > RTSPREQ_NONE && rtspreq < RTSPREQ_LAST)); + data->set.opt_no_body = TRUE; /* most requests don't contain a body */ + switch(rtspreq) { + case RTSPREQ_NONE: + failf(data, "Got invalid RTSP request: RTSPREQ_NONE"); + return CURLE_BAD_FUNCTION_ARGUMENT; + case RTSPREQ_OPTIONS: + p_request = "OPTIONS"; + break; + case RTSPREQ_DESCRIBE: + p_request = "DESCRIBE"; + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_ANNOUNCE: + p_request = "ANNOUNCE"; + break; + case RTSPREQ_SETUP: + p_request = "SETUP"; + break; + case RTSPREQ_PLAY: + p_request = "PLAY"; + break; + case RTSPREQ_PAUSE: + p_request = "PAUSE"; + break; + case RTSPREQ_TEARDOWN: + p_request = "TEARDOWN"; + break; + case RTSPREQ_GET_PARAMETER: + /* GET_PARAMETER's no_body status is determined later */ + p_request = "GET_PARAMETER"; + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_SET_PARAMETER: + p_request = "SET_PARAMETER"; + break; + case RTSPREQ_RECORD: + p_request = "RECORD"; + break; + case RTSPREQ_RECEIVE: + p_request = ""; + /* Treat interleaved RTP as body*/ + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_LAST: + failf(data, "Got invalid RTSP request: RTSPREQ_LAST"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + if(rtspreq == RTSPREQ_RECEIVE) { + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, -1, NULL); + + return result; + } + + p_session_id = data->set.str[STRING_RTSP_SESSION_ID]; + if(!p_session_id && + (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) { + failf(data, "Refusing to issue an RTSP request [%s] without a session ID.", + p_request ? p_request : ""); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + /* TODO: auth? */ + /* TODO: proxy? */ + + /* Stream URI. Default to server '*' if not specified */ + if(data->set.str[STRING_RTSP_STREAM_URI]) { + p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI]; + } + else { + p_stream_uri = "*"; + } + + /* Transport Header for SETUP requests */ + p_transport = Curl_checkheaders(conn, "Transport:"); + if(rtspreq == RTSPREQ_SETUP && !p_transport) { + /* New Transport: setting? */ + if(data->set.str[STRING_RTSP_TRANSPORT]) { + Curl_safefree(conn->allocptr.rtsp_transport); + + conn->allocptr.rtsp_transport = + aprintf("Transport: %s\r\n", + data->set.str[STRING_RTSP_TRANSPORT]); + if(!conn->allocptr.rtsp_transport) + return CURLE_OUT_OF_MEMORY; + } + else { + failf(data, + "Refusing to issue an RTSP SETUP without a Transport: header."); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + p_transport = conn->allocptr.rtsp_transport; + } + + /* Accept Headers for DESCRIBE requests */ + if(rtspreq == RTSPREQ_DESCRIBE) { + /* Accept Header */ + p_accept = Curl_checkheaders(conn, "Accept:")? + NULL:"Accept: application/sdp\r\n"; + + /* Accept-Encoding header */ + if(!Curl_checkheaders(conn, "Accept-Encoding:") && + data->set.str[STRING_ENCODING]) { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = + aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); + + if(!conn->allocptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; + + p_accept_encoding = conn->allocptr.accept_encoding; + } + } + + /* The User-Agent string might have been allocated in url.c already, because + it might have been used in the proxy connect, but if we have got a header + with the user-agent string specified, we erase the previously made string + here. */ + if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) { + Curl_safefree(conn->allocptr.uagent); + conn->allocptr.uagent = NULL; + } + else if(!Curl_checkheaders(conn, "User-Agent:") && + data->set.str[STRING_USERAGENT]) { + p_uagent = conn->allocptr.uagent; + } + + /* Referrer */ + Curl_safefree(conn->allocptr.ref); + if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) + conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + else + conn->allocptr.ref = NULL; + + p_referrer = conn->allocptr.ref; + + /* + * Range Header + * Only applies to PLAY, PAUSE, RECORD + * + * Go ahead and use the Range stuff supplied for HTTP + */ + if(data->state.use_range && + (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) { + + /* Check to see if there is a range set in the custom headers */ + if(!Curl_checkheaders(conn, "Range:") && data->state.range) { + Curl_safefree(conn->allocptr.rangeline); + conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range); + p_range = conn->allocptr.rangeline; + } + } + + /* + * Sanity check the custom headers + */ + if(Curl_checkheaders(conn, "CSeq:")) { + failf(data, "CSeq cannot be set as a custom header."); + return CURLE_RTSP_CSEQ_ERROR; + } + if(Curl_checkheaders(conn, "Session:")) { + failf(data, "Session ID cannot be set as a custom header."); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + /* Initialize a dynamic send buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + result = + Curl_add_bufferf(req_buffer, + "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */ + "CSeq: %ld\r\n", /* CSeq */ + (p_request ? p_request : ""), p_stream_uri, + rtsp->CSeq_sent); + if(result) + return result; + + /* + * Rather than do a normal alloc line, keep the session_id unformatted + * to make comparison easier + */ + if(p_session_id) { + result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id); + if(result) + return result; + } + + /* + * Shared HTTP-like options + */ + result = Curl_add_bufferf(req_buffer, + "%s" /* transport */ + "%s" /* accept */ + "%s" /* accept-encoding */ + "%s" /* range */ + "%s" /* referrer */ + "%s" /* user-agent */ + , + p_transport ? p_transport : "", + p_accept ? p_accept : "", + p_accept_encoding ? p_accept_encoding : "", + p_range ? p_range : "", + p_referrer ? p_referrer : "", + p_uagent ? p_uagent : ""); + if(result) + return result; + + if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) { + result = Curl_add_timecondition(data, req_buffer); + if(result) + return result; + } + + result = Curl_add_custom_headers(conn, FALSE, req_buffer); + if(result) + return result; + + if(rtspreq == RTSPREQ_ANNOUNCE || + rtspreq == RTSPREQ_SET_PARAMETER || + rtspreq == RTSPREQ_GET_PARAMETER) { + + if(data->set.upload) { + putsize = data->state.infilesize; + data->set.httpreq = HTTPREQ_PUT; + + } + else { + postsize = (data->set.postfieldsize != -1)? + data->set.postfieldsize: + (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); + data->set.httpreq = HTTPREQ_POST; + } + + if(putsize > 0 || postsize > 0) { + /* As stated in the http comments, it is probably not wise to + * actually set a custom Content-Length in the headers */ + if(!Curl_checkheaders(conn, "Content-Length:")) { + result = Curl_add_bufferf(req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", + (data->set.upload ? putsize : postsize)); + if(result) + return result; + } + + if(rtspreq == RTSPREQ_SET_PARAMETER || + rtspreq == RTSPREQ_GET_PARAMETER) { + if(!Curl_checkheaders(conn, "Content-Type:")) { + result = Curl_add_bufferf(req_buffer, + "Content-Type: text/parameters\r\n"); + if(result) + return result; + } + } + + if(rtspreq == RTSPREQ_ANNOUNCE) { + if(!Curl_checkheaders(conn, "Content-Type:")) { + result = Curl_add_bufferf(req_buffer, + "Content-Type: application/sdp\r\n"); + if(result) + return result; + } + } + + data->state.expect100header = FALSE; /* RTSP posts are simple/small */ + } + else if(rtspreq == RTSPREQ_GET_PARAMETER) { + /* Check for an empty GET_PARAMETER (heartbeat) request */ + data->set.httpreq = HTTPREQ_HEAD; + data->set.opt_no_body = TRUE; + } + } + + /* RTSP never allows chunked transfer */ + data->req.forbidchunk = TRUE; + /* Finish the request buffer */ + result = Curl_add_buffer(req_buffer, "\r\n", 2); + if(result) + return result; + + if(postsize > 0) { + result = Curl_add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + if(result) + return result; + } + + /* issue the request */ + result = Curl_add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) { + failf(data, "Failed sending RTSP request"); + return result; + } + + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, + putsize?FIRSTSOCKET:-1, + putsize?&http->writebytecount:NULL); + + /* Increment the CSeq on success */ + data->state.rtsp_next_client_CSeq++; + + if(http->writebytecount) { + /* if a request-body has been sent off, we make sure this progress is + noted properly */ + Curl_pgrsSetUploadCounter(data, http->writebytecount); + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + } + + return result; +} + + +static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data, + struct connectdata *conn, + ssize_t *nread, + bool *readmore) { + struct SingleRequest *k = &data->req; + struct rtsp_conn *rtspc = &(conn->proto.rtspc); + + char *rtp; /* moving pointer to rtp data */ + ssize_t rtp_dataleft; /* how much data left to parse in this round */ + char *scratch; + CURLcode result; + + if(rtspc->rtp_buf) { + /* There was some leftover data the last time. Merge buffers */ + char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread); + if(!newptr) { + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return CURLE_OUT_OF_MEMORY; + } + rtspc->rtp_buf = newptr; + memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread); + rtspc->rtp_bufsize += *nread; + rtp = rtspc->rtp_buf; + rtp_dataleft = rtspc->rtp_bufsize; + } + else { + /* Just parse the request buffer directly */ + rtp = k->str; + rtp_dataleft = *nread; + } + + while((rtp_dataleft > 0) && + (rtp[0] == '$')) { + if(rtp_dataleft > 4) { + int rtp_length; + + /* Parse the header */ + /* The channel identifier immediately follows and is 1 byte */ + rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp); + + /* The length is two bytes */ + rtp_length = RTP_PKT_LENGTH(rtp); + + if(rtp_dataleft < rtp_length + 4) { + /* Need more - incomplete payload*/ + *readmore = TRUE; + break; + } + else { + /* We have the full RTP interleaved packet + * Write out the header including the leading '$' */ + DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n", + rtspc->rtp_channel, rtp_length)); + result = rtp_client_write(conn, &rtp[0], rtp_length + 4); + if(result) { + failf(data, "Got an error writing an RTP packet"); + *readmore = FALSE; + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return result; + } + + /* Move forward in the buffer */ + rtp_dataleft -= rtp_length + 4; + rtp += rtp_length + 4; + + if(data->set.rtspreq == RTSPREQ_RECEIVE) { + /* If we are in a passive receive, give control back + * to the app as often as we can. + */ + k->keepon &= ~KEEP_RECV; + } + } + } + else { + /* Need more - incomplete header */ + *readmore = TRUE; + break; + } + } + + if(rtp_dataleft != 0 && rtp[0] == '$') { + DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft, + *readmore ? "(READMORE)" : "")); + + /* Store the incomplete RTP packet for a "rewind" */ + scratch = malloc(rtp_dataleft); + if(!scratch) { + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return CURLE_OUT_OF_MEMORY; + } + memcpy(scratch, rtp, rtp_dataleft); + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = scratch; + rtspc->rtp_bufsize = rtp_dataleft; + + /* As far as the transfer is concerned, this data is consumed */ + *nread = 0; + return CURLE_OK; + } + else { + /* Fix up k->str to point just after the last RTP packet */ + k->str += *nread - rtp_dataleft; + + /* either all of the data has been read or... + * rtp now points at the next byte to parse + */ + if(rtp_dataleft > 0) + DEBUGASSERT(k->str[0] == rtp[0]); + + DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */ + + *nread = rtp_dataleft; + } + + /* If we get here, we have finished with the leftover/merge buffer */ + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + + return CURLE_OK; +} + +static +CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) +{ + struct SessionHandle *data = conn->data; + size_t wrote; + curl_write_callback writeit; + + if(len == 0) { + failf (data, "Cannot write a 0 size RTP packet."); + return CURLE_WRITE_ERROR; + } + + writeit = data->set.fwrite_rtp?data->set.fwrite_rtp:data->set.fwrite_func; + wrote = writeit(ptr, 1, len, data->set.rtp_out); + + if(CURL_WRITEFUNC_PAUSE == wrote) { + failf (data, "Cannot pause RTP"); + return CURLE_WRITE_ERROR; + } + + if(wrote != len) { + failf (data, "Failed writing RTP data"); + return CURLE_WRITE_ERROR; + } + + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_rtsp_parseheader(struct connectdata *conn, + char *header) +{ + struct SessionHandle *data = conn->data; + long CSeq = 0; + + if(checkprefix("CSeq:", header)) { + /* Store the received CSeq. Match is verified in rtsp_done */ + int nc = sscanf(&header[4], ": %ld", &CSeq); + if(nc == 1) { + struct RTSP *rtsp = data->req.protop; + rtsp->CSeq_recv = CSeq; /* mark the request */ + data->state.rtsp_CSeq_recv = CSeq; /* update the handle */ + } + else { + failf(data, "Unable to read the CSeq header: [%s]", header); + return CURLE_RTSP_CSEQ_ERROR; + } + } + else if(checkprefix("Session:", header)) { + char *start; + + /* Find the first non-space letter */ + start = header + 8; + while(*start && ISSPACE(*start)) + start++; + + if(!*start) { + failf(data, "Got a blank Session ID"); + } + else if(data->set.str[STRING_RTSP_SESSION_ID]) { + /* If the Session ID is set, then compare */ + if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], + strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) { + failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]", + start, data->set.str[STRING_RTSP_SESSION_ID]); + return CURLE_RTSP_SESSION_ERROR; + } + } + else { + /* If the Session ID is not set, and we find it in a response, then + set it */ + + /* The session ID can be an alphanumeric or a 'safe' character + * + * RFC 2326 15.1 Base Syntax: + * safe = "\$" | "-" | "_" | "." | "+" + * */ + char *end = start; + while(*end && + (ISALNUM(*end) || *end == '-' || *end == '_' || *end == '.' || + *end == '+' || + (*end == '\\' && *(end + 1) && *(end + 1) == '$' && (++end, 1)))) + end++; + + /* Copy the id substring into a new buffer */ + data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1); + if(data->set.str[STRING_RTSP_SESSION_ID] == NULL) + return CURLE_OUT_OF_MEMORY; + memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start); + (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0'; + } + } + return CURLE_OK; +} + +#endif /* CURL_DISABLE_RTSP */ diff --git a/libcurl/src/lib/rtsp.h b/libcurl/src/lib/rtsp.h new file mode 100644 index 0000000..00933c0 --- /dev/null +++ b/libcurl/src/lib/rtsp.h @@ -0,0 +1,69 @@ +#ifndef HEADER_CURL_RTSP_H +#define HEADER_CURL_RTSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_RTSP + +extern const struct Curl_handler Curl_handler_rtsp; + +CURL_STATIC bool Curl_rtsp_connisdead(struct connectdata *check); +CURL_STATIC CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header); + +#else +/* disabled */ +#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN +#define Curl_rtsp_connisdead(x) TRUE + +#endif /* CURL_DISABLE_RTSP */ + +/* + * RTSP Connection data + * + * Currently, only used for tracking incomplete RTP data reads + */ +struct rtsp_conn { + char *rtp_buf; + ssize_t rtp_bufsize; + int rtp_channel; +}; + +/**************************************************************************** + * RTSP unique setup + ***************************************************************************/ +struct RTSP { + /* + * http_wrapper MUST be the first element of this structure for the wrap + * logic to work. In this way, we get a cheap polymorphism because + * &(data->state.proto.rtsp) == &(data->state.proto.http) per the C spec + * + * HTTP functions can safely treat this as an HTTP struct, but RTSP aware + * functions can also index into the later elements. + */ + struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */ + + long CSeq_sent; /* CSeq of this request */ + long CSeq_recv; /* CSeq received */ +}; + + +#endif /* HEADER_CURL_RTSP_H */ + diff --git a/libcurl/src/lib/security.c b/libcurl/src/lib/security.c new file mode 100644 index 0000000..10cb73c --- /dev/null +++ b/libcurl/src/lib/security.c @@ -0,0 +1,597 @@ +/* This source code was modified by Martin Hedenfalk for + * use in Curl. His latest changes were done 2000-09-18. + * + * It has since been patched and modified a lot by Daniel Stenberg + * to make it better applied to curl conditions, and to make + * it not use globals, pollute name space and more. This source code awaits a + * rewrite to work around the paragraph 2 in the BSD licenses as explained + * below. + * + * Copyright (c) 1998, 1999 Kungliga Tekniska Hgskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * + * Copyright (C) 2001 - 2015, Daniel Stenberg, , et al. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP +#ifdef HAVE_GSSAPI + +#ifdef HAVE_NETDB_H +#include +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include "urldata.h" +#include "curl_base64.h" +#include "curl_memory.h" +#include "curl_sec.h" +#include "ftp.h" +#include "sendf.h" +#include "rawstr.h" +#include "warnless.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +static const struct { + enum protection_level level; + const char *name; +} level_names[] = { + { PROT_CLEAR, "clear" }, + { PROT_SAFE, "safe" }, + { PROT_CONFIDENTIAL, "confidential" }, + { PROT_PRIVATE, "private" } +}; + +static enum protection_level +name_to_level(const char *name) +{ + int i; + for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++) + if(checkprefix(name, level_names[i].name)) + return level_names[i].level; + return PROT_NONE; +} + +/* Convert a protocol |level| to its char representation. + We take an int to catch programming mistakes. */ +static char level_to_char(int level) { + switch(level) { + case PROT_CLEAR: + return 'C'; + case PROT_SAFE: + return 'S'; + case PROT_CONFIDENTIAL: + return 'E'; + case PROT_PRIVATE: + return 'P'; + case PROT_CMD: + /* Fall through */ + default: + /* Those 2 cases should not be reached! */ + break; + } + DEBUGASSERT(0); + /* Default to the most secure alternative. */ + return 'P'; +} + +static const struct Curl_sec_client_mech * const mechs[] = { +#ifdef HAVE_GSSAPI + &Curl_krb5_client_mech, +#endif + NULL +}; + +/* Send an FTP command defined by |message| and the optional arguments. The + function returns the ftp_code. If an error occurs, -1 is returned. */ +static int ftp_send_command(struct connectdata *conn, const char *message, ...) +{ + int ftp_code; + ssize_t nread=0; + va_list args; + char print_buffer[50]; + + va_start(args, message); + vsnprintf(print_buffer, sizeof(print_buffer), message, args); + va_end(args); + + if(Curl_ftpsendf(conn, print_buffer)) { + ftp_code = -1; + } + else { + if(Curl_GetFTPResponse(&nread, conn, &ftp_code)) + ftp_code = -1; + } + + (void)nread; /* Unused */ + return ftp_code; +} + +/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode + saying whether an error occurred or CURLE_OK if |len| was read. */ +static CURLcode +socket_read(curl_socket_t fd, void *to, size_t len) +{ + char *to_p = to; + CURLcode result; + ssize_t nread; + + while(len > 0) { + result = Curl_read_plain(fd, to_p, len, &nread); + if(!result) { + len -= nread; + to_p += nread; + } + else { + /* FIXME: We are doing a busy wait */ + if(result == CURLE_AGAIN) + continue; + return result; + } + } + return CURLE_OK; +} + + +/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a + CURLcode saying whether an error occurred or CURLE_OK if |len| was + written. */ +static CURLcode +socket_write(struct connectdata *conn, curl_socket_t fd, const void *to, + size_t len) +{ + const char *to_p = to; + CURLcode result; + ssize_t written; + + while(len > 0) { + result = Curl_write_plain(conn, fd, to_p, len, &written); + if(!result) { + len -= written; + to_p += written; + } + else { + /* FIXME: We are doing a busy wait */ + if(result == CURLE_AGAIN) + continue; + return result; + } + } + return CURLE_OK; +} + +static CURLcode read_data(struct connectdata *conn, + curl_socket_t fd, + struct krb5buffer *buf) +{ + int len; + void* tmp; + CURLcode result; + + result = socket_read(fd, &len, sizeof(len)); + if(result) + return result; + + len = ntohl(len); + tmp = realloc(buf->data, len); + if(tmp == NULL) + return CURLE_OUT_OF_MEMORY; + + buf->data = tmp; + result = socket_read(fd, buf->data, len); + if(result) + return result; + buf->size = conn->mech->decode(conn->app_data, buf->data, len, + conn->data_prot, conn); + buf->index = 0; + return CURLE_OK; +} + +static size_t +buffer_read(struct krb5buffer *buf, void *data, size_t len) +{ + if(buf->size - buf->index < len) + len = buf->size - buf->index; + memcpy(data, (char*)buf->data + buf->index, len); + buf->index += len; + return len; +} + +/* Matches Curl_recv signature */ +static ssize_t sec_recv(struct connectdata *conn, int sockindex, + char *buffer, size_t len, CURLcode *err) +{ + size_t bytes_read; + size_t total_read = 0; + curl_socket_t fd = conn->sock[sockindex]; + + *err = CURLE_OK; + + /* Handle clear text response. */ + if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) + return read(fd, buffer, len); + + if(conn->in_buffer.eof_flag) { + conn->in_buffer.eof_flag = 0; + return 0; + } + + bytes_read = buffer_read(&conn->in_buffer, buffer, len); + len -= bytes_read; + total_read += bytes_read; + buffer += bytes_read; + + while(len > 0) { + if(read_data(conn, fd, &conn->in_buffer)) + return -1; + if(conn->in_buffer.size == 0) { + if(bytes_read > 0) + conn->in_buffer.eof_flag = 1; + return bytes_read; + } + bytes_read = buffer_read(&conn->in_buffer, buffer, len); + len -= bytes_read; + total_read += bytes_read; + buffer += bytes_read; + } + /* FIXME: Check for overflow */ + return total_read; +} + +/* Send |length| bytes from |from| to the |fd| socket taking care of encoding + and negociating with the server. |from| can be NULL. */ +/* FIXME: We don't check for errors nor report any! */ +static void do_sec_send(struct connectdata *conn, curl_socket_t fd, + const char *from, int length) +{ + int bytes, htonl_bytes; /* 32-bit integers for htonl */ + char *buffer = NULL; + char *cmd_buffer; + size_t cmd_size = 0; + CURLcode error; + enum protection_level prot_level = conn->data_prot; + bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE; + + DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST); + + if(iscmd) { + if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5)) + prot_level = PROT_PRIVATE; + else + prot_level = conn->command_prot; + } + bytes = conn->mech->encode(conn->app_data, from, length, prot_level, + (void**)&buffer); + if(!buffer || bytes <= 0) + return; /* error */ + + if(iscmd) { + error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes), + &cmd_buffer, &cmd_size); + if(error) { + free(buffer); + return; /* error */ + } + if(cmd_size > 0) { + static const char *enc = "ENC "; + static const char *mic = "MIC "; + if(prot_level == PROT_PRIVATE) + socket_write(conn, fd, enc, 4); + else + socket_write(conn, fd, mic, 4); + + socket_write(conn, fd, cmd_buffer, cmd_size); + socket_write(conn, fd, "\r\n", 2); + infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic, + cmd_buffer); + free(cmd_buffer); + } + } + else { + htonl_bytes = htonl(bytes); + socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes)); + socket_write(conn, fd, buffer, curlx_sitouz(bytes)); + } + free(buffer); +} + +static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd, + const char *buffer, size_t length) +{ + ssize_t tx = 0, len = conn->buffer_size; + + len -= conn->mech->overhead(conn->app_data, conn->data_prot, + curlx_sztosi(len)); + if(len <= 0) + len = length; + while(length) { + if(length < (size_t)len) + len = length; + + do_sec_send(conn, fd, buffer, curlx_sztosi(len)); + length -= len; + buffer += len; + tx += len; + } + return tx; +} + +/* Matches Curl_send signature */ +static ssize_t sec_send(struct connectdata *conn, int sockindex, + const void *buffer, size_t len, CURLcode *err) +{ + curl_socket_t fd = conn->sock[sockindex]; + *err = CURLE_OK; + return sec_write(conn, fd, buffer, len); +} + +CURL_STATIC int Curl_sec_read_msg(struct connectdata *conn, char *buffer, + enum protection_level level) +{ + /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an + int */ + int decoded_len; + char *buf; + int ret_code; + size_t decoded_sz = 0; + CURLcode error; + + DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); + + error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz); + if(error || decoded_sz == 0) + return -1; + + if(decoded_sz > (size_t)INT_MAX) { + free(buf); + return -1; + } + decoded_len = curlx_uztosi(decoded_sz); + + decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len, + level, conn); + if(decoded_len <= 0) { + free(buf); + return -1; + } + + if(conn->data->set.verbose) { + buf[decoded_len] = '\n'; + Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1, conn); + } + + buf[decoded_len] = '\0'; + DEBUGASSERT(decoded_len > 3); + if(buf[3] == '-') + ret_code = 0; + else { + /* Check for error? */ + (void)sscanf(buf, "%d", &ret_code); + } + + if(buf[decoded_len - 1] == '\n') + buf[decoded_len - 1] = '\0'; + /* FIXME: Is |buffer| length always greater than |decoded_len|? */ + strcpy(buffer, buf); + free(buf); + return ret_code; +} + +/* FIXME: The error code returned here is never checked. */ +static int sec_set_protection_level(struct connectdata *conn) +{ + int code; + char* pbsz; + static unsigned int buffer_size = 1 << 20; /* 1048576 */ + enum protection_level level = conn->request_data_prot; + + DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); + + if(!conn->sec_complete) { + infof(conn->data, "Trying to change the protection level after the" + "completion of the data exchange.\n"); + return -1; + } + + /* Bail out if we try to set up the same level */ + if(conn->data_prot == level) + return 0; + + if(level) { + code = ftp_send_command(conn, "PBSZ %u", buffer_size); + if(code < 0) + return -1; + + if(code/100 != 2) { + failf(conn->data, "Failed to set the protection's buffer size."); + return -1; + } + conn->buffer_size = buffer_size; + + pbsz = strstr(conn->data->state.buffer, "PBSZ="); + if(pbsz) { + /* FIXME: Checks for errors in sscanf? */ + sscanf(pbsz, "PBSZ=%u", &buffer_size); + if(buffer_size < conn->buffer_size) + conn->buffer_size = buffer_size; + } + } + + /* Now try to negiociate the protection level. */ + code = ftp_send_command(conn, "PROT %c", level_to_char(level)); + + if(code < 0) + return -1; + + if(code/100 != 2) { + failf(conn->data, "Failed to set the protection level."); + return -1; + } + + conn->data_prot = level; + if(level == PROT_PRIVATE) + conn->command_prot = level; + + return 0; +} + +CURL_STATIC int +Curl_sec_request_prot(struct connectdata *conn, const char *level) +{ + enum protection_level l = name_to_level(level); + if(l == PROT_NONE) + return -1; + DEBUGASSERT(l > PROT_NONE && l < PROT_LAST); + conn->request_data_prot = l; + return 0; +} + +static CURLcode choose_mech(struct connectdata *conn) +{ + int ret; + struct SessionHandle *data = conn->data; + const struct Curl_sec_client_mech * const *mech; + void *tmp_allocation; + const char *mech_name; + + for(mech = mechs; (*mech); ++mech) { + mech_name = (*mech)->name; + /* We have no mechanism with a NULL name but keep this check */ + DEBUGASSERT(mech_name != NULL); + if(mech_name == NULL) { + infof(data, "Skipping mechanism with empty name (%p)\n", (void *)mech); + continue; + } + tmp_allocation = realloc(conn->app_data, (*mech)->size); + if(tmp_allocation == NULL) { + failf(data, "Failed realloc of size %u", (*mech)->size); + mech = NULL; + return CURLE_OUT_OF_MEMORY; + } + conn->app_data = tmp_allocation; + + if((*mech)->init) { + ret = (*mech)->init(conn->app_data); + if(ret != 0) { + infof(data, "Failed initialization for %s. Skipping it.\n", mech_name); + continue; + } + } + + infof(data, "Trying mechanism %s...\n", mech_name); + ret = ftp_send_command(conn, "AUTH %s", mech_name); + if(ret < 0) + /* FIXME: This error is too generic but it is OK for now. */ + return CURLE_COULDNT_CONNECT; + + if(ret/100 != 3) { + switch(ret) { + case 504: + infof(data, "Mechanism %s is not supported by the server (server " + "returned ftp code: 504).\n", mech_name); + break; + case 534: + infof(data, "Mechanism %s was rejected by the server (server returned " + "ftp code: 534).\n", mech_name); + break; + default: + if(ret/100 == 5) { + infof(data, "server does not support the security extensions\n"); + return CURLE_USE_SSL_FAILED; + } + break; + } + continue; + } + + /* Authenticate */ + ret = (*mech)->auth(conn->app_data, conn); + + if(ret == AUTH_CONTINUE) + continue; + else if(ret != AUTH_OK) { + /* Mechanism has dumped the error to stderr, don't error here. */ + return -1; + } + DEBUGASSERT(ret == AUTH_OK); + + conn->mech = *mech; + conn->sec_complete = 1; + conn->recv[FIRSTSOCKET] = sec_recv; + conn->send[FIRSTSOCKET] = sec_send; + conn->recv[SECONDARYSOCKET] = sec_recv; + conn->send[SECONDARYSOCKET] = sec_send; + conn->command_prot = PROT_SAFE; + /* Set the requested protection level */ + /* BLOCKING */ + (void)sec_set_protection_level(conn); + break; + } + + return *mech != NULL ? CURLE_OK : CURLE_FAILED_INIT; +} + +CURL_STATIC CURLcode +Curl_sec_login(struct connectdata *conn) +{ + return choose_mech(conn); +} + + +CURL_STATIC void +Curl_sec_end(struct connectdata *conn) +{ + if(conn->mech != NULL && conn->mech->end) + conn->mech->end(conn->app_data); + free(conn->app_data); + conn->app_data = NULL; + if(conn->in_buffer.data) { + free(conn->in_buffer.data); + conn->in_buffer.data = NULL; + conn->in_buffer.size = 0; + conn->in_buffer.index = 0; + /* FIXME: Is this really needed? */ + conn->in_buffer.eof_flag = 0; + } + conn->sec_complete = 0; + conn->data_prot = PROT_CLEAR; + conn->mech = NULL; +} + +#endif /* HAVE_GSSAPI */ + +#endif /* CURL_DISABLE_FTP */ diff --git a/libcurl/src/lib/select.c b/libcurl/src/lib/select.c new file mode 100644 index 0000000..ce9db28 --- /dev/null +++ b/libcurl/src/lib/select.c @@ -0,0 +1,578 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) +#error "We can't compile without select() or poll() support." +#endif + +#if defined(__BEOS__) && !defined(__HAIKU__) +/* BeOS has FD_SET defined in socket.h */ +#include +#endif + +#ifdef MSDOS +#include /* delay() */ +#endif + +#ifdef __VXWORKS__ +#include /* bzero() in FD_SET */ +#endif + +#include + +#include "urldata.h" +#include "connect.h" +#include "select.h" +#include "warnless.h" + +/* Convenience local macros */ + +#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv) + +CURL_STATIC_DEF(int, Curl_ack_eintr, 0); +#define error_not_EINTR (Curl_ack_eintr || error != EINTR) + +/* + * Internal function used for waiting a specific amount of ms + * in Curl_socket_ready() and Curl_poll() when no file descriptor + * is provided to wait on, just being used to delay execution. + * WinSock select() and poll() timeout mechanisms need a valid + * socket descriptor in a not null file descriptor set to work. + * Waiting indefinitely with this function is not allowed, a + * zero or negative timeout value will return immediately. + * Timeout resolution, accuracy, as well as maximum supported + * value is system dependent, neither factor is a citical issue + * for the intended use of this function in the library. + * + * Return values: + * -1 = system call error, invalid timeout value, or interrupted + * 0 = specified timeout has elapsed + */ +CURL_STATIC int Curl_wait_ms(int timeout_ms) +{ +#if !defined(MSDOS) && !defined(USE_WINSOCK) || defined(CURL_WINRT) +#ifndef HAVE_POLL_FINE + struct timeval pending_tv; +#endif + struct timeval initial_tv; + int pending_ms; + int error; +#endif + int r = 0; + + if(!timeout_ms) + return 0; + if(timeout_ms < 0) { + SET_SOCKERRNO(EINVAL); + return -1; + } +#if defined(MSDOS) + delay(timeout_ms); +#elif defined(USE_WINSOCK) && !defined(CURL_WINRT) + Sleep(timeout_ms); +#else + pending_ms = timeout_ms; + initial_tv = curlx_tvnow(); + do { +#if defined(HAVE_POLL_FINE) + r = poll(NULL, 0, pending_ms); +#else + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + r = select(0, NULL, NULL, NULL, &pending_tv); +#endif /* HAVE_POLL_FINE */ + if(r != -1) + break; + error = SOCKERRNO; + if(error && error_not_EINTR) + break; + pending_ms = timeout_ms - elapsed_ms; + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } while(r == -1); +#endif /* USE_WINSOCK */ + if(r) + r = -1; + return r; +} + +/* + * Wait for read or write events on a set of file descriptors. It uses poll() + * when a fine poll() is available, in order to avoid limits with FD_SETSIZE, + * otherwise select() is used. An error is returned if select() is being used + * and a file descriptor is too large for FD_SETSIZE. + * + * A negative timeout value makes this function wait indefinitely, + * unles no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE + * 0 = timeout + * [bitmask] = action as described below + * + * CURL_CSELECT_IN - first socket is readable + * CURL_CSELECT_IN2 - second socket is readable + * CURL_CSELECT_OUT - write socket is writable + * CURL_CSELECT_ERR - an error condition occurred + */ +int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ + curl_socket_t readfd1, + curl_socket_t writefd, /* socket to write to */ + long timeout_ms) /* milliseconds to wait */ +{ +#ifdef HAVE_POLL_FINE + struct pollfd pfd[3]; + int num; +#else + struct timeval pending_tv; + struct timeval *ptimeout; + fd_set fds_read; + fd_set fds_write; + fd_set fds_err; + curl_socket_t maxfd; +#endif + struct timeval initial_tv = {0, 0}; + int pending_ms = 0; + int error; + int r; + int ret; + + if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && + (writefd == CURL_SOCKET_BAD)) { + /* no sockets, just wait */ + r = Curl_wait_ms((int)timeout_ms); + return r; + } + + /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed + time in this function does not need to be measured. This happens + when function is called with a zero timeout or a negative timeout + value indicating a blocking call should be performed. */ + + if(timeout_ms > 0) { + pending_ms = (int)timeout_ms; + initial_tv = curlx_tvnow(); + } + +#ifdef HAVE_POLL_FINE + + num = 0; + if(readfd0 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd0; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd1; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(writefd != CURL_SOCKET_BAD) { + pfd[num].fd = writefd; + pfd[num].events = POLLWRNORM|POLLOUT; + pfd[num].revents = 0; + num++; + } + + do { + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(pfd, num, pending_ms); + if(r != -1) + break; + error = SOCKERRNO; + if(error && error_not_EINTR) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - elapsed_ms); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + ret = 0; + num = 0; + if(readfd0 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN2; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } + if(writefd != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLWRNORM|POLLOUT)) + ret |= CURL_CSELECT_OUT; + if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + } + + return ret; + +#else /* HAVE_POLL_FINE */ + + FD_ZERO(&fds_err); + maxfd = (curl_socket_t)-1; + + FD_ZERO(&fds_read); + if(readfd0 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd0); + FD_SET(readfd0, &fds_read); + FD_SET(readfd0, &fds_err); + maxfd = readfd0; + } + if(readfd1 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd1); + FD_SET(readfd1, &fds_read); + FD_SET(readfd1, &fds_err); + if(readfd1 > maxfd) + maxfd = readfd1; + } + + FD_ZERO(&fds_write); + if(writefd != CURL_SOCKET_BAD) { + VERIFY_SOCK(writefd); + FD_SET(writefd, &fds_write); + FD_SET(writefd, &fds_err); + if(writefd > maxfd) + maxfd = writefd; + } + + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; + + do { + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } + + /* WinSock select() must not be called with an fd_set that contains zero + fd flags, or it will return WSAEINVAL. But, it also can't be called + with no fd_sets at all! From the documentation: + + Any two of the parameters, readfds, writefds, or exceptfds, can be + given as null. At least one must be non-null, and any non-null + descriptor set must contain at least one handle to a socket. + + We know that we have at least one bit set in at least two fd_sets in + this case, but we may have no bits set in either fds_read or fd_write, + so check for that and handle it. Luckily, with WinSock, we can _also_ + ask how many bits are set on an fd_set. + + It is unclear why WinSock doesn't just handle this for us instead of + calling this an error. + + Note also that WinSock ignores the first argument, so we don't worry + about the fact that maxfd is computed incorrectly with WinSock (since + curl_socket_t is unsigned in such cases and thus -1 is the largest + value). + */ + r = select((int)maxfd + 1, +#ifndef USE_WINSOCK + &fds_read, + &fds_write, +#else + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, +#endif + &fds_err, ptimeout); + if(r != -1) + break; + error = SOCKERRNO; + if(error && error_not_EINTR) + break; + if(timeout_ms > 0) { + pending_ms = timeout_ms - elapsed_ms; + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + ret = 0; + if(readfd0 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd0, &fds_read)) + ret |= CURL_CSELECT_IN; + if(FD_ISSET(readfd0, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd1, &fds_read)) + ret |= CURL_CSELECT_IN2; + if(FD_ISSET(readfd1, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(writefd != CURL_SOCKET_BAD) { + if(FD_ISSET(writefd, &fds_write)) + ret |= CURL_CSELECT_OUT; + if(FD_ISSET(writefd, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + + return ret; + +#endif /* HAVE_POLL_FINE */ + +} + +/* + * This is a wrapper around poll(). If poll() does not exist, then + * select() is used instead. An error is returned if select() is + * being used and a file descriptor is too large for FD_SETSIZE. + * A negative timeout value makes this function wait indefinitely, + * unles no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE + * 0 = timeout + * N = number of structures with non zero revent fields + */ +CURL_STATIC int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) +{ +#ifndef HAVE_POLL_FINE + struct timeval pending_tv; + struct timeval *ptimeout; + fd_set fds_read; + fd_set fds_write; + fd_set fds_err; + curl_socket_t maxfd; +#endif + struct timeval initial_tv = {0, 0}; + bool fds_none = TRUE; + unsigned int i; + int pending_ms = 0; + int error; + int r; + + if(ufds) { + for(i = 0; i < nfds; i++) { + if(ufds[i].fd != CURL_SOCKET_BAD) { + fds_none = FALSE; + break; + } + } + } + if(fds_none) { + r = Curl_wait_ms(timeout_ms); + return r; + } + + /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed + time in this function does not need to be measured. This happens + when function is called with a zero timeout or a negative timeout + value indicating a blocking call should be performed. */ + + if(timeout_ms > 0) { + pending_ms = timeout_ms; + initial_tv = curlx_tvnow(); + } + +#ifdef HAVE_POLL_FINE + + do { + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(ufds, nfds, pending_ms); + if(r != -1) + break; + error = SOCKERRNO; + if(error && error_not_EINTR) + break; + if(timeout_ms > 0) { + pending_ms = timeout_ms - elapsed_ms; + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + for(i = 0; i < nfds; i++) { + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + if(ufds[i].revents & POLLHUP) + ufds[i].revents |= POLLIN; + if(ufds[i].revents & POLLERR) + ufds[i].revents |= (POLLIN|POLLOUT); + } + +#else /* HAVE_POLL_FINE */ + + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + FD_ZERO(&fds_err); + maxfd = (curl_socket_t)-1; + + for(i = 0; i < nfds; i++) { + ufds[i].revents = 0; + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + VERIFY_SOCK(ufds[i].fd); + if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI| + POLLRDNORM|POLLWRNORM|POLLRDBAND)) { + if(ufds[i].fd > maxfd) + maxfd = ufds[i].fd; + if(ufds[i].events & (POLLRDNORM|POLLIN)) + FD_SET(ufds[i].fd, &fds_read); + if(ufds[i].events & (POLLWRNORM|POLLOUT)) + FD_SET(ufds[i].fd, &fds_write); + if(ufds[i].events & (POLLRDBAND|POLLPRI)) + FD_SET(ufds[i].fd, &fds_err); + } + } + +#ifdef USE_WINSOCK + /* WinSock select() can't handle zero events. See the comment about this in + Curl_check_socket(). */ + if(fds_read.fd_count == 0 && fds_write.fd_count == 0 + && fds_err.fd_count == 0) { + r = Curl_wait_ms(timeout_ms); + return r; + } +#endif + + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; + + do { + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } + r = select((int)maxfd + 1, +#ifndef USE_WINSOCK + &fds_read, &fds_write, &fds_err, +#else + /* WinSock select() can't handle fd_sets with zero bits set, so + don't give it such arguments. See the comment about this in + Curl_check_socket(). + */ + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + fds_err.fd_count ? &fds_err : NULL, +#endif + ptimeout); + if(r != -1) + break; + error = SOCKERRNO; + if(error && error_not_EINTR) + break; + if(timeout_ms > 0) { + pending_ms = timeout_ms - elapsed_ms; + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + r = 0; + for(i = 0; i < nfds; i++) { + ufds[i].revents = 0; + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + if(FD_ISSET(ufds[i].fd, &fds_read)) + ufds[i].revents |= POLLIN; + if(FD_ISSET(ufds[i].fd, &fds_write)) + ufds[i].revents |= POLLOUT; + if(FD_ISSET(ufds[i].fd, &fds_err)) + ufds[i].revents |= POLLPRI; + if(ufds[i].revents != 0) + r++; + } + +#endif /* HAVE_POLL_FINE */ + + return r; +} + +#ifdef TPF +/* + * This is a replacement for select() on the TPF platform. + * It is used whenever libcurl calls select(). + * The call below to tpf_process_signals() is required because + * TPF's select calls are not signal interruptible. + * + * Return values are the same as select's. + */ +int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, + fd_set* excepts, struct timeval* tv) +{ + int rc; + + rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv); + tpf_process_signals(); + return rc; +} +#endif /* TPF */ diff --git a/libcurl/src/lib/select.h b/libcurl/src/lib/select.h new file mode 100644 index 0000000..903c14a --- /dev/null +++ b/libcurl/src/lib/select.h @@ -0,0 +1,114 @@ +#ifndef HEADER_CURL_SELECT_H +#define HEADER_CURL_SELECT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_POLL_H +#include +#elif defined(HAVE_POLL_H) +#include +#endif + +/* + * Definition of pollfd struct and constants for platforms lacking them. + */ + +#if !defined(HAVE_STRUCT_POLLFD) && \ + !defined(HAVE_SYS_POLL_H) && \ + !defined(HAVE_POLL_H) + +#define POLLIN 0x01 +#define POLLPRI 0x02 +#define POLLOUT 0x04 +#define POLLERR 0x08 +#define POLLHUP 0x10 +#define POLLNVAL 0x20 + +struct pollfd +{ + curl_socket_t fd; + short events; + short revents; +}; + +#endif + +#ifndef POLLRDNORM +#define POLLRDNORM POLLIN +#endif + +#ifndef POLLWRNORM +#define POLLWRNORM POLLOUT +#endif + +#ifndef POLLRDBAND +#define POLLRDBAND POLLPRI +#endif + +/* there are three CSELECT defines that are defined in the public header that + are exposed to users, but this *IN2 bit is only ever used internally and + therefore defined here */ +#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1) + +CURL_STATIC int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, + curl_socket_t writefd, + long timeout_ms); + +/* provide the former API internally */ +#define Curl_socket_ready(x,y,z) \ + Curl_socket_check(x, CURL_SOCKET_BAD, y, z) + +CURL_STATIC int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); + +/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set, + * EINTR condition is honored and function might exit early without + * awaiting full timeout. Otherwise EINTR will be ignored and full + * timeout will elapse. */ +CURL_STATIC_DECL(int, Curl_ack_eintr, 0); + +CURL_STATIC int Curl_wait_ms(int timeout_ms); + +#ifdef TPF +int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, + fd_set* excepts, struct timeval* tv); +#endif + +/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which + unfortunately makes it impossible for us to easily check if they're valid +*/ +#if defined(USE_WINSOCK) || defined(TPF) +#define VALID_SOCK(x) 1 +#define VERIFY_SOCK(x) Curl_nop_stmt +#else +#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) +#define VERIFY_SOCK(x) do { \ + if(!VALID_SOCK(x)) { \ + SET_SOCKERRNO(EINVAL); \ + return -1; \ + } \ +} WHILE_FALSE +#endif + +#endif /* HEADER_CURL_SELECT_H */ + diff --git a/libcurl/src/lib/sendf.c b/libcurl/src/lib/sendf.c new file mode 100644 index 0000000..854606b --- /dev/null +++ b/libcurl/src/lib/sendf.c @@ -0,0 +1,710 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "vtls/vtls.h" +#include "ssh.h" +#include "multiif.h" +#include "non-ascii.h" +#include "curl_printf.h" +#include "strerror.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef CURL_DO_LINEEND_CONV +/* + * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF + * (\n), with special processing for CRLF sequences that are split between two + * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new + * size of the data is returned. + */ +static size_t convert_lineends(struct SessionHandle *data, + char *startPtr, size_t size) +{ + char *inPtr, *outPtr; + + /* sanity check */ + if((startPtr == NULL) || (size < 1)) { + return size; + } + + if(data->state.prev_block_had_trailing_cr) { + /* The previous block of incoming data + had a trailing CR, which was turned into a LF. */ + if(*startPtr == '\n') { + /* This block of incoming data starts with the + previous block's LF so get rid of it */ + memmove(startPtr, startPtr+1, size-1); + size--; + /* and it wasn't a bare CR but a CRLF conversion instead */ + data->state.crlf_conversions++; + } + data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */ + } + + /* find 1st CR, if any */ + inPtr = outPtr = memchr(startPtr, '\r', size); + if(inPtr) { + /* at least one CR, now look for CRLF */ + while(inPtr < (startPtr+size-1)) { + /* note that it's size-1, so we'll never look past the last byte */ + if(memcmp(inPtr, "\r\n", 2) == 0) { + /* CRLF found, bump past the CR and copy the NL */ + inPtr++; + *outPtr = *inPtr; + /* keep track of how many CRLFs we converted */ + data->state.crlf_conversions++; + } + else { + if(*inPtr == '\r') { + /* lone CR, move LF instead */ + *outPtr = '\n'; + } + else { + /* not a CRLF nor a CR, just copy whatever it is */ + *outPtr = *inPtr; + } + } + outPtr++; + inPtr++; + } /* end of while loop */ + + if(inPtr < startPtr+size) { + /* handle last byte */ + if(*inPtr == '\r') { + /* deal with a CR at the end of the buffer */ + *outPtr = '\n'; /* copy a NL instead */ + /* note that a CRLF might be split across two blocks */ + data->state.prev_block_had_trailing_cr = TRUE; + } + else { + /* copy last byte */ + *outPtr = *inPtr; + } + outPtr++; + } + if(outPtr < startPtr+size) + /* tidy up by null terminating the now shorter data */ + *outPtr = '\0'; + + return (outPtr - startPtr); + } + return size; +} +#endif /* CURL_DO_LINEEND_CONV */ + +/* Curl_infof() is for info message along the way */ + +CURL_STATIC void Curl_infof(struct SessionHandle *data, const char *fmt, ...) +{ + if(data && data->set.verbose) { + va_list ap; + size_t len; + char print_buffer[2048 + 1]; + va_start(ap, fmt); + vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap); + va_end(ap); + len = strlen(print_buffer); + Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL); + } +} + +/* Curl_failf() is for messages stating why we failed. + * The message SHALL NOT include any LF or CR. + */ + +CURL_STATIC void Curl_failf(struct SessionHandle *data, const char *fmt, ...) +{ + va_list ap; + size_t len; + va_start(ap, fmt); + + vsnprintf(data->state.buffer, BUFSIZE, fmt, ap); + + if(data->set.errorbuffer && !data->state.errorbuf) { + snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer); + data->state.errorbuf = TRUE; /* wrote error string */ + } + if(data->set.verbose) { + len = strlen(data->state.buffer); + if(len < BUFSIZE - 1) { + data->state.buffer[len] = '\n'; + data->state.buffer[++len] = '\0'; + } + Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL); + } + + va_end(ap); +} + +/* Curl_sendf() sends formated data to the server */ +CURL_STATIC CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, + const char *fmt, ...) +{ + struct SessionHandle *data = conn->data; + ssize_t bytes_written; + size_t write_len; + CURLcode result = CURLE_OK; + char *s; + char *sptr; + va_list ap; + va_start(ap, fmt); + s = vaprintf(fmt, ap); /* returns an allocated string */ + va_end(ap); + if(!s) + return CURLE_OUT_OF_MEMORY; /* failure */ + + bytes_written=0; + write_len = strlen(s); + sptr = s; + + for(;;) { + /* Write the buffer to the socket */ + result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); + + if(result) + break; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn); + + if((size_t)bytes_written != write_len) { + /* if not all was written at once, we must advance the pointer, decrease + the size left and try again! */ + write_len -= bytes_written; + sptr += bytes_written; + } + else + break; + } + + free(s); /* free the output string */ + + return result; +} + +/* + * Curl_write() is an internal write function that sends data to the + * server. Works with plain sockets, SCP, SSL or kerberos. + * + * If the write would block (CURLE_AGAIN), we return CURLE_OK and + * (*written == 0). Otherwise we return regular CURLcode value. + */ +CURL_STATIC CURLcode Curl_write(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, + size_t len, + ssize_t *written) +{ + ssize_t bytes_written; + CURLcode result = CURLE_OK; + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + bytes_written = conn->send[num](conn, num, mem, len, &result); + + *written = bytes_written; + if(bytes_written >= 0) + /* we completely ignore the curlcode value when subzero is not returned */ + return CURLE_OK; + + /* handle CURLE_AGAIN or a send failure */ + switch(result) { + case CURLE_AGAIN: + *written = 0; + return CURLE_OK; + + case CURLE_OK: + /* general send failure */ + return CURLE_SEND_ERROR; + + default: + /* we got a specific curlcode, forward it */ + return result; + } +} + +CURL_STATIC ssize_t Curl_send_plain(struct connectdata *conn, int num, + const void *mem, size_t len, CURLcode *code) +{ + curl_socket_t sockfd = conn->sock[num]; + ssize_t bytes_written = swrite(sockfd, mem, len); + + *code = CURLE_OK; + if(-1 == bytes_written) { + int err = SOCKERRNO; + + if( +#ifdef WSAEWOULDBLOCK + /* This is how Windows does it */ + (WSAEWOULDBLOCK == err) +#else + /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned + due to its inability to send off data without blocking. We therefor + treat both error codes the same here */ + (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) +#endif + ) { + /* this is just a case of EWOULDBLOCK */ + bytes_written=0; + *code = CURLE_AGAIN; + } + else { + failf(conn->data, "Send failure: %s", + Curl_strerror(conn, err)); + conn->data->state.os_errno = err; + *code = CURLE_SEND_ERROR; + } + } + return bytes_written; +} + +/* + * Curl_write_plain() is an internal write function that sends data to the + * server using plain sockets only. Otherwise meant to have the exact same + * proto as Curl_write() + */ +CURL_STATIC CURLcode Curl_write_plain(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, + size_t len, + ssize_t *written) +{ + ssize_t bytes_written; + CURLcode result; + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + bytes_written = Curl_send_plain(conn, num, mem, len, &result); + + *written = bytes_written; + + return result; +} + +CURL_STATIC ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, + size_t len, CURLcode *code) +{ + curl_socket_t sockfd = conn->sock[num]; + ssize_t nread = sread(sockfd, buf, len); + + *code = CURLE_OK; + if(-1 == nread) { + int err = SOCKERRNO; + + if( +#ifdef WSAEWOULDBLOCK + /* This is how Windows does it */ + (WSAEWOULDBLOCK == err) +#else + /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned + due to its inability to send off data without blocking. We therefor + treat both error codes the same here */ + (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) +#endif + ) { + /* this is just a case of EWOULDBLOCK */ + *code = CURLE_AGAIN; + } + else { + failf(conn->data, "Recv failure: %s", + Curl_strerror(conn, err)); + conn->data->state.os_errno = err; + *code = CURLE_RECV_ERROR; + } + } + return nread; +} + +static CURLcode pausewrite(struct SessionHandle *data, + int type, /* what type of data */ + const char *ptr, + size_t len) +{ + /* signalled to pause sending on this connection, but since we have data + we want to send we need to dup it to save a copy for when the sending + is again enabled */ + struct SingleRequest *k = &data->req; + char *dupl = malloc(len); + if(!dupl) + return CURLE_OUT_OF_MEMORY; + + memcpy(dupl, ptr, len); + + /* store this information in the state struct for later use */ + data->state.tempwrite = dupl; + data->state.tempwritesize = len; + data->state.tempwritetype = type; + + /* mark the connection as RECV paused */ + k->keepon |= KEEP_RECV_PAUSE; + + DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n", + len, type)); + + return CURLE_OK; +} + + +/* Curl_client_chop_write() writes chunks of data not larger than + * CURL_MAX_WRITE_SIZE via client write callback(s) and + * takes care of pause requests from the callbacks. + */ +CURL_STATIC CURLcode Curl_client_chop_write(struct connectdata *conn, + int type, + char * ptr, + size_t len) +{ + struct SessionHandle *data = conn->data; + curl_write_callback writeheader = NULL; + curl_write_callback writebody = NULL; + + if (!len) + return CURLE_OK; + + /* If reading is actually paused, we're forced to append this chunk of data + to the already held data, but only if it is the same type as otherwise it + can't work and it'll return error instead. */ + if(data->req.keepon & KEEP_RECV_PAUSE) { + size_t newlen; + char *newptr; + if(type != data->state.tempwritetype) + /* major internal confusion */ + return CURLE_RECV_ERROR; + + DEBUGASSERT(data->state.tempwrite); + + /* figure out the new size of the data to save */ + newlen = len + data->state.tempwritesize; + /* allocate the new memory area */ + newptr = realloc(data->state.tempwrite, newlen); + if(!newptr) + return CURLE_OUT_OF_MEMORY; + /* copy the new data to the end of the new area */ + memcpy(newptr + data->state.tempwritesize, ptr, len); + /* update the pointer and the size */ + data->state.tempwrite = newptr; + data->state.tempwritesize = newlen; + return CURLE_OK; + } + + /* Determine the callback(s) to use. */ + if(type & CLIENTWRITE_BODY) + writebody = data->set.fwrite_func; + if((type & CLIENTWRITE_HEADER) && + (data->set.fwrite_header || data->set.writeheader)) { + /* + * Write headers to the same callback or to the especially setup + * header callback function (added after version 7.7.1). + */ + writeheader = + data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; + } + + /* Chop data, write chunks. */ + while(len) { + size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE; + + if(writebody) { + size_t wrote = writebody(ptr, 1, chunklen, data->set.out); + + if(CURL_WRITEFUNC_PAUSE == wrote) { + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* Protocols that work without network cannot be paused. This is + actually only FILE:// just now, and it can't pause since the + transfer isn't done using the "normal" procedure. */ + failf(data, "Write callback asked for PAUSE when not supported!"); + return CURLE_WRITE_ERROR; + } + else + return pausewrite(data, type, ptr, len); + } + else if(wrote != chunklen) { + failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen); + return CURLE_WRITE_ERROR; + } + } + + if(writeheader) { + size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader); + + if(CURL_WRITEFUNC_PAUSE == wrote) + /* here we pass in the HEADER bit only since if this was body as well + then it was passed already and clearly that didn't trigger the + pause, so this is saved for later with the HEADER bit only */ + return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); + + if(wrote != chunklen) { + failf (data, "Failed writing header"); + return CURLE_WRITE_ERROR; + } + } + + ptr += chunklen; + len -= chunklen; + } + + return CURLE_OK; +} + + +/* Curl_client_write() sends data to the write callback(s) + + The bit pattern defines to what "streams" to write to. Body and/or header. + The defines are in sendf.h of course. + + If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the + local character encoding. This is a problem and should be changed in + the future to leave the original data alone. + */ +CURL_STATIC CURLcode Curl_client_write(struct connectdata *conn, + int type, + char *ptr, + size_t len) +{ + struct SessionHandle *data = conn->data; + + if(0 == len) + len = strlen(ptr); + + /* FTP data may need conversion. */ + if((type & CLIENTWRITE_BODY) && + (conn->handler->protocol & PROTO_FAMILY_FTP) && + conn->proto.ftpc.transfertype == 'A') { + /* convert from the network encoding */ + CURLcode result = Curl_convert_from_network(data, ptr, len); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + +#ifdef CURL_DO_LINEEND_CONV + /* convert end-of-line markers */ + len = convert_lineends(data, ptr, len); +#endif /* CURL_DO_LINEEND_CONV */ + } + + return Curl_client_chop_write(conn, type, ptr, len); +} + +CURL_STATIC CURLcode Curl_read_plain(curl_socket_t sockfd, + char *buf, + size_t bytesfromsocket, + ssize_t *n) +{ + ssize_t nread = sread(sockfd, buf, bytesfromsocket); + + if(-1 == nread) { + int err = SOCKERRNO; +#ifdef USE_WINSOCK + if(WSAEWOULDBLOCK == err) +#else + if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)) +#endif + return CURLE_AGAIN; + else + return CURLE_RECV_ERROR; + } + + /* we only return number of bytes read when we return OK */ + *n = nread; + return CURLE_OK; +} + +/* + * Internal read-from-socket function. This is meant to deal with plain + * sockets, SSL sockets and kerberos sockets. + * + * Returns a regular CURLcode value. + */ +CURLcode Curl_read(struct connectdata *conn, /* connection data */ + curl_socket_t sockfd, /* read from this socket */ + char *buf, /* store read data here */ + size_t sizerequested, /* max amount to read */ + ssize_t *n) /* amount bytes read */ +{ + CURLcode result = CURLE_RECV_ERROR; + ssize_t nread = 0; + size_t bytesfromsocket = 0; + char *buffertofill = NULL; + bool pipelining = Curl_multi_pipeline_enabled(conn->data->multi); + + /* Set 'num' to 0 or 1, depending on which socket that has been sent here. + If it is the second socket, we set num to 1. Otherwise to 0. This lets + us use the correct ssl handle. */ + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + *n=0; /* reset amount to zero */ + + /* If session can pipeline, check connection buffer */ + if(pipelining) { + size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos, + sizerequested); + + /* Copy from our master buffer first if we have some unread data there*/ + if(bytestocopy > 0) { + memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy); + conn->read_pos += bytestocopy; + conn->bits.stream_was_rewound = FALSE; + + *n = (ssize_t)bytestocopy; + return CURLE_OK; + } + /* If we come here, it means that there is no data to read from the buffer, + * so we read from the socket */ + bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char)); + buffertofill = conn->master_buffer; + } + else { + bytesfromsocket = CURLMIN((long)sizerequested, + conn->data->set.buffer_size ? + conn->data->set.buffer_size : BUFSIZE); + buffertofill = buf; + } + + nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result); + if(nread < 0) + return result; + + if(pipelining) { + memcpy(buf, conn->master_buffer, nread); + conn->buf_len = nread; + conn->read_pos = nread; + } + + *n += nread; + + return CURLE_OK; +} + +/* return 0 on success */ +static int showit(struct SessionHandle *data, curl_infotype type, + char *ptr, size_t size) +{ + static const char s_infotype[CURLINFO_END][3] = { + "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; + +#ifdef CURL_DOES_CONVERSIONS + char buf[BUFSIZE+1]; + size_t conv_size = 0; + + switch(type) { + case CURLINFO_HEADER_OUT: + /* assume output headers are ASCII */ + /* copy the data into my buffer so the original is unchanged */ + if(size > BUFSIZE) { + size = BUFSIZE; /* truncate if necessary */ + buf[BUFSIZE] = '\0'; + } + conv_size = size; + memcpy(buf, ptr, size); + /* Special processing is needed for this block if it + * contains both headers and data (separated by CRLFCRLF). + * We want to convert just the headers, leaving the data as-is. + */ + if(size > 4) { + size_t i; + for(i = 0; i < size-4; i++) { + if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) { + /* convert everything through this CRLFCRLF but no further */ + conv_size = i + 4; + break; + } + } + } + + Curl_convert_from_network(data, buf, conv_size); + /* Curl_convert_from_network calls failf if unsuccessful */ + /* we might as well continue even if it fails... */ + ptr = buf; /* switch pointer to use my buffer instead */ + break; + default: + /* leave everything else as-is */ + break; + } +#endif /* CURL_DOES_CONVERSIONS */ + + if(data->set.fdebug) + return (*data->set.fdebug)(data, type, ptr, size, + data->set.debugdata); + + switch(type) { + case CURLINFO_TEXT: + case CURLINFO_HEADER_OUT: + case CURLINFO_HEADER_IN: + fwrite(s_infotype[type], 2, 1, data->set.err); + fwrite(ptr, size, 1, data->set.err); +#ifdef CURL_DOES_CONVERSIONS + if(size != conv_size) { + /* we had untranslated data so we need an explicit newline */ + fwrite("\n", 1, 1, data->set.err); + } +#endif + break; + default: /* nada */ + break; + } + return 0; +} + +CURL_STATIC int Curl_debug(struct SessionHandle *data, curl_infotype type, + char *ptr, size_t size, + struct connectdata *conn) +{ + int rc; + if(data->set.printhost && conn && conn->host.dispname) { + char buffer[160]; + const char *t=NULL; + const char *w="Data"; + switch (type) { + case CURLINFO_HEADER_IN: + w = "Header"; + /* FALLTHROUGH */ + case CURLINFO_DATA_IN: + t = "from"; + break; + case CURLINFO_HEADER_OUT: + w = "Header"; + /* FALLTHROUGH */ + case CURLINFO_DATA_OUT: + t = "to"; + break; + default: + break; + } + + if(t) { + snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t, + conn->host.dispname); + rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer)); + if(rc) + return rc; + } + } + rc = showit(data, type, ptr, size); + return rc; +} diff --git a/libcurl/src/lib/sendf.h b/libcurl/src/lib/sendf.h new file mode 100644 index 0000000..f5f03c2 --- /dev/null +++ b/libcurl/src/lib/sendf.h @@ -0,0 +1,93 @@ +#ifndef HEADER_CURL_SENDF_H +#define HEADER_CURL_SENDF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +CURL_STATIC CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *, + const char *fmt, ...); +CURL_STATIC void Curl_infof(struct SessionHandle *, const char *fmt, ...); +CURL_STATIC void Curl_failf(struct SessionHandle *, const char *fmt, ...); + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + +#if defined(HAVE_VARIADIC_MACROS_C99) +#define infof(...) Curl_nop_stmt +#elif defined(HAVE_VARIADIC_MACROS_GCC) +#define infof(x...) Curl_nop_stmt +#else +#define infof (void) +#endif + +#else /* CURL_DISABLE_VERBOSE_STRINGS */ + +#define infof Curl_infof + +#endif /* CURL_DISABLE_VERBOSE_STRINGS */ + +#define failf Curl_failf + +#define CLIENTWRITE_BODY (1<<0) +#define CLIENTWRITE_HEADER (1<<1) +#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) + +CURL_STATIC CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr, + size_t len) WARN_UNUSED_RESULT; + +CURL_STATIC CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, + size_t len) WARN_UNUSED_RESULT; + +/* internal read-function, does plain socket only */ +CURL_STATIC CURLcode Curl_read_plain(curl_socket_t sockfd, + char *buf, + size_t bytesfromsocket, + ssize_t *n); + +CURL_STATIC ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, + size_t len, CURLcode *code); +CURL_STATIC ssize_t Curl_send_plain(struct connectdata *conn, int num, + const void *mem, size_t len, CURLcode *code); + +/* internal read-function, does plain socket, SSL and krb4 */ +CURL_STATIC CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd, + char *buf, size_t buffersize, + ssize_t *n); +/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */ +CURL_STATIC CURLcode Curl_write(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, size_t len, + ssize_t *written); + +/* internal write-function, does plain sockets ONLY */ +CURL_STATIC CURLcode Curl_write_plain(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, size_t len, + ssize_t *written); + +/* the function used to output verbose information */ +CURL_STATIC int Curl_debug(struct SessionHandle *handle, curl_infotype type, + char *data, size_t size, + struct connectdata *conn); + + +#endif /* HEADER_CURL_SENDF_H */ diff --git a/libcurl/src/lib/setup-os400.h b/libcurl/src/lib/setup-os400.h new file mode 100644 index 0000000..6d4c507 --- /dev/null +++ b/libcurl/src/lib/setup-os400.h @@ -0,0 +1,223 @@ +#ifndef HEADER_CURL_SETUP_OS400_H +#define HEADER_CURL_SETUP_OS400_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* OS/400 netdb.h does not define NI_MAXHOST. */ +#define NI_MAXHOST 1025 + +/* OS/400 netdb.h does not define NI_MAXSERV. */ +#define NI_MAXSERV 32 + +/* No OS/400 header file defines u_int32_t. */ +typedef unsigned long u_int32_t; + + +/* System API wrapper prototypes & definitions to support ASCII parameters. */ + +#include +#include +#include +#include +#include + +extern CURL_STATIC int Curl_getaddrinfo_a(const char * nodename, + const char * servname, + const struct addrinfo * hints, + struct addrinfo * * res); +#define getaddrinfo Curl_getaddrinfo_a + + +extern CURL_STATIC int Curl_getnameinfo_a(const struct sockaddr * sa, + curl_socklen_t salen, + char * nodename, curl_socklen_t nodenamelen, + char * servname, curl_socklen_t servnamelen, + int flags); +#define getnameinfo Curl_getnameinfo_a + + +/* GSKit wrappers. */ + +extern CURL_STATIC int Curl_gsk_environment_open(gsk_handle * my_env_handle); +#define gsk_environment_open Curl_gsk_environment_open + +extern CURL_STATIC int Curl_gsk_secure_soc_open(gsk_handle my_env_handle, + gsk_handle * my_session_handle); +#define gsk_secure_soc_open Curl_gsk_secure_soc_open + +extern CURL_STATIC int Curl_gsk_environment_close(gsk_handle * my_env_handle); +#define gsk_environment_close Curl_gsk_environment_close + +extern CURL_STATIC int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle); +#define gsk_secure_soc_close Curl_gsk_secure_soc_close + +extern CURL_STATIC int Curl_gsk_environment_init(gsk_handle my_env_handle); +#define gsk_environment_init Curl_gsk_environment_init + +extern CURL_STATIC int Curl_gsk_secure_soc_init(gsk_handle my_session_handle); +#define gsk_secure_soc_init Curl_gsk_secure_soc_init + +extern CURL_STATIC int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, + GSK_BUF_ID bufID, + const char * buffer, + int bufSize); +#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a + +extern CURL_STATIC int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, + GSK_ENUM_ID enumID, + GSK_ENUM_VALUE enumValue); +#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum + +extern CURL_STATIC int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, + int numValue); +#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value + +extern CURL_STATIC int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle, + GSK_CALLBACK_ID callBackID, + void * callBackAreaPtr); +#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback + +extern CURL_STATIC int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, + GSK_BUF_ID bufID, + const char * * buffer, + int * bufSize); +#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a + +extern CURL_STATIC int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, + GSK_ENUM_ID enumID, + GSK_ENUM_VALUE * enumValue); +#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum + +extern CURL_STATIC int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, + int * numValue); +#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value + +extern CURL_STATIC int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle, + GSK_CERT_ID certID, + const gsk_cert_data_elem * * certDataElem, + int * certDataElementCount); +#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info + +extern CURL_STATIC int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, + GSK_MISC_ID miscID); +#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc + +extern CURL_STATIC int Curl_gsk_secure_soc_read(gsk_handle my_session_handle, + char * readBuffer, + int readBufSize, int * amtRead); +#define gsk_secure_soc_read Curl_gsk_secure_soc_read + +extern CURL_STATIC int Curl_gsk_secure_soc_write(gsk_handle my_session_handle, + char * writeBuffer, + int writeBufSize, int * amtWritten); +#define gsk_secure_soc_write Curl_gsk_secure_soc_write + +extern CURL_STATIC const char * Curl_gsk_strerror_a(int gsk_return_value); +#define gsk_strerror Curl_gsk_strerror_a + +extern CURL_STATIC int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle, + int IOCompletionPort, + Qso_OverlappedIO_t * communicationsArea); +#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit + + +/* GSSAPI wrappers. */ + +extern CURL_STATIC OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status, + gss_buffer_t in_name, + gss_OID in_name_type, + gss_name_t * out_name); +#define gss_import_name Curl_gss_import_name_a + + +extern CURL_STATIC OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status, + OM_uint32 status_value, + int status_type, gss_OID mech_type, + gss_msg_ctx_t * message_context, + gss_buffer_t status_string); +#define gss_display_status Curl_gss_display_status_a + + +extern CURL_STATIC OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status, + gss_cred_id_t cred_handle, + gss_ctx_id_t * context_handle, + gss_name_t target_name, + gss_OID mech_type, + gss_flags_t req_flags, + OM_uint32 time_req, + gss_channel_bindings_t + input_chan_bindings, + gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + gss_flags_t * ret_flags, + OM_uint32 * time_rec); +#define gss_init_sec_context Curl_gss_init_sec_context_a + + +extern CURL_STATIC OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token); +#define gss_delete_sec_context Curl_gss_delete_sec_context_a + + +/* LDAP wrappers. */ + +#define BerValue struct berval + +#define ldap_url_parse ldap_url_parse_utf8 +#define ldap_init Curl_ldap_init_a +#define ldap_simple_bind_s Curl_ldap_simple_bind_s_a +#define ldap_search_s Curl_ldap_search_s_a +#define ldap_get_values_len Curl_ldap_get_values_len_a +#define ldap_err2string Curl_ldap_err2string_a +#define ldap_get_dn Curl_ldap_get_dn_a +#define ldap_first_attribute Curl_ldap_first_attribute_a +#define ldap_next_attribute Curl_ldap_next_attribute_a + +/* Some socket functions must be wrapped to process textual addresses + like AF_UNIX. */ + +extern CURL_STATIC int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen); +extern CURL_STATIC int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen); +extern CURL_STATIC int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags, + struct sockaddr * dstaddr, int addrlen); +extern CURL_STATIC int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags, + struct sockaddr * fromaddr, int * addrlen); + +#define connect Curl_os400_connect +#define bind Curl_os400_bind +#define sendto Curl_os400_sendto +#define recvfrom Curl_os400_recvfrom + +#ifdef HAVE_LIBZ +#define zlibVersion Curl_os400_zlibVersion +#define inflateInit_ Curl_os400_inflateInit_ +#define inflateInit2_ Curl_os400_inflateInit2_ +#define inflate Curl_os400_inflate +#define inflateEnd Curl_os400_inflateEnd +#endif + +#endif /* HEADER_CURL_SETUP_OS400_H */ diff --git a/libcurl/src/lib/setup-vms.h b/libcurl/src/lib/setup-vms.h new file mode 100644 index 0000000..f6179a4 --- /dev/null +++ b/libcurl/src/lib/setup-vms.h @@ -0,0 +1,430 @@ +#ifndef HEADER_CURL_SETUP_VMS_H +#define HEADER_CURL_SETUP_VMS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* */ +/* JEM, 12/30/12, VMS now generates config.h, so only define wrappers for */ +/* getenv(), getpwuid() and provide is_vms_shell() */ +/* Also need upper case symbols for system services, and */ +/* OpenSSL, and some Kerberos image */ + +#ifdef __DECC +#pragma message save +#pragma message disable dollarid +#endif + +/* Hide the stuff we are overriding */ +#define getenv decc_getenv +#ifdef __DECC +# if __INITIAL_POINTER_SIZE != 64 +# define getpwuid decc_getpwuid +# endif +#endif +#include + char * decc$getenv(const char * __name); +#include + +#include +#include + +#undef getenv +#undef getpwuid +#define getenv vms_getenv +#define getpwuid vms_getpwuid + +/* VAX needs these in upper case when compiling exact case */ +#define sys$assign SYS$ASSIGN +#define sys$dassgn SYS$DASSGN +#define sys$qiow SYS$QIOW + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __save +# endif +#endif + +#if __USE_LONG_GID_T +# define decc_getpwuid DECC$__LONG_GID_GETPWUID +#else +# if __INITIAL_POINTER_SIZE +# define decc_getpwuid decc$__32_getpwuid +# else +# define decc_getpwuid decc$getpwuid +# endif +#endif + + struct passwd * decc_getpwuid(uid_t uid); + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE == 32 +/* Translate the path, but only if the path is a VMS file specification */ +/* The translation is usually only needed for older versions of VMS */ +static char * vms_translate_path(const char * path) { +char * unix_path; +char * test_str; + + /* See if the result is in VMS format, if not, we are done */ + /* Assume that this is a PATH, not just some data */ + test_str = strpbrk(path, ":[<^"); + if(test_str == NULL) { + return (char *)path; + } + + unix_path = decc$translate_vms(path); + + if((int)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return (char *)path; + } +} +# else + /* VMS translate path is actually not needed on the current 64 bit */ + /* VMS platforms, so instead of figuring out the pointer settings */ + /* Change it to a noop */ +# define vms_translate_path(__path) __path +# endif +#endif + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __restore +# endif +#endif + +static char * vms_getenv(const char * envvar) { + +char * result; +char * vms_path; + + /* first use the DECC getenv() function */ + result = decc$getenv(envvar); + if(result == NULL) { + return result; + } + + vms_path = result; + result = vms_translate_path(vms_path); + + /* note that if you backport this to use VAX C RTL, that the VAX C RTL */ + /* may do a malloc(2048) for each call to getenv(), so you will need */ + /* to add a free(vms_path) */ + /* Do not do a free() for DEC C RTL builds, which should be used for */ + /* VMS 5.5-2 and later, even if using GCC */ + + return result; +} + + +static struct passwd vms_passwd_cache; + +static struct passwd * vms_getpwuid(uid_t uid) { + +struct passwd * my_passwd; + +/* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */ +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +__char_ptr32 unix_path; +# else +char * unix_path; +# endif +#else +char * unix_path; +#endif + + my_passwd = decc_getpwuid(uid); + if(my_passwd == NULL) { + return my_passwd; + } + + unix_path = vms_translate_path(my_passwd->pw_dir); + + if((long)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return my_passwd; + } + + /* If no changes needed just return it */ + if(unix_path == my_passwd->pw_dir) { + return my_passwd; + } + + /* Need to copy the structure returned */ + /* Since curl is only using pw_dir, no need to fix up * + /* the pw_shell when running under Bash */ + vms_passwd_cache.pw_name = my_passwd->pw_name; + vms_passwd_cache.pw_uid = my_passwd->pw_uid; + vms_passwd_cache.pw_gid = my_passwd->pw_uid; + vms_passwd_cache.pw_dir = unix_path; + vms_passwd_cache.pw_shell = my_passwd->pw_shell; + + return &vms_passwd_cache; +} + +#ifdef __DECC +#pragma message restore +#endif + +/* Bug - VMS OpenSSL and Kerberos universal symbols are in uppercase only */ +/* VMS libraries should have universal symbols in exact and uppercase */ + +#define ASN1_INTEGER_get ASN1_INTEGER_GET +#define ASN1_STRING_data ASN1_STRING_DATA +#define ASN1_STRING_length ASN1_STRING_LENGTH +#define ASN1_STRING_print ASN1_STRING_PRINT +#define ASN1_STRING_to_UTF8 ASN1_STRING_TO_UTF8 +#define ASN1_STRING_type ASN1_STRING_TYPE +#define BIO_ctrl BIO_CTRL +#define BIO_free BIO_FREE +#define BIO_new BIO_NEW +#define BIO_s_mem BIO_S_MEM +#define BN_bn2bin BN_BN2BIN +#define BN_num_bits BN_NUM_BITS +#define CRYPTO_cleanup_all_ex_data CRYPTO_CLEANUP_ALL_EX_DATA +#define CRYPTO_free CRYPTO_FREE +#define CRYPTO_malloc CRYPTO_MALLOC +#define CONF_modules_load_file CONF_MODULES_LOAD_FILE +#ifdef __VAX +# ifdef VMS_OLD_SSL + /* Ancient OpenSSL on VAX/VMS missing this constant */ +# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +# undef CONF_modules_load_file + static int CONF_modules_load_file(const char *filename, + const char *appname, + unsigned long flags) { + return 1; + } +# endif +#endif +#define DES_ecb_encrypt DES_ECB_ENCRYPT +#define DES_set_key DES_SET_KEY +#define DES_set_odd_parity DES_SET_ODD_PARITY +#define ENGINE_ctrl ENGINE_CTRL +#define ENGINE_ctrl_cmd ENGINE_CTRL_CMD +#define ENGINE_finish ENGINE_FINISH +#define ENGINE_free ENGINE_FREE +#define ENGINE_get_first ENGINE_GET_FIRST +#define ENGINE_get_id ENGINE_GET_ID +#define ENGINE_get_next ENGINE_GET_NEXT +#define ENGINE_init ENGINE_INIT +#define ENGINE_load_builtin_engines ENGINE_LOAD_BUILTIN_ENGINES +#define ENGINE_load_private_key ENGINE_LOAD_PRIVATE_KEY +#define ENGINE_set_default ENGINE_SET_DEFAULT +#define ERR_clear_error ERR_CLEAR_ERROR +#define ERR_error_string ERR_ERROR_STRING +#define ERR_error_string_n ERR_ERROR_STRING_N +#define ERR_free_strings ERR_FREE_STRINGS +#define ERR_get_error ERR_GET_ERROR +#define ERR_peek_error ERR_PEEK_ERROR +#define ERR_remove_state ERR_REMOVE_STATE +#define EVP_PKEY_copy_parameters EVP_PKEY_COPY_PARAMETERS +#define EVP_PKEY_free EVP_PKEY_FREE +#define EVP_cleanup EVP_CLEANUP +#define GENERAL_NAMES_free GENERAL_NAMES_FREE +#define i2d_X509_PUBKEY I2D_X509_PUBKEY +#define MD4_Final MD4_FINAL +#define MD4_Init MD4_INIT +#define MD4_Update MD4_UPDATE +#define MD5_Final MD5_FINAL +#define MD5_Init MD5_INIT +#define MD5_Update MD5_UPDATE +#define OPENSSL_add_all_algo_noconf OPENSSL_ADD_ALL_ALGO_NOCONF +#define PEM_read_X509 PEM_READ_X509 +#define PEM_write_bio_X509 PEM_WRITE_BIO_X509 +#define PKCS12_PBE_add PKCS12_PBE_ADD +#define PKCS12_free PKCS12_FREE +#define PKCS12_parse PKCS12_PARSE +#define RAND_add RAND_ADD +#define RAND_bytes RAND_BYTES +#define RAND_egd RAND_EGD +#define RAND_file_name RAND_FILE_NAME +#define RAND_load_file RAND_LOAD_FILE +#define RAND_status RAND_STATUS +#define SSL_CIPHER_get_name SSL_CIPHER_GET_NAME +#define SSL_CTX_add_client_CA SSL_CTX_ADD_CLIENT_CA +#define SSL_CTX_callback_ctrl SSL_CTX_CALLBACK_CTRL +#define SSL_CTX_check_private_key SSL_CTX_CHECK_PRIVATE_KEY +#define SSL_CTX_ctrl SSL_CTX_CTRL +#define SSL_CTX_free SSL_CTX_FREE +#define SSL_CTX_get_cert_store SSL_CTX_GET_CERT_STORE +#define SSL_CTX_load_verify_locations SSL_CTX_LOAD_VERIFY_LOCATIONS +#define SSL_CTX_new SSL_CTX_NEW +#define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST +#define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD +#define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB +#define SSL_CTX_set_verify SSL_CTX_SET_VERIFY +#define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY +#define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE +#define SSL_CTX_use_cert_chain_file SSL_CTX_USE_CERT_CHAIN_FILE +#define SSL_CTX_use_certificate SSL_CTX_USE_CERTIFICATE +#define SSL_CTX_use_certificate_file SSL_CTX_USE_CERTIFICATE_FILE +#define SSL_SESSION_free SSL_SESSION_FREE +#define SSL_connect SSL_CONNECT +#define SSL_free SSL_FREE +#define SSL_get1_session SSL_GET1_SESSION +#define SSL_get_certificate SSL_GET_CERTIFICATE +#define SSL_get_current_cipher SSL_GET_CURRENT_CIPHER +#define SSL_get_error SSL_GET_ERROR +#define SSL_get_peer_cert_chain SSL_GET_PEER_CERT_CHAIN +#define SSL_get_peer_certificate SSL_GET_PEER_CERTIFICATE +#define SSL_get_privatekey SSL_GET_PRIVATEKEY +#define SSL_get_session SSL_GET_SESSION +#define SSL_get_shutdown SSL_GET_SHUTDOWN +#define SSL_get_verify_result SSL_GET_VERIFY_RESULT +#define SSL_library_init SSL_LIBRARY_INIT +#define SSL_load_error_strings SSL_LOAD_ERROR_STRINGS +#define SSL_new SSL_NEW +#define SSL_peek SSL_PEEK +#define SSL_pending SSL_PENDING +#define SSL_read SSL_READ +#define SSL_set_connect_state SSL_SET_CONNECT_STATE +#define SSL_set_fd SSL_SET_FD +#define SSL_set_session SSL_SET_SESSION +#define SSL_shutdown SSL_SHUTDOWN +#define SSL_write SSL_WRITE +#define SSLeay SSLEAY +#define SSLv23_client_method SSLV23_CLIENT_METHOD +#define SSLv3_client_method SSLV3_CLIENT_METHOD +#define TLSv1_client_method TLSV1_CLIENT_METHOD +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_get0_user_data UI_GET0_USER_DATA +#define UI_get_input_flags UI_GET_INPUT_FLAGS +#define UI_get_string_type UI_GET_STRING_TYPE +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_method_get_closer UI_METHOD_GET_CLOSER +#define UI_method_get_opener UI_METHOD_GET_OPENER +#define UI_method_get_reader UI_METHOD_GET_READER +#define UI_method_get_writer UI_METHOD_GET_WRITER +#define UI_method_set_closer UI_METHOD_SET_CLOSER +#define UI_method_set_opener UI_METHOD_SET_OPENER +#define UI_method_set_reader UI_METHOD_SET_READER +#define UI_method_set_writer UI_METHOD_SET_WRITER +#define UI_OpenSSL UI_OPENSSL +#define UI_set_result UI_SET_RESULT +#define X509V3_EXT_print X509V3_EXT_PRINT +#define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL +#define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT +#define X509_LOOKUP_file X509_LOOKUP_FILE +#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA +#define X509_NAME_get_entry X509_NAME_GET_ENTRY +#define X509_NAME_get_index_by_NID X509_NAME_GET_INDEX_BY_NID +#define X509_NAME_print_ex X509_NAME_PRINT_EX +#define X509_STORE_CTX_get_current_cert X509_STORE_CTX_GET_CURRENT_CERT +#define X509_STORE_add_lookup X509_STORE_ADD_LOOKUP +#define X509_STORE_set_flags X509_STORE_SET_FLAGS +#define X509_check_issued X509_CHECK_ISSUED +#define X509_free X509_FREE +#define X509_get_ext_d2i X509_GET_EXT_D2I +#define X509_get_issuer_name X509_GET_ISSUER_NAME +#define X509_get_pubkey X509_GET_PUBKEY +#define X509_get_serialNumber X509_GET_SERIALNUMBER +#define X509_get_subject_name X509_GET_SUBJECT_NAME +#define X509_load_crl_file X509_LOAD_CRL_FILE +#define X509_verify_cert_error_string X509_VERIFY_CERT_ERROR_STRING +#define d2i_PKCS12_fp D2I_PKCS12_FP +#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT +#define sk_num SK_NUM +#define sk_pop SK_POP +#define sk_pop_free SK_POP_FREE +#define sk_value SK_VALUE + +#define USE_UPPERCASE_GSSAPI 1 +#define gss_seal GSS_SEAL +#define gss_unseal GSS_UNSEAL + +#define USE_UPPERCASE_KRBAPI 1 + +/* AI_NUMERICHOST needed for IP V6 support in Curl */ +#ifdef HAVE_NETDB_H +#include +#ifndef AI_NUMERICHOST +#ifdef ENABLE_IPV6 +#undef ENABLE_IPV6 +#endif +#endif +#endif + +/* VAX symbols are always in uppercase */ +#ifdef __VAX +#define inflate INFLATE +#define inflateEnd INFLATEEND +#define inflateInit2_ INFLATEINIT2_ +#define inflateInit_ INFLATEINIT_ +#define zlibVersion ZLIBVERSION +#endif + +/* Older VAX OpenSSL port defines these as Macros */ +/* Need to include the headers first and then redefine */ +/* that way a newer port will also work if some one has one */ +#ifdef __VAX + +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) +# define des_set_odd_parity DES_SET_ODD_PARITY +# define des_set_key DES_SET_KEY +# define des_ecb_encrypt DES_ECB_ENCRYPT + +# endif +# include +# ifndef OpenSSL_add_all_algorithms +# define OpenSSL_add_all_algorithms OPENSSL_ADD_ALL_ALGORITHMS + void OPENSSL_ADD_ALL_ALGORITHMS(void); +# endif + + /* Curl defines these to lower case and VAX needs them in upper case */ + /* So we need static routines */ +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) + +# undef des_set_odd_parity +# undef DES_set_odd_parity +# undef des_set_key +# undef DES_set_key +# undef des_ecb_encrypt +# undef DES_ecb_encrypt + + static void des_set_odd_parity(des_cblock *key) { + DES_SET_ODD_PARITY(key); + } + + static int des_set_key(const_des_cblock *key, + des_key_schedule schedule) { + return DES_SET_KEY(key, schedule); + } + + static void des_ecb_encrypt(const_des_cblock *input, + des_cblock *output, + des_key_schedule ks, int enc) { + DES_ECB_ENCRYPT(input, output, ks, enc); + } +#endif +/* Need this to stop a macro redefinition error */ +#if OPENSSL_VERSION_NUMBER < 0x00907000L +# ifdef X509_STORE_set_flags +# undef X509_STORE_set_flags +# define X509_STORE_set_flags(x,y) Curl_nop_stmt +# endif +#endif +#endif + +#endif /* HEADER_CURL_SETUP_VMS_H */ diff --git a/libcurl/src/lib/share.c b/libcurl/src/lib/share.c new file mode 100644 index 0000000..ee04521 --- /dev/null +++ b/libcurl/src/lib/share.c @@ -0,0 +1,253 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "share.h" +#include "vtls/vtls.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +CURLSH * +curl_share_init(void) +{ + struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); + if(share) + share->specifier |= (1<dirty) + /* don't allow setting options while one or more handles are already + using this share */ + return CURLSHE_IN_USE; + + va_start(param, option); + + switch(option) { + case CURLSHOPT_SHARE: + /* this is a type this share will share */ + type = va_arg(param, int); + share->specifier |= (1<hostcache) { + share->hostcache = Curl_mk_dnscache(); + if(!share->hostcache) + res = CURLSHE_NOMEM; + } + break; + + case CURL_LOCK_DATA_COOKIE: +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(!share->cookies) { + share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE ); + if(!share->cookies) + res = CURLSHE_NOMEM; + } +#else /* CURL_DISABLE_HTTP */ + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_SSL_SESSION: +#ifdef USE_SSL + if(!share->sslsession) { + share->max_ssl_sessions = 8; + share->sslsession = calloc(share->max_ssl_sessions, + sizeof(struct curl_ssl_session)); + share->sessionage = 0; + if(!share->sslsession) + res = CURLSHE_NOMEM; + } +#else + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ + break; + + default: + res = CURLSHE_BAD_OPTION; + } + break; + + case CURLSHOPT_UNSHARE: + /* this is a type this share will no longer share */ + type = va_arg(param, int); + share->specifier &= ~(1<hostcache) { + Curl_hash_destroy(share->hostcache); + share->hostcache = NULL; + } + break; + + case CURL_LOCK_DATA_COOKIE: +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(share->cookies) { + Curl_cookie_cleanup(share->cookies); + share->cookies = NULL; + } +#else /* CURL_DISABLE_HTTP */ + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_SSL_SESSION: +#ifdef USE_SSL + Curl_safefree(share->sslsession); +#else + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_CONNECT: + break; + + default: + res = CURLSHE_BAD_OPTION; + break; + } + break; + + case CURLSHOPT_LOCKFUNC: + lockfunc = va_arg(param, curl_lock_function); + share->lockfunc = lockfunc; + break; + + case CURLSHOPT_UNLOCKFUNC: + unlockfunc = va_arg(param, curl_unlock_function); + share->unlockfunc = unlockfunc; + break; + + case CURLSHOPT_USERDATA: + ptr = va_arg(param, void *); + share->clientdata = ptr; + break; + + default: + res = CURLSHE_BAD_OPTION; + break; + } + + va_end(param); + + return res; +} + +CURLSHcode +curl_share_cleanup(CURLSH *sh) +{ + struct Curl_share *share = (struct Curl_share *)sh; + + if(share == NULL) + return CURLSHE_INVALID; + + if(share->lockfunc) + share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, + share->clientdata); + + if(share->dirty) { + if(share->unlockfunc) + share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); + return CURLSHE_IN_USE; + } + + if(share->hostcache) { + Curl_hash_destroy(share->hostcache); + share->hostcache = NULL; + } + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + Curl_cookie_cleanup(share->cookies); +#endif + +#ifdef USE_SSL + if(share->sslsession) { + size_t i; + for(i = 0; i < share->max_ssl_sessions; i++) + Curl_ssl_kill_session(&(share->sslsession[i])); + free(share->sslsession); + } +#endif + + if(share->unlockfunc) + share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); + free(share); + + return CURLSHE_OK; +} + + +CURL_STATIC CURLSHcode +Curl_share_lock(struct SessionHandle *data, curl_lock_data type, + curl_lock_access accesstype) +{ + struct Curl_share *share = data->share; + + if(share == NULL) + return CURLSHE_INVALID; + + if(share->specifier & (1<lockfunc) /* only call this if set! */ + share->lockfunc(data, type, accesstype, share->clientdata); + } + /* else if we don't share this, pretend successful lock */ + + return CURLSHE_OK; +} + +CURL_STATIC CURLSHcode +Curl_share_unlock(struct SessionHandle *data, curl_lock_data type) +{ + struct Curl_share *share = data->share; + + if(share == NULL) + return CURLSHE_INVALID; + + if(share->specifier & (1<unlockfunc) /* only call this if set! */ + share->unlockfunc (data, type, share->clientdata); + } + + return CURLSHE_OK; +} diff --git a/libcurl/src/lib/share.h b/libcurl/src/lib/share.h new file mode 100644 index 0000000..ea90977 --- /dev/null +++ b/libcurl/src/lib/share.h @@ -0,0 +1,61 @@ +#ifndef HEADER_CURL_SHARE_H +#define HEADER_CURL_SHARE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "cookie.h" +#include "urldata.h" + +/* SalfordC says "A structure member may not be volatile". Hence: + */ +#ifdef __SALFORDC__ +#define CURL_VOLATILE +#else +#define CURL_VOLATILE volatile +#endif + +/* this struct is libcurl-private, don't export details */ +struct Curl_share { + unsigned int specifier; + CURL_VOLATILE unsigned int dirty; + + curl_lock_function lockfunc; + curl_unlock_function unlockfunc; + void *clientdata; + + struct curl_hash *hostcache; +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + struct CookieInfo *cookies; +#endif + + struct curl_ssl_session *sslsession; + size_t max_ssl_sessions; + long sessionage; +}; + +CURL_STATIC CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data, + curl_lock_access); +CURL_STATIC CURLSHcode Curl_share_unlock (struct SessionHandle *, curl_lock_data); + +#endif /* HEADER_CURL_SHARE_H */ diff --git a/libcurl/src/lib/sigpipe.h b/libcurl/src/lib/sigpipe.h new file mode 100644 index 0000000..e8d2acd --- /dev/null +++ b/libcurl/src/lib/sigpipe.h @@ -0,0 +1,78 @@ +#ifndef HEADER_CURL_SIGPIPE_H +#define HEADER_CURL_SIGPIPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && defined(USE_OPENSSL) +#include + +struct sigpipe_ignore { + struct sigaction old_pipe_act; + bool no_signal; +}; + +#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x + +/* + * sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl + * internals, and then sigpipe_restore() will restore the situation when we + * return from libcurl again. + */ +static void sigpipe_ignore(struct SessionHandle *data, + struct sigpipe_ignore *ig) +{ + /* get a local copy of no_signal because the SessionHandle might not be + around when we restore */ + ig->no_signal = data->set.no_signal; + if(!data->set.no_signal) { + struct sigaction action; + /* first, extract the existing situation */ + memset(&ig->old_pipe_act, 0, sizeof(struct sigaction)); + sigaction(SIGPIPE, NULL, &ig->old_pipe_act); + action = ig->old_pipe_act; + /* ignore this signal */ + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + } +} + +/* + * sigpipe_restore() puts back the outside world's opinion of signal handler + * and SIGPIPE handling. It MUST only be called after a corresponding + * sigpipe_ignore() was used. + */ +static void sigpipe_restore(struct sigpipe_ignore *ig) +{ + if(!ig->no_signal) + /* restore the outside state */ + sigaction(SIGPIPE, &ig->old_pipe_act, NULL); +} + +#else +/* for systems without sigaction */ +#define sigpipe_ignore(x,y) Curl_nop_stmt +#define sigpipe_restore(x) Curl_nop_stmt +#define SIGPIPE_VARIABLE(x) +#endif + +#endif /* HEADER_CURL_SIGPIPE_H */ diff --git a/libcurl/src/lib/slist.c b/libcurl/src/lib/slist.c new file mode 100644 index 0000000..78ecf54 --- /dev/null +++ b/libcurl/src/lib/slist.c @@ -0,0 +1,143 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "slist.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* returns last node in linked list */ +static struct curl_slist *slist_get_last(struct curl_slist *list) +{ + struct curl_slist *item; + + /* if caller passed us a NULL, return now */ + if(!list) + return NULL; + + /* loop through to find the last item */ + item = list; + while(item->next) { + item = item->next; + } + return item; +} + +/* + * Curl_slist_append_nodup() appends a string to the linked list. Rather than + * copying the string in dynamic storage, it takes its ownership. The string + * should have been malloc()ated. Curl_slist_append_nodup always returns + * the address of the first record, so that you can use this function as an + * initialization function as well as an append function. + * If an error occurs, NULL is returned and the string argument is NOT + * released. + */ +CURL_STATIC struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data) +{ + struct curl_slist *last; + struct curl_slist *new_item; + + DEBUGASSERT(data); + + new_item = malloc(sizeof(struct curl_slist)); + if(!new_item) + return NULL; + + new_item->next = NULL; + new_item->data = data; + + /* if this is the first item, then new_item *is* the list */ + if(!list) + return new_item; + + last = slist_get_last(list); + last->next = new_item; + return list; +} + +/* + * curl_slist_append() appends a string to the linked list. It always returns + * the address of the first record, so that you can use this function as an + * initialization function as well as an append function. If you find this + * bothersome, then simply create a separate _init function and call it + * appropriately from within the program. + */ +struct curl_slist *curl_slist_append(struct curl_slist *list, + const char *data) +{ + char *dupdata = strdup(data); + + if(!dupdata) + return NULL; + + list = Curl_slist_append_nodup(list, dupdata); + if(!list) + free(dupdata); + + return list; +} + +/* + * Curl_slist_duplicate() duplicates a linked list. It always returns the + * address of the first record of the cloned list or NULL in case of an + * error (or if the input list was NULL). + */ +CURL_STATIC struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist) +{ + struct curl_slist *outlist = NULL; + struct curl_slist *tmp; + + while(inlist) { + tmp = curl_slist_append(outlist, inlist->data); + + if(!tmp) { + curl_slist_free_all(outlist); + return NULL; + } + + outlist = tmp; + inlist = inlist->next; + } + return outlist; +} + +/* be nice and clean up resources */ +void curl_slist_free_all(struct curl_slist *list) +{ + struct curl_slist *next; + struct curl_slist *item; + + if(!list) + return; + + item = list; + do { + next = item->next; + Curl_safefree(item->data); + free(item); + item = next; + } while(next); +} + diff --git a/libcurl/src/lib/slist.h b/libcurl/src/lib/slist.h new file mode 100644 index 0000000..b4fef87 --- /dev/null +++ b/libcurl/src/lib/slist.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_SLIST_H +#define HEADER_CURL_SLIST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Curl_slist_duplicate() duplicates a linked list. It always returns the + * address of the first record of the cloned list or NULL in case of an + * error (or if the input list was NULL). + */ +CURL_STATIC struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist); + +/* + * Curl_slist_append_nodup() takes ownership of the given string and appends + * it to the list. + */ +CURL_STATIC struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, + char *data); + +#endif /* HEADER_CURL_SLIST_H */ + diff --git a/libcurl/src/lib/smb.c b/libcurl/src/lib/smb.c new file mode 100644 index 0000000..8cb3503 --- /dev/null +++ b/libcurl/src/lib/smb.c @@ -0,0 +1,970 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014, Bill Nagel , Exacq Technologies + * Copyright (C) 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#define BUILDING_CURL_SMB_C + +#ifdef HAVE_PROCESS_H +#include +#define getpid _getpid +#endif + +#include "smb.h" +#include "urldata.h" +#include "sendf.h" +#include "multiif.h" +#include "connect.h" +#include "progress.h" +#include "transfer.h" +#include "vtls/vtls.h" +#include "curl_ntlm_core.h" +#include "escape.h" +#include "curl_endian.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode smb_setup_connection(struct connectdata *conn); +static CURLcode smb_connect(struct connectdata *conn, bool *done); +static CURLcode smb_connection_state(struct connectdata *conn, bool *done); +static CURLcode smb_request_state(struct connectdata *conn, bool *done); +static CURLcode smb_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode smb_disconnect(struct connectdata *conn, bool dead); +static int smb_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode smb_parse_url_path(struct connectdata *conn); + +/* + * SMB handler interface + */ +const struct Curl_handler Curl_handler_smb = { + "SMB", /* scheme */ + smb_setup_connection, /* setup_connection */ + ZERO_NULL, /* do_it */ + smb_done, /* done */ + ZERO_NULL, /* do_more */ + smb_connect, /* connect_it */ + smb_connection_state, /* connecting */ + smb_request_state, /* doing */ + smb_getsock, /* proto_getsock */ + smb_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smb_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_SMB, /* defport */ + CURLPROTO_SMB, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * SMBS handler interface + */ +const struct Curl_handler Curl_handler_smbs = { + "SMBS", /* scheme */ + smb_setup_connection, /* setup_connection */ + ZERO_NULL, /* do_it */ + smb_done, /* done */ + ZERO_NULL, /* do_more */ + smb_connect, /* connect_it */ + smb_connection_state, /* connecting */ + smb_request_state, /* doing */ + smb_getsock, /* proto_getsock */ + smb_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smb_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_SMBS, /* defport */ + CURLPROTO_SMBS, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + +#define MAX_PAYLOAD_SIZE 0x8000 +#define MAX_MESSAGE_SIZE (MAX_PAYLOAD_SIZE + 0x1000) +#define CLIENTNAME "curl" +#define SERVICENAME "?????" + +/* Append a string to an SMB message */ +#define MSGCAT(str) \ + strcpy(p, (str)); \ + p += strlen(str); + +/* Append a null-terminated string to an SMB message */ +#define MSGCATNULL(str) \ + strcpy(p, (str)); \ + p += strlen(str) + 1; + +/* SMB is mostly little endian */ +#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ + defined(__OS400__) +static unsigned short smb_swap16(unsigned short x) +{ + return (x << 8) | ((x >> 8) & 0xff); +} + +static unsigned int smb_swap32(unsigned int x) +{ + return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | + ((x >> 24) & 0xff); +} + +#ifdef HAVE_LONGLONG +static unsigned long long smb_swap64(unsigned long long x) +{ + return ((unsigned long long)smb_swap32(x) << 32) | smb_swap32(x >> 32); +} +#else +static unsigned __int64 smb_swap64(unsigned __int64 x) +{ + return ((unsigned __int64)smb_swap32(x) << 32) | smb_swap32(x >> 32); +} +#endif +#else +# define smb_swap16(x) (x) +# define smb_swap32(x) (x) +# define smb_swap64(x) (x) +#endif + +/* SMB request state */ +enum smb_req_state { + SMB_REQUESTING, + SMB_TREE_CONNECT, + SMB_OPEN, + SMB_DOWNLOAD, + SMB_UPLOAD, + SMB_CLOSE, + SMB_TREE_DISCONNECT, + SMB_DONE +}; + +/* SMB request data */ +struct smb_request { + enum smb_req_state state; + char *share; + char *path; + unsigned short tid; /* Even if we connect to the same tree as another */ + unsigned short fid; /* request, the tid will be different */ + CURLcode result; +}; + +static void conn_state(struct connectdata *conn, enum smb_conn_state newstate) +{ + struct smb_conn *smb = &conn->proto.smbc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* For debug purposes */ + static const char * const names[] = { + "SMB_NOT_CONNECTED", + "SMB_CONNECTING", + "SMB_NEGOTIATE", + "SMB_SETUP", + "SMB_CONNECTED", + /* LAST */ + }; + + if(smb->state != newstate) + infof(conn->data, "SMB conn %p state change from %s to %s\n", + (void *)smb, names[smb->state], names[newstate]); +#endif + + smb->state = newstate; +} + +static void request_state(struct connectdata *conn, + enum smb_req_state newstate) +{ + struct smb_request *req = conn->data->req.protop; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* For debug purposes */ + static const char * const names[] = { + "SMB_REQUESTING", + "SMB_TREE_CONNECT", + "SMB_OPEN", + "SMB_DOWNLOAD", + "SMB_UPLOAD", + "SMB_CLOSE", + "SMB_TREE_DISCONNECT", + "SMB_DONE", + /* LAST */ + }; + + if(req->state != newstate) + infof(conn->data, "SMB request %p state change from %s to %s\n", + (void *)req, names[req->state], names[newstate]); +#endif + + req->state = newstate; +} + +static CURLcode smb_setup_connection(struct connectdata *conn) +{ + struct smb_request *req; + + /* Initialize the request state */ + conn->data->req.protop = req = calloc(1, sizeof(struct smb_request)); + if(!req) + return CURLE_OUT_OF_MEMORY; + + /* Parse the URL path */ + return smb_parse_url_path(conn); +} + +static CURLcode smb_connect(struct connectdata *conn, bool *done) +{ + struct smb_conn *smbc = &conn->proto.smbc; + char *slash; + + (void) done; + + /* Check we have a username and password to authenticate with */ + if(!conn->bits.user_passwd) + return CURLE_LOGIN_DENIED; + + /* Initialize the connection state */ + memset(smbc, 0, sizeof(*smbc)); + smbc->state = SMB_CONNECTING; + smbc->recv_buf = malloc(MAX_MESSAGE_SIZE); + if(!smbc->recv_buf) + return CURLE_OUT_OF_MEMORY; + + /* Multiple requests are allowed with this connection */ + connkeep(conn, "SMB default"); + + /* Parse the username, domain, and password */ + slash = strchr(conn->user, '/'); + if(!slash) + slash = strchr(conn->user, '\\'); + + if(slash) { + smbc->user = slash + 1; + smbc->domain = strdup(conn->user); + if(!smbc->domain) + return CURLE_OUT_OF_MEMORY; + smbc->domain[slash - conn->user] = 0; + } + else { + smbc->user = conn->user; + smbc->domain = strdup(conn->host.name); + if(!smbc->domain) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +static CURLcode smb_recv_message(struct connectdata *conn, void **msg) +{ + struct smb_conn *smbc = &conn->proto.smbc; + char *buf = smbc->recv_buf; + ssize_t bytes_read; + size_t nbt_size; + size_t msg_size; + size_t len = MAX_MESSAGE_SIZE - smbc->got; + CURLcode result; + + result = Curl_read(conn, FIRSTSOCKET, buf + smbc->got, len, &bytes_read); + if(result) + return result; + + if(!bytes_read) + return CURLE_OK; + + smbc->got += bytes_read; + + /* Check for a 32-bit nbt header */ + if(smbc->got < sizeof(unsigned int)) + return CURLE_OK; + + nbt_size = Curl_read16_be((unsigned char *)(buf + sizeof(unsigned short))) + + sizeof(unsigned int); + if(smbc->got < nbt_size) + return CURLE_OK; + + msg_size = sizeof(struct smb_header); + if(nbt_size >= msg_size + 1) { + /* Add the word count */ + msg_size += 1 + ((unsigned char) buf[msg_size]) * sizeof(unsigned short); + if(nbt_size >= msg_size + sizeof(unsigned short)) { + /* Add the byte count */ + msg_size += sizeof(unsigned short) + + Curl_read16_le((unsigned char *)&buf[msg_size]); + if(nbt_size < msg_size) + return CURLE_READ_ERROR; + } + } + + *msg = buf; + + return CURLE_OK; +} + +static void smb_pop_message(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + + smbc->got = 0; +} + +static void smb_format_message(struct connectdata *conn, struct smb_header *h, + unsigned char cmd, size_t len) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_request *req = conn->data->req.protop; + unsigned int pid; + + memset(h, 0, sizeof(*h)); + h->nbt_length = htons((unsigned short) (sizeof(*h) - sizeof(unsigned int) + + len)); + memcpy((char *)h->magic, "\xffSMB", 4); + h->command = cmd; + h->flags = SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES; + h->flags2 = smb_swap16(SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAME); + h->uid = smb_swap16(smbc->uid); + h->tid = smb_swap16(req->tid); + pid = getpid(); + h->pid_high = smb_swap16((unsigned short)(pid >> 16)); + h->pid = smb_swap16((unsigned short) pid); +} + +static CURLcode smb_send(struct connectdata *conn, ssize_t len, + size_t upload_size) +{ + struct smb_conn *smbc = &conn->proto.smbc; + ssize_t bytes_written; + CURLcode result; + + result = Curl_write(conn, FIRSTSOCKET, conn->data->state.uploadbuffer, + len, &bytes_written); + if(result) + return result; + + if(bytes_written != len) { + smbc->send_size = len; + smbc->sent = bytes_written; + } + + smbc->upload_size = upload_size; + + return CURLE_OK; +} + +static CURLcode smb_flush(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + ssize_t bytes_written; + ssize_t len = smbc->send_size - smbc->sent; + CURLcode result; + + if(!smbc->send_size) + return CURLE_OK; + + result = Curl_write(conn, FIRSTSOCKET, + conn->data->state.uploadbuffer + smbc->sent, + len, &bytes_written); + if(result) + return result; + + if(bytes_written != len) + smbc->sent += bytes_written; + else + smbc->send_size = 0; + + return CURLE_OK; +} + +static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd, + const void *msg, size_t msg_len) +{ + smb_format_message(conn, (struct smb_header *)conn->data->state.uploadbuffer, + cmd, msg_len); + memcpy(conn->data->state.uploadbuffer + sizeof(struct smb_header), + msg, msg_len); + + return smb_send(conn, sizeof(struct smb_header) + msg_len, 0); +} + +static CURLcode smb_send_negotiate(struct connectdata *conn) +{ + const char *msg = "\x00\x0c\x00\x02NT LM 0.12"; + + return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15); +} + +static CURLcode smb_send_setup(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_setup msg; + char *p = msg.bytes; + unsigned char lm_hash[21]; + unsigned char lm[24]; + unsigned char nt_hash[21]; + unsigned char nt[24]; + + size_t byte_count = sizeof(lm) + sizeof(nt); + byte_count += strlen(smbc->user) + strlen(smbc->domain); + byte_count += strlen(OS) + strlen(CLIENTNAME) + 4; /* 4 null chars */ + if(byte_count > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash); + Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm); +#if USE_NTRESPONSES + Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash); + Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt); +#else + memset(nt, 0, sizeof(nt)); +#endif + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_SETUP_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.max_buffer_size = smb_swap16(MAX_MESSAGE_SIZE); + msg.max_mpx_count = smb_swap16(1); + msg.vc_number = smb_swap16(1); + msg.session_key = smb_swap32(smbc->session_key); + msg.capabilities = smb_swap32(SMB_CAP_LARGE_FILES); + msg.lengths[0] = smb_swap16(sizeof(lm)); + msg.lengths[1] = smb_swap16(sizeof(nt)); + memcpy(p, lm, sizeof(lm)); + p += sizeof(lm); + memcpy(p, nt, sizeof(nt)); + p += sizeof(nt); + MSGCATNULL(smbc->user); + MSGCATNULL(smbc->domain); + MSGCATNULL(OS); + MSGCATNULL(CLIENTNAME); + byte_count = p - msg.bytes; + msg.byte_count = smb_swap16((unsigned short)byte_count); + + return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_tree_connect(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_tree_connect msg; + char *p = msg.bytes; + + size_t byte_count = strlen(conn->host.name) + strlen(req->share); + byte_count += strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */ + if(byte_count > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_TREE_CONNECT_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.pw_len = 0; + MSGCAT("\\\\"); + MSGCAT(conn->host.name); + MSGCAT("\\"); + MSGCATNULL(req->share); + MSGCATNULL(SERVICENAME); /* Match any type of service */ + byte_count = p - msg.bytes; + msg.byte_count = smb_swap16((unsigned short)byte_count); + + return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_open(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_nt_create msg; + size_t byte_count; + + if((strlen(req->path) + 1) > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_NT_CREATE_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + byte_count = strlen(req->path); + msg.name_length = smb_swap16((unsigned short)byte_count); + msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL); + if(conn->data->set.upload) { + msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE); + msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF); + } + else { + msg.access = smb_swap32(SMB_GENERIC_READ); + msg.create_disposition = smb_swap32(SMB_FILE_OPEN); + } + msg.byte_count = smb_swap16((unsigned short) ++byte_count); + strcpy(msg.bytes, req->path); + + return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_close(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_close msg; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_CLOSE; + msg.fid = smb_swap16(req->fid); + + return smb_send_message(conn, SMB_COM_CLOSE, &msg, sizeof(msg)); +} + +static CURLcode smb_send_tree_disconnect(struct connectdata *conn) +{ + struct smb_tree_disconnect msg; + + memset(&msg, 0, sizeof(msg)); + + return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg)); +} + +static CURLcode smb_send_read(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + curl_off_t offset = conn->data->req.offset; + struct smb_read msg; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_READ_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.fid = smb_swap16(req->fid); + msg.offset = smb_swap32((unsigned int) offset); + msg.offset_high = smb_swap32((unsigned int) (offset >> 32)); + msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE); + msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE); + + return smb_send_message(conn, SMB_COM_READ_ANDX, &msg, sizeof(msg)); +} + +static CURLcode smb_send_write(struct connectdata *conn) +{ + struct smb_write *msg = (struct smb_write *)conn->data->state.uploadbuffer; + struct smb_request *req = conn->data->req.protop; + curl_off_t offset = conn->data->req.offset; + + curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount; + if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */ + upload_size = MAX_PAYLOAD_SIZE - 1; + + memset(msg, 0, sizeof(*msg)); + msg->word_count = SMB_WC_WRITE_ANDX; + msg->andx.command = SMB_COM_NO_ANDX_COMMAND; + msg->fid = smb_swap16(req->fid); + msg->offset = smb_swap32((unsigned int) offset); + msg->offset_high = smb_swap32((unsigned int) (offset >> 32)); + msg->data_length = smb_swap16((unsigned short) upload_size); + msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int)); + msg->byte_count = smb_swap16((unsigned short) (upload_size + 1)); + + smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX, + sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size); + + return smb_send(conn, sizeof(*msg), (size_t) upload_size); +} + +static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg) +{ + struct smb_conn *smbc = &conn->proto.smbc; + CURLcode result; + + /* Check if there is data in the transfer buffer */ + if(!smbc->send_size && smbc->upload_size) { + int nread = smbc->upload_size > BUFSIZE ? BUFSIZE : + (int) smbc->upload_size; + conn->data->req.upload_fromhere = conn->data->state.uploadbuffer; + result = Curl_fillreadbuffer(conn, nread, &nread); + if(result && result != CURLE_AGAIN) + return result; + if(!nread) + return CURLE_OK; + + smbc->upload_size -= nread; + smbc->send_size = nread; + smbc->sent = 0; + } + + /* Check if there is data to send */ + if(smbc->send_size) { + result = smb_flush(conn); + if(result) + return result; + } + + /* Check if there is still data to be sent */ + if(smbc->send_size || smbc->upload_size) + return CURLE_AGAIN; + + return smb_recv_message(conn, msg); +} + +static CURLcode smb_connection_state(struct connectdata *conn, bool *done) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_negotiate_response *nrsp; + struct smb_header *h; + CURLcode result; + void *msg = NULL; + + if(smbc->state == SMB_CONNECTING) { +#ifdef USE_SSL + if((conn->handler->flags & PROTOPT_SSL)) { + bool ssl_done; + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done); + if(result && result != CURLE_AGAIN) + return result; + if(!ssl_done) + return CURLE_OK; + } +#endif + + result = smb_send_negotiate(conn); + if(result) { + connclose(conn, "SMB: failed to send negotiate message"); + return result; + } + + conn_state(conn, SMB_NEGOTIATE); + } + + /* Send the previous message and check for a response */ + result = smb_send_and_recv(conn, &msg); + if(result && result != CURLE_AGAIN) { + connclose(conn, "SMB: failed to communicate"); + return result; + } + + if(!msg) + return CURLE_OK; + + h = msg; + + switch(smbc->state) { + case SMB_NEGOTIATE: + if(h->status) { + connclose(conn, "SMB: negotiation failed"); + return CURLE_COULDNT_CONNECT; + } + nrsp = msg; + memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge)); + smbc->session_key = smb_swap32(nrsp->session_key); + result = smb_send_setup(conn); + if(result) { + connclose(conn, "SMB: failed to send setup message"); + return result; + } + conn_state(conn, SMB_SETUP); + break; + + case SMB_SETUP: + if(h->status) { + connclose(conn, "SMB: authentication failed"); + return CURLE_LOGIN_DENIED; + } + smbc->uid = smb_swap16(h->uid); + conn_state(conn, SMB_CONNECTED); + *done = true; + break; + + default: + smb_pop_message(conn); + return CURLE_OK; /* ignore */ + } + + smb_pop_message(conn); + + return CURLE_OK; +} + +static CURLcode smb_request_state(struct connectdata *conn, bool *done) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_header *h; + enum smb_req_state next_state = SMB_DONE; + unsigned short len; + unsigned short off; + CURLcode result; + void *msg = NULL; + + /* Start the request */ + if(req->state == SMB_REQUESTING) { + result = smb_send_tree_connect(conn); + if(result) { + connclose(conn, "SMB: failed to send tree connect message"); + return result; + } + + request_state(conn, SMB_TREE_CONNECT); + } + + /* Send the previous message and check for a response */ + result = smb_send_and_recv(conn, &msg); + if(result && result != CURLE_AGAIN) { + connclose(conn, "SMB: failed to communicate"); + return result; + } + + if(!msg) + return CURLE_OK; + + h = msg; + + switch(req->state) { + case SMB_TREE_CONNECT: + if(h->status) { + req->result = CURLE_REMOTE_FILE_NOT_FOUND; + if(h->status == smb_swap32(SMB_ERR_NOACCESS)) + req->result = CURLE_REMOTE_ACCESS_DENIED; + break; + } + req->tid = smb_swap16(h->tid); + next_state = SMB_OPEN; + break; + + case SMB_OPEN: + if(h->status) { + req->result = CURLE_REMOTE_FILE_NOT_FOUND; + next_state = SMB_TREE_DISCONNECT; + break; + } + req->fid = smb_swap16(((struct smb_nt_create_response *)msg)->fid); + conn->data->req.offset = 0; + if(conn->data->set.upload) { + conn->data->req.size = conn->data->state.infilesize; + Curl_pgrsSetUploadSize(conn->data, conn->data->req.size); + next_state = SMB_UPLOAD; + } + else { + conn->data->req.size = + smb_swap64(((struct smb_nt_create_response *)msg)->end_of_file); + Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size); + next_state = SMB_DOWNLOAD; + } + break; + + case SMB_DOWNLOAD: + if(h->status) { + req->result = CURLE_RECV_ERROR; + next_state = SMB_CLOSE; + break; + } + len = Curl_read16_le(((unsigned char *) msg) + + sizeof(struct smb_header) + 11); + off = Curl_read16_le(((unsigned char *) msg) + + sizeof(struct smb_header) + 13); + if(len > 0) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *)msg + off + sizeof(unsigned int), + len); + if(result) { + req->result = result; + next_state = SMB_CLOSE; + break; + } + } + conn->data->req.bytecount += len; + conn->data->req.offset += len; + Curl_pgrsSetDownloadCounter(conn->data, conn->data->req.bytecount); + next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD; + break; + + case SMB_UPLOAD: + if(h->status) { + req->result = CURLE_UPLOAD_FAILED; + next_state = SMB_CLOSE; + break; + } + len = Curl_read16_le(((unsigned char *) msg) + + sizeof(struct smb_header) + 5); + conn->data->req.bytecount += len; + conn->data->req.offset += len; + Curl_pgrsSetUploadCounter(conn->data, conn->data->req.bytecount); + if(conn->data->req.bytecount >= conn->data->req.size) + next_state = SMB_CLOSE; + else + next_state = SMB_UPLOAD; + break; + + case SMB_CLOSE: + /* We don't care if the close failed, proceed to tree disconnect anyway */ + next_state = SMB_TREE_DISCONNECT; + break; + + case SMB_TREE_DISCONNECT: + next_state = SMB_DONE; + break; + + default: + smb_pop_message(conn); + return CURLE_OK; /* ignore */ + } + + smb_pop_message(conn); + + switch(next_state) { + case SMB_OPEN: + result = smb_send_open(conn); + break; + + case SMB_DOWNLOAD: + result = smb_send_read(conn); + break; + + case SMB_UPLOAD: + result = smb_send_write(conn); + break; + + case SMB_CLOSE: + result = smb_send_close(conn); + break; + + case SMB_TREE_DISCONNECT: + result = smb_send_tree_disconnect(conn); + break; + + case SMB_DONE: + result = req->result; + *done = true; + break; + + default: + break; + } + + if(result) { + connclose(conn, "SMB: failed to send message"); + return result; + } + + request_state(conn, next_state); + + return CURLE_OK; +} + +static CURLcode smb_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct smb_request *req = conn->data->req.protop; + + (void) premature; + + Curl_safefree(req->share); + Curl_safefree(conn->data->req.protop); + + return status; +} + +static CURLcode smb_disconnect(struct connectdata *conn, bool dead) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_request *req = conn->data->req.protop; + + (void) dead; + + Curl_safefree(smbc->domain); + Curl_safefree(smbc->recv_buf); + + /* smb_done is not always called, so cleanup the request */ + if(req) { + Curl_safefree(req->share); + Curl_safefree(conn->data->req.protop); + } + + return CURLE_OK; +} + +static int smb_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct smb_conn *smbc = &conn->proto.smbc; + + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + + if(smbc->send_size || smbc->upload_size) + return GETSOCK_WRITESOCK(0); + + return GETSOCK_READSOCK(0); +} + +static CURLcode smb_parse_url_path(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct smb_request *req = data->req.protop; + char *path; + char *slash; + + /* URL decode the path */ + result = Curl_urldecode(data, data->state.path, 0, &path, NULL, TRUE); + if(result) + return result; + + /* Parse the path for the share */ + req->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path); + if(!req->share) { + free(path); + + return CURLE_OUT_OF_MEMORY; + } + + slash = strchr(req->share, '/'); + if(!slash) + slash = strchr(req->share, '\\'); + + /* The share must be present */ + if(!slash) { + free(path); + + return CURLE_URL_MALFORMAT; + } + + /* Parse the path for the file path converting any forward slashes into + backslashes */ + *slash++ = 0; + req->path = slash; + for(; *slash; slash++) { + if(*slash == '/') + *slash = '\\'; + } + + free(path); + + return CURLE_OK; +} + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */ diff --git a/libcurl/src/lib/smb.h b/libcurl/src/lib/smb.h new file mode 100644 index 0000000..7852fa1 --- /dev/null +++ b/libcurl/src/lib/smb.h @@ -0,0 +1,271 @@ +#ifndef HEADER_CURL_SMB_H +#define HEADER_CURL_SMB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014, Bill Nagel , Exacq Technologies + * + * 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. + * + ***************************************************************************/ + +enum smb_conn_state { + SMB_NOT_CONNECTED = 0, + SMB_CONNECTING, + SMB_NEGOTIATE, + SMB_SETUP, + SMB_CONNECTED +}; + +struct smb_conn { + enum smb_conn_state state; + char *user; + char *domain; + unsigned char challenge[8]; + unsigned int session_key; + unsigned short uid; + char *recv_buf; + size_t upload_size; + size_t send_size; + size_t sent; + size_t got; +}; + +/* + * Definitions for SMB protocol data structures + */ +#ifdef BUILDING_CURL_SMB_C + +#if defined(_MSC_VER) || defined(__ILEC400__) +# define PACK +# pragma pack(push) +# pragma pack(1) +#elif defined(__GNUC__) +# define PACK __attribute__((packed)) +#else +# define PACK +#endif + +#define SMB_COM_CLOSE 0x04 +#define SMB_COM_READ_ANDX 0x2e +#define SMB_COM_WRITE_ANDX 0x2f +#define SMB_COM_TREE_DISCONNECT 0x71 +#define SMB_COM_NEGOTIATE 0x72 +#define SMB_COM_SETUP_ANDX 0x73 +#define SMB_COM_TREE_CONNECT_ANDX 0x75 +#define SMB_COM_NT_CREATE_ANDX 0xa2 +#define SMB_COM_NO_ANDX_COMMAND 0xff + +#define SMB_WC_CLOSE 0x03 +#define SMB_WC_READ_ANDX 0x0c +#define SMB_WC_WRITE_ANDX 0x0e +#define SMB_WC_SETUP_ANDX 0x0d +#define SMB_WC_TREE_CONNECT_ANDX 0x04 +#define SMB_WC_NT_CREATE_ANDX 0x18 + +#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10 +#define SMB_FLAGS_CASELESS_PATHNAMES 0x08 +#define SMB_FLAGS2_UNICODE_STRINGS 0x8000 +#define SMB_FLAGS2_IS_LONG_NAME 0x0040 +#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001 + +#define SMB_CAP_LARGE_FILES 0x08 +#define SMB_GENERIC_WRITE 0x40000000 +#define SMB_GENERIC_READ 0x80000000 +#define SMB_FILE_SHARE_ALL 0x07 +#define SMB_FILE_OPEN 0x01 +#define SMB_FILE_OVERWRITE_IF 0x05 + +#define SMB_ERR_NOACCESS 0x00050001 + +struct smb_header { + unsigned char nbt_type; + unsigned char nbt_flags; + unsigned short nbt_length; + unsigned char magic[4]; + unsigned char command; + unsigned int status; + unsigned char flags; + unsigned short flags2; + unsigned short pid_high; + unsigned char signature[8]; + unsigned short pad; + unsigned short tid; + unsigned short pid; + unsigned short uid; + unsigned short mid; +} PACK; + +struct smb_negotiate_response { + struct smb_header h; + unsigned char word_count; + unsigned short dialect_index; + unsigned char security_mode; + unsigned short max_mpx_count; + unsigned short max_number_vcs; + unsigned int max_buffer_size; + unsigned int max_raw_size; + unsigned int session_key; + unsigned int capabilities; + unsigned int system_time_low; + unsigned int system_time_high; + unsigned short server_time_zone; + unsigned char encryption_key_length; + unsigned short byte_count; + char bytes[1]; +} PACK; + +struct andx { + unsigned char command; + unsigned char pad; + unsigned short offset; +} PACK; + +struct smb_setup { + unsigned char word_count; + struct andx andx; + unsigned short max_buffer_size; + unsigned short max_mpx_count; + unsigned short vc_number; + unsigned int session_key; + unsigned short lengths[2]; + unsigned int pad; + unsigned int capabilities; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_tree_connect { + unsigned char word_count; + struct andx andx; + unsigned short flags; + unsigned short pw_len; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_nt_create { + unsigned char word_count; + struct andx andx; + unsigned char pad; + unsigned short name_length; + unsigned int flags; + unsigned int root_fid; + unsigned int access; +#ifdef HAVE_LONGLONG + unsigned long long allocation_size; +#else + unsigned __int64 allocation_size; +#endif + unsigned int ext_file_attributes; + unsigned int share_access; + unsigned int create_disposition; + unsigned int create_options; + unsigned int impersonation_level; + unsigned char security_flags; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_nt_create_response { + struct smb_header h; + unsigned char word_count; + struct andx andx; + unsigned char op_lock_level; + unsigned short fid; + unsigned int create_disposition; +#ifdef HAVE_LONGLONG + unsigned long long create_time; + unsigned long long last_access_time; + unsigned long long last_write_time; + unsigned long long last_change_time; +#else + unsigned __int64 create_time; + unsigned __int64 last_access_time; + unsigned __int64 last_write_time; + unsigned __int64 last_change_time; +#endif + unsigned int ext_file_attributes; +#ifdef HAVE_LONGLONG + unsigned long long allocation_size; + unsigned long long end_of_file; +#else + unsigned __int64 allocation_size; + unsigned __int64 end_of_file; +#endif +} PACK; + +struct smb_read { + unsigned char word_count; + struct andx andx; + unsigned short fid; + unsigned int offset; + unsigned short max_bytes; + unsigned short min_bytes; + unsigned int timeout; + unsigned short remaining; + unsigned int offset_high; + unsigned short byte_count; +} PACK; + +struct smb_write { + struct smb_header h; + unsigned char word_count; + struct andx andx; + unsigned short fid; + unsigned int offset; + unsigned int timeout; + unsigned short write_mode; + unsigned short remaining; + unsigned short pad; + unsigned short data_length; + unsigned short data_offset; + unsigned int offset_high; + unsigned short byte_count; + unsigned char pad2; +} PACK; + +struct smb_close { + unsigned char word_count; + unsigned short fid; + unsigned int last_mtime; + unsigned short byte_count; +} PACK; + +struct smb_tree_disconnect { + unsigned char word_count; + unsigned short byte_count; +} PACK; + +#if defined(_MSC_VER) || defined(__ILEC400__) +# pragma pack(pop) +#endif + +#endif /* BUILDING_CURL_SMB_C */ + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +extern const struct Curl_handler Curl_handler_smb; +extern const struct Curl_handler Curl_handler_smbs; + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */ + +#endif /* HEADER_CURL_SMB_H */ diff --git a/libcurl/src/lib/smtp.c b/libcurl/src/lib/smtp.c new file mode 100644 index 0000000..e827a0e --- /dev/null +++ b/libcurl/src/lib/smtp.c @@ -0,0 +1,1671 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC1870 SMTP Service Extension for Message Size + * RFC2195 CRAM-MD5 authentication + * RFC2831 DIGEST-MD5 authentication + * RFC3207 SMTP over TLS + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC4954 SMTP Authentication + * RFC5321 SMTP protocol + * RFC6749 OAuth 2.0 Authorization Framework + * Draft SMTP URL Interface + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_SMTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "smtp.h" + +#include "strtoofft.h" +#include "strequal.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "rawstr.h" +#include "curl_gethostname.h" +#include "curl_sasl.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* Local API functions */ +static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode smtp_do(struct connectdata *conn, bool *done); +static CURLcode smtp_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode smtp_connect(struct connectdata *conn, bool *done); +static CURLcode smtp_disconnect(struct connectdata *conn, bool dead); +static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done); +static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode smtp_setup_connection(struct connectdata *conn); +static CURLcode smtp_parse_url_options(struct connectdata *conn); +static CURLcode smtp_parse_url_path(struct connectdata *conn); +static CURLcode smtp_parse_custom_request(struct connectdata *conn); +static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, + const char *initresp); +static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); +static void smtp_get_message(char *buffer, char** outptr); + +/* + * SMTP protocol handler. + */ + +const struct Curl_handler Curl_handler_smtp = { + "SMTP", /* scheme */ + smtp_setup_connection, /* setup_connection */ + smtp_do, /* do_it */ + smtp_done, /* done */ + ZERO_NULL, /* do_more */ + smtp_connect, /* connect_it */ + smtp_multi_statemach, /* connecting */ + smtp_doing, /* doing */ + smtp_getsock, /* proto_getsock */ + smtp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smtp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_SMTP, /* defport */ + CURLPROTO_SMTP, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */ +}; + +#ifdef USE_SSL +/* + * SMTPS protocol handler. + */ + +const struct Curl_handler Curl_handler_smtps = { + "SMTPS", /* scheme */ + smtp_setup_connection, /* setup_connection */ + smtp_do, /* do_it */ + smtp_done, /* done */ + ZERO_NULL, /* do_more */ + smtp_connect, /* connect_it */ + smtp_multi_statemach, /* connecting */ + smtp_doing, /* doing */ + smtp_getsock, /* proto_getsock */ + smtp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smtp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_SMTPS, /* defport */ + CURLPROTO_SMTPS, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL + | PROTOPT_NOURLQUERY /* flags */ +}; +#endif + +#ifndef CURL_DISABLE_HTTP +/* + * HTTP-proxyed SMTP protocol handler. + */ + +static const struct Curl_handler Curl_handler_smtp_proxy = { + "SMTP", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_SMTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * HTTP-proxyed SMTPS protocol handler. + */ + +static const struct Curl_handler Curl_handler_smtps_proxy = { + "SMTPS", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_SMTPS, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; +#endif +#endif + +/* SASL parameters for the smtp protocol */ +static const struct SASLproto saslsmtp = { + "smtp", /* The service name */ + 334, /* Code received when continuation is expected */ + 235, /* Code to receive upon authentication success */ + 512 - 8, /* Maximum initial response length (no max) */ + smtp_perform_auth, /* Send authentication command */ + smtp_continue_auth, /* Send authentication continuation */ + smtp_get_message /* Get SASL response message */ +}; + +#ifdef USE_SSL +static void smtp_to_smtps(struct connectdata *conn) +{ + conn->handler = &Curl_handler_smtps; +} +#else +#define smtp_to_smtps(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * smtp_endofresp() + * + * Checks for an ending SMTP status code at the start of the given string, but + * also detects various capabilities from the EHLO response including the + * supported authentication mechanisms. + */ +static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + bool result = FALSE; + + /* Nothing for us */ + if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) + return FALSE; + + /* Do we have a command response? This should be the response code followed + by a space and optionally some text as per RFC-5321 and as outlined in + Section 4. Examples of RFC-4954 but some e-mail servers ignore this and + only send the response code instead as per Section 4.2. */ + if(line[3] == ' ' || len == 5) { + result = TRUE; + *resp = curlx_sltosi(strtol(line, NULL, 10)); + + /* Make sure real server never sends internal value */ + if(*resp == 1) + *resp = 0; + } + /* Do we have a multiline (continuation) response? */ + else if(line[3] == '-' && + (smtpc->state == SMTP_EHLO || smtpc->state == SMTP_COMMAND)) { + result = TRUE; + *resp = 1; /* Internal response code */ + } + + return result; +} + +/*********************************************************************** + * + * smtp_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void smtp_get_message(char *buffer, char** outptr) +{ + size_t len = 0; + char* message = NULL; + + /* Find the start of the message */ + for(message = buffer + 4; *message == ' ' || *message == '\t'; message++) + ; + + /* Find the end of the message */ + for(len = strlen(message); len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change SMTP state! + */ +static void state(struct connectdata *conn, smtpstate newstate) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "STOP", + "SERVERGREET", + "EHLO", + "HELO", + "STARTTLS", + "UPGRADETLS", + "AUTH", + "COMMAND", + "MAIL", + "RCPT", + "DATA", + "POSTDATA", + "QUIT", + /* LAST */ + }; + + if(smtpc->state != newstate) + infof(conn->data, "SMTP %p state change from %s to %s\n", + (void *)smtpc, names[smtpc->state], names[newstate]); +#endif + + smtpc->state = newstate; +} + +/*********************************************************************** + * + * smtp_perform_ehlo() + * + * Sends the EHLO command to not only initialise communication with the ESMTP + * server but to also obtain a list of server side supported capabilities. + */ +static CURLcode smtp_perform_ehlo(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */ + smtpc->sasl.authused = SASL_AUTH_NONE; /* Clear the authentication mechanism + used for esmtp connections */ + smtpc->tls_supported = FALSE; /* Clear the TLS capability */ + smtpc->auth_supported = FALSE; /* Clear the AUTH capability */ + + /* Send the EHLO command */ + result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain); + + if(!result) + state(conn, SMTP_EHLO); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_helo() + * + * Sends the HELO command to initialise communication with the SMTP server. + */ +static CURLcode smtp_perform_helo(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + smtpc->sasl.authused = SASL_AUTH_NONE; /* No authentication mechanism used + in smtp connections */ + + /* Send the HELO command */ + result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain); + + if(!result) + state(conn, SMTP_HELO); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_starttls() + * + * Sends the STLS command to start the upgrade to TLS. + */ +static CURLcode smtp_perform_starttls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the STARTTLS command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS"); + + if(!result) + state(conn, SMTP_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + /* Start the SSL connection */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); + + if(!result) { + if(smtpc->state != SMTP_UPGRADETLS) + state(conn, SMTP_UPGRADETLS); + + if(smtpc->ssldone) { + smtp_to_smtps(conn); + result = smtp_perform_ehlo(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * smtp_perform_auth() + * + * Sends an AUTH command allowing the client to login with the given SASL + * authentication mechanism. + */ +static CURLcode smtp_perform_auth(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + if(initresp) { /* AUTH ... */ + /* Send the AUTH command with the initial response */ + result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); + } + else { + /* Send the AUTH command */ + result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * smtp_continue_auth() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + + return Curl_pp_sendf(&smtpc->pp, "%s", resp); +} + +/*********************************************************************** + * + * smtp_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism. + */ +static CURLcode smtp_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + saslprogress progress; + + /* Check we have enough data to authenticate with, and the + server supports authentiation, and end the connect phase if not */ + if(!smtpc->auth_supported || + !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) { + state(conn, SMTP_STOP); + return result; + } + + /* Calculate the SASL login details */ + result = Curl_sasl_start(&smtpc->sasl, conn, FALSE, &progress); + + if(!result) { + if(progress == SASL_INPROGRESS) + state(conn, SMTP_AUTH); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * smtp_perform_command() + * + * Sends a SMTP based command. + */ +static CURLcode smtp_perform_command(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SMTP *smtp = data->req.protop; + + /* Send the command */ + if(smtp->rcpt) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s", + smtp->custom && smtp->custom[0] != '\0' ? + smtp->custom : "VRFY", + smtp->rcpt->data); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", + smtp->custom && smtp->custom[0] != '\0' ? + smtp->custom : "HELP"); + + if(!result) + state(conn, SMTP_COMMAND); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_mail() + * + * Sends an MAIL command to initiate the upload of a message. + */ +static CURLcode smtp_perform_mail(struct connectdata *conn) +{ + char *from = NULL; + char *auth = NULL; + char *size = NULL; + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + /* Calculate the FROM parameter */ + if(!data->set.str[STRING_MAIL_FROM]) + /* Null reverse-path, RFC-5321, sect. 3.6.3 */ + from = strdup("<>"); + else if(data->set.str[STRING_MAIL_FROM][0] == '<') + from = aprintf("%s", data->set.str[STRING_MAIL_FROM]); + else + from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]); + + if(!from) + return CURLE_OUT_OF_MEMORY; + + /* Calculate the optional AUTH parameter */ + if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) { + if(data->set.str[STRING_MAIL_AUTH][0] != '\0') + auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]); + else + /* Empty AUTH, RFC-2554, sect. 5 */ + auth = strdup("<>"); + + if(!auth) { + free(from); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* Calculate the optional SIZE parameter */ + if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) { + size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize); + + if(!size) { + free(from); + free(auth); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* Send the MAIL command */ + if(!auth && !size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s", from); + else if(auth && !size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s AUTH=%s", from, auth); + else if(auth && size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s SIZE=%s", from, size); + + free(from); + free(auth); + free(size); + + if(!result) + state(conn, SMTP_MAIL); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_rcpt_to() + * + * Sends a RCPT TO command for a given recipient as part of the message upload + * process. + */ +static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SMTP *smtp = data->req.protop; + + /* Send the RCPT TO command */ + if(smtp->rcpt->data[0] == '<') + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s", + smtp->rcpt->data); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", + smtp->rcpt->data); + if(!result) + state(conn, SMTP_RCPT); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_quit() + * + * Performs the quit action prior to sclose() being called. + */ +static CURLcode smtp_perform_quit(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Send the QUIT command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT"); + + if(!result) + state(conn, SMTP_QUIT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode smtp_state_servergreet_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "Got unexpected smtp-server response: %d", smtpcode); + result = CURLE_FTP_WEIRD_SERVER_REPLY; + } + else + result = smtp_perform_ehlo(conn); + + return result; +} + +/* For STARTTLS responses */ +static CURLcode smtp_state_starttls_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 220) { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied. %c", smtpcode); + result = CURLE_USE_SSL_FAILED; + } + else + result = smtp_perform_authentication(conn); + } + else + result = smtp_perform_upgrade_tls(conn); + + return result; +} + +/* For EHLO responses */ +static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *line = data->state.buffer; + size_t len = strlen(line); + size_t wordlen; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2 && smtpcode != 1) { + if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) + result = smtp_perform_helo(conn); + else { + failf(data, "Remote access denied: %d", smtpcode); + result = CURLE_REMOTE_ACCESS_DENIED; + } + } + else { + line += 4; + len -= 4; + + /* Does the server support the STARTTLS capability? */ + if(len >= 8 && !memcmp(line, "STARTTLS", 8)) + smtpc->tls_supported = TRUE; + + /* Does the server support the SIZE capability? */ + else if(len >= 4 && !memcmp(line, "SIZE", 4)) + smtpc->size_supported = TRUE; + + /* Does the server support authentication? */ + else if(len >= 5 && !memcmp(line, "AUTH ", 5)) { + smtpc->auth_supported = TRUE; + + /* Advance past the AUTH keyword */ + line += 5; + len -= 5; + + /* Loop through the data line */ + for(;;) { + size_t llen; + unsigned int mechbit; + + while(len && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + len--; + } + + if(!len) + break; + + /* Extract the word */ + for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Test the word for a matching authentication mechanism */ + if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) && + llen == wordlen) + smtpc->sasl.authmechs |= mechbit; + + line += wordlen; + len -= wordlen; + } + } + + if(smtpcode != 1) { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(smtpc->tls_supported) + /* Switch to TLS connection now */ + result = smtp_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = smtp_perform_authentication(conn); + else { + failf(data, "STARTTLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = smtp_perform_authentication(conn); + } + } + + return result; +} + +/* For HELO responses */ +static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "Remote access denied: %d", smtpcode); + result = CURLE_REMOTE_ACCESS_DENIED; + } + else + /* End of connect phase */ + state(conn, SMTP_STOP); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode smtp_state_auth_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&smtpc->sasl, conn, smtpcode, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, SMTP_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + break; + default: + break; + } + + return result; +} + +/* For command responses */ +static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SMTP *smtp = data->req.protop; + char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + if((smtp->rcpt && smtpcode/100 != 2 && smtpcode != 553 && smtpcode != 1) || + (!smtp->rcpt && smtpcode/100 != 2 && smtpcode != 1)) { + failf(data, "Command failed: %d", smtpcode); + result = CURLE_RECV_ERROR; + } + else { + /* Temporarily add the LF character back and send as body to the client */ + if(!data->set.opt_no_body) { + line[len] = '\n'; + result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + line[len] = '\0'; + } + + if(smtpcode != 1) { + if(smtp->rcpt) { + smtp->rcpt = smtp->rcpt->next; + + if(smtp->rcpt) { + /* Send the next command */ + result = smtp_perform_command(conn); + } + else + /* End of DO phase */ + state(conn, SMTP_STOP); + } + else + /* End of DO phase */ + state(conn, SMTP_STOP); + } + } + + return result; +} + +/* For MAIL responses */ +static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "MAIL failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else + /* Start the RCPT TO command */ + result = smtp_perform_rcpt_to(conn); + + return result; +} + +/* For RCPT responses */ +static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SMTP *smtp = data->req.protop; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "RCPT failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else { + smtp->rcpt = smtp->rcpt->next; + + if(smtp->rcpt) + /* Send the next RCPT TO command */ + result = smtp_perform_rcpt_to(conn); + else { + /* Send the DATA command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA"); + + if(!result) + state(conn, SMTP_DATA); + } + } + + return result; +} + +/* For DATA response */ +static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 354) { + failf(data, "DATA failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else { + /* Set the progress upload size */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* SMTP upload */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + + /* End of DO phase */ + state(conn, SMTP_STOP); + } + + return result; +} + +/* For POSTDATA responses, which are received after the entire DATA + part has been sent to the server */ +static CURLcode smtp_state_postdata_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 250) + result = CURLE_RECV_ERROR; + + /* End of DONE phase */ + state(conn, SMTP_STOP); + + return result; +} + +static CURLcode smtp_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct SessionHandle *data = conn->data; + int smtpcode; + struct smtp_conn *smtpc = &conn->proto.smtpc; + struct pingpong *pp = &smtpc->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */ + if(smtpc->state == SMTP_UPGRADETLS) + return smtp_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); + if(result) + return result; + + /* Store the latest response for later retrieval if necessary */ + if(smtpc->state != SMTP_QUIT && smtpcode != 1) + data->info.httpcode = smtpcode; + + if(!smtpcode) + break; + + /* We have now received a full SMTP server response */ + switch(smtpc->state) { + case SMTP_SERVERGREET: + result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_EHLO: + result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_HELO: + result = smtp_state_helo_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_STARTTLS: + result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH: + result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_COMMAND: + result = smtp_state_command_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_MAIL: + result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_RCPT: + result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_DATA: + result = smtp_state_data_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_POSTDATA: + result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, SMTP_STOP); + break; + } + } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); + if(result || !smtpc->ssldone) + return result; + } + + result = Curl_pp_statemach(&smtpc->pp, FALSE); + *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode smtp_block_statemach(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + while(smtpc->state != SMTP_STOP && !result) + result = Curl_pp_statemach(&smtpc->pp, TRUE); + + return result; +} + +/* Allocate and initialize the SMTP struct for the current SessionHandle if + required */ +static CURLcode smtp_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SMTP *smtp; + + smtp = data->req.protop = calloc(sizeof(struct SMTP), 1); + if(!smtp) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the SMTP "protocol connect" and "doing" phases only */ +static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.smtpc.pp, socks, numsocks); +} + +/*********************************************************************** + * + * smtp_connect() + * + * This function should do everything that is to be considered a part of + * the connection phase. + * + * The variable pointed to by 'done' will be TRUE if the protocol-layer + * connect phase is done when this function returns, or FALSE if not. + */ +static CURLcode smtp_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + struct pingpong *pp = &smtpc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in SMTP */ + connkeep(conn, "SMTP default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = smtp_statemach_act; + pp->endofresp = smtp_endofresp; + pp->conn = conn; + + /* Initialize the SASL storage */ + Curl_sasl_init(&smtpc->sasl, &saslsmtp); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = smtp_parse_url_options(conn); + if(result) + return result; + + /* Parse the URL path */ + result = smtp_parse_url_path(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, SMTP_SERVERGREET); + + result = smtp_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * smtp_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode smtp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SMTP *smtp = data->req.protop; + struct pingpong *pp = &conn->proto.smtpc.pp; + char *eob; + ssize_t len; + ssize_t bytes_written; + + (void)premature; + + if(!smtp || !pp->conn) + /* When the easy handle is removed from the multi interface while libcurl + is still trying to resolve the host name, the SMTP struct is not yet + initialized. However, the removal action calls Curl_done() which in + turn calls this function, so we simply return success. */ + return CURLE_OK; + + if(status) { + connclose(conn, "SMTP done with bad status"); /* marked for closure */ + result = status; /* use the already set error code */ + } + else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) { + /* Calculate the EOB taking into account any terminating CRLF from the + previous line of the email or the CRLF of the DATA command when there + is "no mail data". RFC-5321, sect. 4.1.1.4. + + Note: As some SSL backends, such as OpenSSL, will cause Curl_write() to + fail when using a different pointer following a previous write, that + returned CURLE_AGAIN, we duplicate the EOB now rather than when the + bytes written doesn't equal len. */ + if(smtp->trailing_crlf || !conn->data->state.infilesize) { + eob = strdup(SMTP_EOB + 2); + len = SMTP_EOB_LEN - 2; + } + else { + eob = strdup(SMTP_EOB); + len = SMTP_EOB_LEN; + } + + if(!eob) + return CURLE_OUT_OF_MEMORY; + + /* Send the end of block data */ + result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written); + if(result) { + free(eob); + return result; + } + + if(bytes_written != len) { + /* The whole chunk was not sent so keep it around and adjust the + pingpong structure accordingly */ + pp->sendthis = eob; + pp->sendsize = len; + pp->sendleft = len - bytes_written; + } + else { + /* Successfully sent so adjust the response timeout relative to now */ + pp->response = Curl_tvnow(); + + free(eob); + } + + state(conn, SMTP_POSTDATA); + + /* Run the state-machine + + TODO: when the multi interface is used, this _really_ should be using + the smtp_multi_statemach function but we have no general support for + non-blocking DONE operations, not in the multi state machine and with + Curl_done() invokes on several places in the code! + */ + result = smtp_block_statemach(conn); + } + + /* Cleanup our per-request based variables */ + Curl_safefree(smtp->custom); + + /* Clear the transfer mode for the next request */ + smtp->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * smtp_perform() + * + * This is the actual DO function for SMTP. Transfer a mail, send a command + * or get some data according to the options previously setup. + */ +static CURLcode smtp_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is SMTP and no proxy */ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SMTP *smtp = data->req.protop; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(data->set.opt_no_body) { + /* Requested no body means no transfer */ + smtp->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Store the first recipient (or NULL if not specified) */ + smtp->rcpt = data->set.mail_rcpt; + + /* Start the first command in the DO phase */ + if(data->set.upload && data->set.mail_rcpt) + /* MAIL transfer */ + result = smtp_perform_mail(conn); + else + /* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */ + result = smtp_perform_command(conn); + + if(result) + return result; + + /* Run the state-machine */ + result = smtp_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * smtp_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (smtp_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode smtp_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the custom request */ + result = smtp_parse_custom_request(conn); + if(result) + return result; + + result = smtp_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * smtp_disconnect() + * + * Disconnect from an SMTP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The SMTP session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart) + if(!smtp_perform_quit(conn)) + (void)smtp_block_statemach(conn); /* ignore errors on QUIT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&smtpc->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, smtpc->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(smtpc->domain); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected) +{ + struct SMTP *smtp = conn->data->req.protop; + + (void)connected; + + if(smtp->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = smtp_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = smtp_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * smtp_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode smtp_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct SessionHandle *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = smtp_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = smtp_dophase_done(conn, connected); + + return result; +} + +static CURLcode smtp_setup_connection(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + CURLcode result; + + if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { + /* Unless we have asked to tunnel SMTP operations through the proxy, we + switch and use HTTP operations only */ +#ifndef CURL_DISABLE_HTTP + if(conn->handler == &Curl_handler_smtp) + conn->handler = &Curl_handler_smtp_proxy; + else { +#ifdef USE_SSL + conn->handler = &Curl_handler_smtps_proxy; +#else + failf(data, "SMTPS not supported!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + /* set it up as a HTTP connection instead */ + return conn->handler->setup_connection(conn); + +#else + failf(data, "SMTP over http proxy requires HTTP support built-in!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + + /* Initialise the SMTP layer */ + result = smtp_init(conn); + if(result) + return result; + + data->state.path++; /* don't include the initial slash */ + + return CURLE_OK; +} + +/*********************************************************************** + * + * smtp_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode smtp_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *ptr = conn->options; + + smtpc->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strnequal(key, "AUTH=", 5)) + result = Curl_sasl_parse_url_auth_option(&smtpc->sasl, + value, ptr - value); + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + return result; +} + +/*********************************************************************** + * + * smtp_parse_url_path() + * + * Parse the URL path into separate path components. + */ +static CURLcode smtp_parse_url_path(struct connectdata *conn) +{ + /* The SMTP struct is already initialised in smtp_connect() */ + struct SessionHandle *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *path = data->state.path; + char localhost[HOSTNAME_MAX + 1]; + + /* Calculate the path if necessary */ + if(!*path) { + if(!Curl_gethostname(localhost, sizeof(localhost))) + path = localhost; + else + path = "localhost"; + } + + /* URL decode the path and use it as the domain in our EHLO */ + return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); +} + +/*********************************************************************** + * + * smtp_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode smtp_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SMTP *smtp = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + /* URL decode the custom request */ + if(custom) + result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE); + + return result; +} + +CURL_STATIC CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) +{ + /* When sending a SMTP payload we must detect CRLF. sequences making sure + they are sent as CRLF.. instead, as a . on the beginning of a line will + be deleted by the server when not part of an EOB terminator and a + genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of + data by the server + */ + ssize_t i; + ssize_t si; + struct SessionHandle *data = conn->data; + struct SMTP *smtp = data->req.protop; + char *scratch = data->state.scratch; + char *newscratch = NULL; + char *oldscratch = NULL; + size_t eob_sent; + + /* Do we need to allocate a scratch buffer? */ + if(!scratch || data->set.crlf) { + oldscratch = scratch; + + scratch = newscratch = malloc(2 * BUFSIZE); + if(!newscratch) { + failf(data, "Failed to alloc scratch buffer!"); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* Have we already sent part of the EOB? */ + eob_sent = smtp->eob; + + /* This loop can be improved by some kind of Boyer-Moore style of + approach but that is saved for later... */ + for(i = 0, si = 0; i < nread; i++) { + if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) { + smtp->eob++; + + /* Is the EOB potentially the terminating CRLF? */ + if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob) + smtp->trailing_crlf = TRUE; + else + smtp->trailing_crlf = FALSE; + } + else if(smtp->eob) { + /* A previous substring matched so output that first */ + memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent); + si += smtp->eob - eob_sent; + + /* Then compare the first byte */ + if(SMTP_EOB[0] == data->req.upload_fromhere[i]) + smtp->eob = 1; + else + smtp->eob = 0; + + eob_sent = 0; + + /* Reset the trailing CRLF flag as there was more data */ + smtp->trailing_crlf = FALSE; + } + + /* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */ + if(SMTP_EOB_FIND_LEN == smtp->eob) { + /* Copy the replacement data to the target buffer */ + memcpy(&scratch[si], &SMTP_EOB_REPL[eob_sent], + SMTP_EOB_REPL_LEN - eob_sent); + si += SMTP_EOB_REPL_LEN - eob_sent; + smtp->eob = 0; + eob_sent = 0; + } + else if(!smtp->eob) + scratch[si++] = data->req.upload_fromhere[i]; + } + + if(smtp->eob - eob_sent) { + /* A substring matched before processing ended so output that now */ + memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent); + si += smtp->eob - eob_sent; + } + + /* Only use the new buffer if we replaced something */ + if(si != nread) { + /* Upload from the new (replaced) buffer instead */ + data->req.upload_fromhere = scratch; + + /* Save the buffer so it can be freed later */ + data->state.scratch = scratch; + + /* Free the old scratch buffer */ + free(oldscratch); + + /* Set the new amount too */ + data->req.upload_present = si; + } + else + free(newscratch); + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_SMTP */ diff --git a/libcurl/src/lib/smtp.h b/libcurl/src/lib/smtp.h new file mode 100644 index 0000000..360740a --- /dev/null +++ b/libcurl/src/lib/smtp.h @@ -0,0 +1,91 @@ +#ifndef HEADER_CURL_SMTP_H +#define HEADER_CURL_SMTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * SMTP unique setup + ***************************************************************************/ +typedef enum { + SMTP_STOP, /* do nothing state, stops the state machine */ + SMTP_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + SMTP_EHLO, + SMTP_HELO, + SMTP_STARTTLS, + SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + SMTP_AUTH, + SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */ + SMTP_MAIL, /* MAIL FROM */ + SMTP_RCPT, /* RCPT TO */ + SMTP_DATA, + SMTP_POSTDATA, + SMTP_QUIT, + SMTP_LAST /* never used */ +} smtpstate; + +/* This SMTP struct is used in the SessionHandle. All SMTP data that is + connection-oriented must be in smtp_conn to properly deal with the fact that + perhaps the SessionHandle is changed between the times the connection is + used. */ +struct SMTP { + curl_pp_transfer transfer; + char *custom; /* Custom Request */ + struct curl_slist *rcpt; /* Recipient list */ + size_t eob; /* Number of bytes of the EOB (End Of Body) that + have been received so far */ + bool trailing_crlf; /* Specifies if the tailing CRLF is present */ +}; + +/* smtp_conn is used for struct connection-oriented data in the connectdata + struct */ +struct smtp_conn { + struct pingpong pp; + smtpstate state; /* Always use smtp.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + char *domain; /* Client address/name to send in the EHLO */ + struct SASL sasl; /* SASL-related storage */ + bool tls_supported; /* StartTLS capability supported by server */ + bool size_supported; /* If server supports SIZE extension according to + RFC 1870 */ + bool auth_supported; /* AUTH capability supported by server */ +}; + +extern const struct Curl_handler Curl_handler_smtp; +extern const struct Curl_handler Curl_handler_smtps; + +/* this is the 5-bytes End-Of-Body marker for SMTP */ +#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a" +#define SMTP_EOB_LEN 5 +#define SMTP_EOB_FIND_LEN 3 + +/* if found in data, replace it with this string instead */ +#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e" +#define SMTP_EOB_REPL_LEN 4 + +CURL_STATIC CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread); + +#endif /* HEADER_CURL_SMTP_H */ diff --git a/libcurl/src/lib/sockaddr.h b/libcurl/src/lib/sockaddr.h new file mode 100644 index 0000000..6a2151c --- /dev/null +++ b/libcurl/src/lib/sockaddr.h @@ -0,0 +1,43 @@ +#ifndef HEADER_CURL_SOCKADDR_H +#define HEADER_CURL_SOCKADDR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +struct Curl_sockaddr_storage { + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sa_in6; +#endif +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE + struct sockaddr_storage sa_stor; +#else + char cbuf[256]; /* this should be big enough to fit a lot */ +#endif + } buffer; +}; + +#endif /* HEADER_CURL_SOCKADDR_H */ + diff --git a/libcurl/src/lib/socks.c b/libcurl/src/lib/socks.c new file mode 100644 index 0000000..9dfe097 --- /dev/null +++ b/libcurl/src/lib/socks.c @@ -0,0 +1,755 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_PROXY) + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "strequal.h" +#include "select.h" +#include "connect.h" +#include "timeval.h" +#include "socks.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Helper read-from-socket functions. Does the same as Curl_read() but it + * blocks until all bytes amount of buffersize will be read. No more, no less. + * + * This is STUPID BLOCKING behaviour which we frown upon, but right now this + * is what we have... + */ +int Curl_blockread_all(struct connectdata *conn, /* connection data */ + curl_socket_t sockfd, /* read from this socket */ + char *buf, /* store read data here */ + ssize_t buffersize, /* max amount to read */ + ssize_t *n) /* amount bytes read */ +{ + ssize_t nread; + ssize_t allread = 0; + int result; + long timeleft; + *n = 0; + for(;;) { + timeleft = Curl_timeleft(conn->data, NULL, TRUE); + if(timeleft < 0) { + /* we already got the timeout */ + result = CURLE_OPERATION_TIMEDOUT; + break; + } + if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, timeleft) <= 0) { + result = ~CURLE_OK; + break; + } + result = Curl_read_plain(sockfd, buf, buffersize, &nread); + if(CURLE_AGAIN == result) + continue; + else if(result) + break; + + if(buffersize == nread) { + allread += nread; + *n = allread; + result = CURLE_OK; + break; + } + if(!nread) { + result = ~CURLE_OK; + break; + } + + buffersize -= nread; + buf += nread; + allread += nread; + } + return result; +} + +/* +* This function logs in to a SOCKS4 proxy and sends the specifics to the final +* destination server. +* +* Reference : +* http://socks.permeo.com/protocol/socks4.protocol +* +* Note : +* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)" +* Nonsupport "Identification Protocol (RFC1413)" +*/ +CURL_STATIC CURLcode Curl_SOCKS4(const char *proxy_name, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn, + bool protocol4a) +{ +#define SOCKS4REQLEN 262 + unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user + id */ + int result; + CURLcode code; + curl_socket_t sock = conn->sock[sockindex]; + struct SessionHandle *data = conn->data; + + if(Curl_timeleft(data, NULL, TRUE) < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + (void)curlx_nonblock(sock, FALSE); + + infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); + + /* + * Compose socks4 request + * + * Request format + * + * +----+----+----+----+----+----+----+----+----+----+....+----+ + * | VN | CD | DSTPORT | DSTIP | USERID |NULL| + * +----+----+----+----+----+----+----+----+----+----+....+----+ + * # of bytes: 1 1 2 4 variable 1 + */ + + socksreq[0] = 4; /* version (SOCKS4) */ + socksreq[1] = 1; /* connect */ + socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ + socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + + /* DNS resolve only for SOCKS4, not SOCKS4a */ + if(!protocol4a) { + struct Curl_dns_entry *dns; + Curl_addrinfo *hp=NULL; + int rc; + + rc = Curl_resolv(conn, hostname, remote_port, &dns); + + if(rc == CURLRESOLV_ERROR) + return CURLE_COULDNT_RESOLVE_PROXY; + + if(rc == CURLRESOLV_PENDING) + /* ignores the return code, but 'dns' remains NULL on failure */ + (void)Curl_resolver_wait_resolv(conn, &dns); + + /* + * We cannot use 'hostent' as a struct that Curl_resolv() returns. It + * returns a Curl_addrinfo pointer that may not always look the same. + */ + if(dns) + hp=dns->addr; + if(hp) { + char buf[64]; + unsigned short ip[4]; + Curl_printable_address(hp, buf, sizeof(buf)); + + if(4 == sscanf( buf, "%hu.%hu.%hu.%hu", + &ip[0], &ip[1], &ip[2], &ip[3])) { + /* Set DSTIP */ + socksreq[4] = (unsigned char)ip[0]; + socksreq[5] = (unsigned char)ip[1]; + socksreq[6] = (unsigned char)ip[2]; + socksreq[7] = (unsigned char)ip[3]; + } + else + hp = NULL; /* fail! */ + + infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf); + + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + + } + if(!hp) { + failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.", + hostname); + return CURLE_COULDNT_RESOLVE_HOST; + } + } + + /* + * This is currently not supporting "Identification Protocol (RFC1413)". + */ + socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ + if(proxy_name) { + size_t plen = strlen(proxy_name); + if(plen >= sizeof(socksreq) - 8) { + failf(data, "Too long SOCKS proxy name, can't use!\n"); + return CURLE_COULDNT_CONNECT; + } + /* copy the proxy name WITH trailing zero */ + memcpy(socksreq + 8, proxy_name, plen+1); + } + + /* + * Make connection + */ + { + ssize_t actualread; + ssize_t written; + ssize_t hostnamelen = 0; + int packetsize = 9 + + (int)strlen((char*)socksreq + 8); /* size including NUL */ + + /* If SOCKS4a, set special invalid IP address 0.0.0.x */ + if(protocol4a) { + socksreq[4] = 0; + socksreq[5] = 0; + socksreq[6] = 0; + socksreq[7] = 1; + /* If still enough room in buffer, also append hostname */ + hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ + if(packetsize + hostnamelen <= SOCKS4REQLEN) + strcpy((char*)socksreq + packetsize, hostname); + else + hostnamelen = 0; /* Flag: hostname did not fit in buffer */ + } + + /* Send request */ + code = Curl_write_plain(conn, sock, (char *)socksreq, + packetsize + hostnamelen, + &written); + if(code || (written != packetsize + hostnamelen)) { + failf(data, "Failed to send SOCKS4 connect request."); + return CURLE_COULDNT_CONNECT; + } + if(protocol4a && hostnamelen == 0) { + /* SOCKS4a with very long hostname - send that name separately */ + hostnamelen = (ssize_t)strlen(hostname) + 1; + code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen, + &written); + if(code || (written != hostnamelen)) { + failf(data, "Failed to send SOCKS4 connect request."); + return CURLE_COULDNT_CONNECT; + } + } + + packetsize = 8; /* receive data size */ + + /* Receive response */ + result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize, + &actualread); + if(result || (actualread != packetsize)) { + failf(data, "Failed to receive SOCKS4 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + + /* + * Response format + * + * +----+----+----+----+----+----+----+----+ + * | VN | CD | DSTPORT | DSTIP | + * +----+----+----+----+----+----+----+----+ + * # of bytes: 1 1 2 4 + * + * VN is the version of the reply code and should be 0. CD is the result + * code with one of the following values: + * + * 90: request granted + * 91: request rejected or failed + * 92: request rejected because SOCKS server cannot connect to + * identd on the client + * 93: request rejected because the client program and identd + * report different user-ids + */ + + /* wrong version ? */ + if(socksreq[0] != 0) { + failf(data, + "SOCKS4 reply has wrong version, version should be 4."); + return CURLE_COULDNT_CONNECT; + } + + /* Result */ + switch(socksreq[1]) { + case 90: + infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":""); + break; + case 91: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected or failed.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + ((socksreq[8] << 8) | socksreq[9]), + socksreq[1]); + return CURLE_COULDNT_CONNECT; + case 92: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected because SOCKS server cannot connect to " + "identd on the client.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + ((socksreq[8] << 8) | socksreq[9]), + socksreq[1]); + return CURLE_COULDNT_CONNECT; + case 93: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected because the client program and identd " + "report different user-ids.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + ((socksreq[8] << 8) | socksreq[9]), + socksreq[1]); + return CURLE_COULDNT_CONNECT; + default: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", Unknown.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + ((socksreq[8] << 8) | socksreq[9]), + socksreq[1]); + return CURLE_COULDNT_CONNECT; + } + } + + (void)curlx_nonblock(sock, TRUE); + + return CURLE_OK; /* Proxy was successful! */ +} + +/* + * This function logs in to a SOCKS5 proxy and sends the specifics to the final + * destination server. + */ +CURLcode Curl_SOCKS5(const char *proxy_name, + const char *proxy_password, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn) +{ + /* + According to the RFC1928, section "6. Replies". This is what a SOCK5 + replies: + + +----+-----+-------+------+----------+----------+ + |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + Where: + + o VER protocol version: X'05' + o REP Reply field: + o X'00' succeeded + */ + + unsigned char socksreq[600]; /* room for large user/pw (255 max each) */ + ssize_t actualread; + ssize_t written; + int result; + CURLcode code; + curl_socket_t sock = conn->sock[sockindex]; + struct SessionHandle *data = conn->data; + long timeout; + bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE; + const size_t hostname_len = strlen(hostname); + ssize_t len = 0; + + /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ + if(!socks5_resolve_local && hostname_len > 255) { + infof(conn->data, "SOCKS5: server resolving disabled for hostnames of " + "length > 255 [actual len=%zu]\n", hostname_len); + socks5_resolve_local = TRUE; + } + + /* get timeout */ + timeout = Curl_timeleft(data, NULL, TRUE); + + if(timeout < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + (void)curlx_nonblock(sock, TRUE); + + /* wait until socket gets connected */ + result = Curl_socket_ready(CURL_SOCKET_BAD, sock, timeout); + + if(-1 == result) { + failf(conn->data, "SOCKS5: no connection here"); + return CURLE_COULDNT_CONNECT; + } + else if(0 == result) { + failf(conn->data, "SOCKS5: connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(result & CURL_CSELECT_ERR) { + failf(conn->data, "SOCKS5: error occurred during connection"); + return CURLE_COULDNT_CONNECT; + } + + socksreq[0] = 5; /* version */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + socksreq[1] = (char)(proxy_name ? 3 : 2); /* number of methods (below) */ + socksreq[2] = 0; /* no authentication */ + socksreq[3] = 1; /* GSS-API */ + socksreq[4] = 2; /* username/password */ +#else + socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */ + socksreq[2] = 0; /* no authentication */ + socksreq[3] = 2; /* username/password */ +#endif + + (void)curlx_nonblock(sock, FALSE); + + code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]), + &written); + if(code || (written != (2 + (int)socksreq[1]))) { + failf(data, "Unable to send initial SOCKS5 request."); + return CURLE_COULDNT_CONNECT; + } + + (void)curlx_nonblock(sock, TRUE); + + result = Curl_socket_ready(sock, CURL_SOCKET_BAD, timeout); + + if(-1 == result) { + failf(conn->data, "SOCKS5 nothing to read"); + return CURLE_COULDNT_CONNECT; + } + else if(0 == result) { + failf(conn->data, "SOCKS5 read timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(result & CURL_CSELECT_ERR) { + failf(conn->data, "SOCKS5 read error occurred"); + return CURLE_RECV_ERROR; + } + + (void)curlx_nonblock(sock, FALSE); + + result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread); + if(result || (actualread != 2)) { + failf(data, "Unable to receive initial SOCKS5 response."); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[0] != 5) { + failf(data, "Received invalid version in initial SOCKS5 response."); + return CURLE_COULDNT_CONNECT; + } + if(socksreq[1] == 0) { + /* Nothing to do, no authentication needed */ + ; + } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + else if(socksreq[1] == 1) { + code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn); + if(code) { + failf(data, "Unable to negotiate SOCKS5 GSS-API context."); + return CURLE_COULDNT_CONNECT; + } + } +#endif + else if(socksreq[1] == 2) { + /* Needs user name and password */ + size_t proxy_name_len, proxy_password_len; + if(proxy_name && proxy_password) { + proxy_name_len = strlen(proxy_name); + proxy_password_len = strlen(proxy_password); + } + else { + proxy_name_len = 0; + proxy_password_len = 0; + } + + /* username/password request looks like + * +----+------+----------+------+----------+ + * |VER | ULEN | UNAME | PLEN | PASSWD | + * +----+------+----------+------+----------+ + * | 1 | 1 | 1 to 255 | 1 | 1 to 255 | + * +----+------+----------+------+----------+ + */ + len = 0; + socksreq[len++] = 1; /* username/pw subnegotiation version */ + socksreq[len++] = (unsigned char) proxy_name_len; + if(proxy_name && proxy_name_len) + memcpy(socksreq + len, proxy_name, proxy_name_len); + len += proxy_name_len; + socksreq[len++] = (unsigned char) proxy_password_len; + if(proxy_password && proxy_password_len) + memcpy(socksreq + len, proxy_password, proxy_password_len); + len += proxy_password_len; + + code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); + if(code || (len != written)) { + failf(data, "Failed to send SOCKS5 sub-negotiation request."); + return CURLE_COULDNT_CONNECT; + } + + result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread); + if(result || (actualread != 2)) { + failf(data, "Unable to receive SOCKS5 sub-negotiation response."); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] != 0) { /* status */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + return CURLE_COULDNT_CONNECT; + } + + /* Everything is good so far, user was authenticated! */ + } + else { + /* error */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(socksreq[1] == 255) { +#else + if(socksreq[1] == 1) { + failf(data, + "SOCKS5 GSSAPI per-message authentication is not supported."); + return CURLE_COULDNT_CONNECT; + } + else if(socksreq[1] == 255) { +#endif + if(!proxy_name || !*proxy_name) { + failf(data, + "No authentication method was acceptable. (It is quite likely" + " that the SOCKS5 server wanted a username/password, since none" + " was supplied to the server on this connection.)"); + } + else { + failf(data, "No authentication method was acceptable."); + } + return CURLE_COULDNT_CONNECT; + } + else { + failf(data, + "Undocumented SOCKS5 mode attempted to be used by server."); + return CURLE_COULDNT_CONNECT; + } + } + + /* Authentication is complete, now specify destination to the proxy */ + len = 0; + socksreq[len++] = 5; /* version (SOCKS5) */ + socksreq[len++] = 1; /* connect */ + socksreq[len++] = 0; /* must be zero */ + + if(!socks5_resolve_local) { + socksreq[len++] = 3; /* ATYP: domain name = 3 */ + socksreq[len++] = (char) hostname_len; /* address length */ + memcpy(&socksreq[len], hostname, hostname_len); /* address str w/o NULL */ + len += hostname_len; + } + else { + struct Curl_dns_entry *dns; + Curl_addrinfo *hp = NULL; + int rc = Curl_resolv(conn, hostname, remote_port, &dns); + + if(rc == CURLRESOLV_ERROR) + return CURLE_COULDNT_RESOLVE_HOST; + + if(rc == CURLRESOLV_PENDING) { + /* this requires that we're in "wait for resolve" state */ + code = Curl_resolver_wait_resolv(conn, &dns); + if(code) + return code; + } + + /* + * We cannot use 'hostent' as a struct that Curl_resolv() returns. It + * returns a Curl_addrinfo pointer that may not always look the same. + */ + if(dns) + hp=dns->addr; + if(hp) { + struct sockaddr_in *saddr_in; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *saddr_in6; +#endif + int i; + + if(hp->ai_family == AF_INET) { + socksreq[len++] = 1; /* ATYP: IPv4 = 1 */ + + saddr_in = (struct sockaddr_in*)hp->ai_addr; + for(i = 0; i < 4; i++) { + socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i]; + infof(data, "%d\n", socksreq[len-1]); + } + } +#ifdef ENABLE_IPV6 + else if(hp->ai_family == AF_INET6) { + socksreq[len++] = 4; /* ATYP: IPv6 = 4 */ + + saddr_in6 = (struct sockaddr_in6*)hp->ai_addr; + for(i = 0; i < 16; i++) { + socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i]; + } + } +#endif + else + hp = NULL; /* fail! */ + + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + } + if(!hp) { + failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", + hostname); + return CURLE_COULDNT_RESOLVE_HOST; + } + } + + socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ + socksreq[len++] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 GSS-API protection not yet implemented."); + } + else +#endif + code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); + + if(code || (len != written)) { + failf(data, "Failed to send SOCKS5 connect request."); + return CURLE_COULDNT_CONNECT; + } + + len = 10; /* minimum packet size is 10 */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 GSS-API protection not yet implemented."); + } + else +#endif + result = Curl_blockread_all(conn, sock, (char *)socksreq, + len, &actualread); + + if(result || (len != actualread)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[0] != 5) { /* version */ + failf(data, + "SOCKS5 reply has wrong version, version should be 5."); + return CURLE_COULDNT_CONNECT; + } + if(socksreq[1] != 0) { /* Anything besides 0 is an error */ + if(socksreq[3] == 1) { + failf(data, + "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + ((socksreq[8] << 8) | socksreq[9]), + socksreq[1]); + } + else if(socksreq[3] == 3) { + failf(data, + "Can't complete SOCKS5 connection to %s:%d. (%d)", + hostname, + ((socksreq[8] << 8) | socksreq[9]), + socksreq[1]); + } + else if(socksreq[3] == 4) { + failf(data, + "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:" + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (unsigned char)socksreq[8], (unsigned char)socksreq[9], + (unsigned char)socksreq[10], (unsigned char)socksreq[11], + (unsigned char)socksreq[12], (unsigned char)socksreq[13], + (unsigned char)socksreq[14], (unsigned char)socksreq[15], + (unsigned char)socksreq[16], (unsigned char)socksreq[17], + (unsigned char)socksreq[18], (unsigned char)socksreq[19], + ((socksreq[8] << 8) | socksreq[9]), + socksreq[1]); + } + return CURLE_COULDNT_CONNECT; + } + + /* Fix: in general, returned BND.ADDR is variable length parameter by RFC + 1928, so the reply packet should be read until the end to avoid errors at + subsequent protocol level. + + +----+-----+-------+------+----------+----------+ + |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + ATYP: + o IP v4 address: X'01', BND.ADDR = 4 byte + o domain name: X'03', BND.ADDR = [ 1 byte length, string ] + o IP v6 address: X'04', BND.ADDR = 16 byte + */ + + /* Calculate real packet size */ + if(socksreq[3] == 3) { + /* domain name */ + int addrlen = (int) socksreq[4]; + len = 5 + addrlen + 2; + } + else if(socksreq[3] == 4) { + /* IPv6 */ + len = 4 + 16 + 2; + } + + /* At this point we already read first 10 bytes */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(!conn->socks5_gssapi_enctype) { + /* decrypt_gssapi_blockread already read the whole packet */ +#endif + if(len > 10) { + len -= 10; + result = Curl_blockread_all(conn, sock, (char *)&socksreq[10], + len, &actualread); + if(result || (len != actualread)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + } +#endif + + (void)curlx_nonblock(sock, TRUE); + return CURLE_OK; /* Proxy was successful! */ +} + +#endif /* CURL_DISABLE_PROXY */ + diff --git a/libcurl/src/lib/socks.h b/libcurl/src/lib/socks.h new file mode 100644 index 0000000..39fdfe6 --- /dev/null +++ b/libcurl/src/lib/socks.h @@ -0,0 +1,77 @@ +#ifndef HEADER_CURL_SOCKS_H +#define HEADER_CURL_SOCKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DISABLE_PROXY +#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN +#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN +#else +/* + * Helper read-from-socket functions. Does the same as Curl_read() but it + * blocks until all bytes amount of buffersize will be read. No more, no less. + * + * This is STUPID BLOCKING behaviour which we frown upon, but right now this + * is what we have... + */ +CURL_STATIC int Curl_blockread_all(struct connectdata *conn, + curl_socket_t sockfd, + char *buf, + ssize_t buffersize, + ssize_t *n); + +/* + * This function logs in to a SOCKS4(a) proxy and sends the specifics to the + * final destination server. + */ +CURL_STATIC CURLcode Curl_SOCKS4(const char *proxy_name, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn, + bool protocol4a); + +/* + * This function logs in to a SOCKS5 proxy and sends the specifics to the + * final destination server. + */ +CURL_STATIC CURLcode Curl_SOCKS5(const char *proxy_name, + const char *proxy_password, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn); + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) +/* + * This function handles the SOCKS5 GSS-API negotiation and initialisation + */ +CURL_STATIC CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn); +#endif + +#endif /* CURL_DISABLE_PROXY */ + +#endif /* HEADER_CURL_SOCKS_H */ + diff --git a/libcurl/src/lib/socks_gssapi.c b/libcurl/src/lib/socks_gssapi.c new file mode 100644 index 0000000..fb30b23 --- /dev/null +++ b/libcurl/src/lib/socks_gssapi.c @@ -0,0 +1,522 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009, 2011, Markus Moeller, + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_PROXY) + +#include "curl_gssapi.h" +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "timeval.h" +#include "socks.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; + +/* + * Helper GSS-API error functions. + */ +static int check_gss_err(struct SessionHandle *data, + OM_uint32 major_status, + OM_uint32 minor_status, + const char* function) +{ + if(GSS_ERROR(major_status)) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char buf[1024]; + size_t len; + + len = 0; + msg_ctx = 0; + while(!msg_ctx) { + /* convert major status code (GSS-API error) to text */ + maj_stat = gss_display_status(&min_stat, major_status, + GSS_C_GSS_CODE, + GSS_C_NULL_OID, + &msg_ctx, &status_string); + if(maj_stat == GSS_S_COMPLETE) { + if(sizeof(buf) > len + status_string.length + 1) { + strcpy(buf+len, (char*) status_string.value); + len += status_string.length; + } + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + if(sizeof(buf) > len + 3) { + strcpy(buf+len, ".\n"); + len += 2; + } + msg_ctx = 0; + while(!msg_ctx) { + /* convert minor status code (underlying routine error) to text */ + maj_stat = gss_display_status(&min_stat, minor_status, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, &status_string); + if(maj_stat == GSS_S_COMPLETE) { + if(sizeof(buf) > len + status_string.length) + strcpy(buf+len, (char*) status_string.value); + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + failf(data, "GSS-API error: %s failed:\n%s", function, buf); + return 1; + } + + return 0; +} + +CURL_STATIC CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + curl_socket_t sock = conn->sock[sockindex]; + CURLcode code; + ssize_t actualread; + ssize_t written; + int result; + OM_uint32 gss_major_status, gss_minor_status, gss_status; + OM_uint32 gss_ret_flags; + int gss_conf_state, gss_enc; + gss_buffer_desc service = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_send_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_recv_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_w_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc* gss_token = GSS_C_NO_BUFFER; + gss_name_t server = GSS_C_NO_NAME; + gss_name_t gss_client_name = GSS_C_NO_NAME; + unsigned short us_length; + char *user=NULL; + unsigned char socksreq[4]; /* room for GSS-API exchange header only */ + char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE]; + + /* GSS-API request looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + /* prepare service name */ + if(strchr(serviceptr, '/')) { + service.value = malloc(strlen(serviceptr)); + if(!service.value) + return CURLE_OUT_OF_MEMORY; + service.length = strlen(serviceptr); + memcpy(service.value, serviceptr, service.length); + + gss_major_status = gss_import_name(&gss_minor_status, &service, + (gss_OID) GSS_C_NULL_OID, &server); + } + else { + service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2); + if(!service.value) + return CURLE_OUT_OF_MEMORY; + service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1; + snprintf(service.value, service.length+1, "%s@%s", + serviceptr, conn->proxy.name); + + gss_major_status = gss_import_name(&gss_minor_status, &service, + GSS_C_NT_HOSTBASED_SERVICE, &server); + } + + gss_release_buffer(&gss_status, &service); /* clear allocated memory */ + + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_import_name()")) { + failf(data, "Failed to create service name."); + gss_release_name(&gss_status, &server); + return CURLE_COULDNT_CONNECT; + } + + /* As long as we need to keep sending some context info, and there's no */ + /* errors, keep sending it... */ + for(;;) { + gss_major_status = Curl_gss_init_sec_context(data, + &gss_minor_status, + &gss_context, + server, + &Curl_krb5_mech_oid, + NULL, + gss_token, + &gss_send_token, + TRUE, + &gss_ret_flags); + + if(gss_token != GSS_C_NO_BUFFER) + gss_release_buffer(&gss_status, &gss_recv_token); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_init_sec_context")) { + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to initial GSS-API token."); + return CURLE_COULDNT_CONNECT; + } + + if(gss_send_token.length != 0) { + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 1; /* authentication message type */ + us_length = htons((short)gss_send_token.length); + memcpy(socksreq+2, &us_length, sizeof(short)); + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send GSS-API authentication request."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + code = Curl_write_plain(conn, sock, (char *)gss_send_token.value, + gss_send_token.length, &written); + + if(code || ((ssize_t)gss_send_token.length != written)) { + failf(data, "Failed to send GSS-API authentication token."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + } + + gss_release_buffer(&gss_status, &gss_send_token); + gss_release_buffer(&gss_status, &gss_recv_token); + if(gss_major_status != GSS_S_CONTINUE_NEEDED) break; + + /* analyse response */ + + /* GSS-API response looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive GSS-API authentication response."); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 1) { /* status / messgae type */ + failf(data, "Invalid GSS-API authentication response type (%d %d).", + socksreq[0], socksreq[1]); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq+2, sizeof(short)); + us_length = ntohs(us_length); + + gss_recv_token.length=us_length; + gss_recv_token.value=malloc(us_length); + if(!gss_recv_token.value) { + failf(data, + "Could not allocate memory for GSS-API authentication " + "response token."); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + + result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, + gss_recv_token.length, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive GSS-API authentication token."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + gss_token = &gss_recv_token; + } + + gss_release_name(&gss_status, &server); + + /* Everything is good so far, user was authenticated! */ + gss_major_status = gss_inquire_context (&gss_minor_status, gss_context, + &gss_client_name, NULL, NULL, NULL, + NULL, NULL, NULL); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_inquire_context")) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + gss_major_status = gss_display_name(&gss_minor_status, gss_client_name, + &gss_send_token, NULL); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_display_name")) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + user=malloc(gss_send_token.length+1); + if(!user) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(user, gss_send_token.value, gss_send_token.length); + user[gss_send_token.length] = '\0'; + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user); + free(user); + user=NULL; + + /* Do encryption */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 2; /* encryption message type */ + + gss_enc = 0; /* no data protection */ + /* do confidentiality protection if supported */ + if(gss_ret_flags & GSS_C_CONF_FLAG) + gss_enc = 2; + /* else do integrity protection */ + else if(gss_ret_flags & GSS_C_INTEG_FLAG) + gss_enc = 1; + + infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", + (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality")); + /* force for the moment to no data protection */ + gss_enc = 0; + /* + * Sending the encryption type in clear seems wrong. It should be + * protected with gss_seal()/gss_wrap(). See RFC1961 extract below + * The NEC reference implementations on which this is based is + * therefore at fault + * + * +------+------+------+.......................+ + * + ver | mtyp | len | token | + * +------+------+------+.......................+ + * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | + * +------+------+------+.......................+ + * + * Where: + * + * - "ver" is the protocol version number, here 1 to represent the + * first version of the SOCKS/GSS-API protocol + * + * - "mtyp" is the message type, here 2 to represent a protection + * -level negotiation message + * + * - "len" is the length of the "token" field in octets + * + * - "token" is the GSS-API encapsulated protection level + * + * The token is produced by encapsulating an octet containing the + * required protection level using gss_seal()/gss_wrap() with conf_req + * set to FALSE. The token is verified using gss_unseal()/ + * gss_unwrap(). + * + */ + if(data->set.socks5_gssapi_nec) { + us_length = htons((short)1); + memcpy(socksreq+2, &us_length, sizeof(short)); + } + else { + gss_send_token.length = 1; + gss_send_token.value = malloc(1); + if(!gss_send_token.value) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + memcpy(gss_send_token.value, &gss_enc, 1); + + gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0, + GSS_C_QOP_DEFAULT, &gss_send_token, + &gss_conf_state, &gss_w_token); + + if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_wrap")) { + gss_release_buffer(&gss_status, &gss_send_token); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to wrap GSS-API encryption value into token."); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_send_token); + + us_length = htons((short)gss_w_token.length); + memcpy(socksreq+2, &us_length, sizeof(short)); + } + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send GSS-API encryption request."); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(data->set.socks5_gssapi_nec) { + memcpy(socksreq, &gss_enc, 1); + code = Curl_write_plain(conn, sock, socksreq, 1, &written); + if(code || ( 1 != written)) { + failf(data, "Failed to send GSS-API encryption type."); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + } + else { + code = Curl_write_plain(conn, sock, (char *)gss_w_token.value, + gss_w_token.length, &written); + if(code || ((ssize_t)gss_w_token.length != written)) { + failf(data, "Failed to send GSS-API encryption type."); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_w_token); + } + + result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive GSS-API encryption response."); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 2) { /* status / messgae type */ + failf(data, "Invalid GSS-API encryption response type (%d %d).", + socksreq[0], socksreq[1]); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq+2, sizeof(short)); + us_length = ntohs(us_length); + + gss_recv_token.length= us_length; + gss_recv_token.value=malloc(gss_recv_token.length); + if(!gss_recv_token.value) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, + gss_recv_token.length, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive GSS-API encryptrion type."); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(!data->set.socks5_gssapi_nec) { + gss_major_status = gss_unwrap(&gss_minor_status, gss_context, + &gss_recv_token, &gss_w_token, + 0, GSS_C_QOP_DEFAULT); + + if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_unwrap")) { + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to unwrap GSS-API encryption value into token."); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_recv_token); + + if(gss_w_token.length != 1) { + failf(data, "Invalid GSS-API encryption response length (%d).", + gss_w_token.length); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, gss_w_token.value, gss_w_token.length); + gss_release_buffer(&gss_status, &gss_w_token); + } + else { + if(gss_recv_token.length != 1) { + failf(data, "Invalid GSS-API encryption response length (%d).", + gss_recv_token.length); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, gss_recv_token.value, gss_recv_token.length); + gss_release_buffer(&gss_status, &gss_recv_token); + } + + infof(data, "SOCKS5 access with%s protection granted.\n", + (socksreq[0]==0)?"out GSS-API data": + ((socksreq[0]==1)?" GSS-API integrity":" GSS-API confidentiality")); + + conn->socks5_gssapi_enctype = socksreq[0]; + if(socksreq[0] == 0) + gss_delete_sec_context(&gss_status, &gss_context, NULL); + + return CURLE_OK; +} + +#endif /* HAVE_GSSAPI && !CURL_DISABLE_PROXY */ diff --git a/libcurl/src/lib/socks_sspi.c b/libcurl/src/lib/socks_sspi.c new file mode 100644 index 0000000..2ada80a --- /dev/null +++ b/libcurl/src/lib/socks_sspi.c @@ -0,0 +1,601 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2009, 2011, Markus Moeller, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY) + +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "strerror.h" +#include "timeval.h" +#include "socks.h" +#include "curl_sspi.h" +#include "curl_multibyte.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Helper sspi error functions. + */ +static int check_sspi_err(struct connectdata *conn, + SECURITY_STATUS status, + const char* function) +{ + if(status != SEC_E_OK && + status != SEC_I_COMPLETE_AND_CONTINUE && + status != SEC_I_COMPLETE_NEEDED && + status != SEC_I_CONTINUE_NEEDED) { + failf(conn->data, "SSPI error: %s failed: %s", function, + Curl_sspi_strerror(conn, status)); + return 1; + } + return 0; +} + +/* This is the SSPI-using version of this function */ +CURL_STATIC CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + curl_socket_t sock = conn->sock[sockindex]; + CURLcode code; + ssize_t actualread; + ssize_t written; + int result; + /* Needs GSS-API authentication */ + SECURITY_STATUS status; + unsigned long sspi_ret_flags = 0; + int gss_enc; + SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3]; + SecBufferDesc input_desc, output_desc, wrap_desc; + SecPkgContext_Sizes sspi_sizes; + CredHandle cred_handle; + CtxtHandle sspi_context; + PCtxtHandle context_handle = NULL; + SecPkgCredentials_Names names; + TimeStamp expiry; + char *service_name = NULL; + unsigned short us_length; + unsigned long qop; + unsigned char socksreq[4]; /* room for GSS-API exchange header only */ + char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE]; + + /* GSS-API request looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + /* prepare service name */ + if(strchr(service, '/')) { + service_name = malloc(strlen(service)); + if(!service_name) + return CURLE_OUT_OF_MEMORY; + memcpy(service_name, service, strlen(service)); + } + else { + service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2); + if(!service_name) + return CURLE_OUT_OF_MEMORY; + snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2, + "%s/%s", service, conn->proxy.name); + } + + input_desc.cBuffers = 1; + input_desc.pBuffers = &sspi_recv_token; + input_desc.ulVersion = SECBUFFER_VERSION; + + sspi_recv_token.BufferType = SECBUFFER_TOKEN; + sspi_recv_token.cbBuffer = 0; + sspi_recv_token.pvBuffer = NULL; + + output_desc.cBuffers = 1; + output_desc.pBuffers = &sspi_send_token; + output_desc.ulVersion = SECBUFFER_VERSION; + + sspi_send_token.BufferType = SECBUFFER_TOKEN; + sspi_send_token.cbBuffer = 0; + sspi_send_token.pvBuffer = NULL; + + wrap_desc.cBuffers = 3; + wrap_desc.pBuffers = sspi_w_token; + wrap_desc.ulVersion = SECBUFFER_VERSION; + + cred_handle.dwLower = 0; + cred_handle.dwUpper = 0; + + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT("Kerberos"), + SECPKG_CRED_OUTBOUND, + NULL, + NULL, + NULL, + NULL, + &cred_handle, + &expiry); + + if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) { + failf(data, "Failed to acquire credentials."); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + return CURLE_COULDNT_CONNECT; + } + + /* As long as we need to keep sending some context info, and there's no */ + /* errors, keep sending it... */ + for(;;) { + TCHAR *sname; + + sname = Curl_convert_UTF8_to_tchar(service_name); + if(!sname) + return CURLE_OUT_OF_MEMORY; + + status = s_pSecFn->InitializeSecurityContext(&cred_handle, + context_handle, + sname, + ISC_REQ_MUTUAL_AUTH | + ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_CONFIDENTIALITY | + ISC_REQ_REPLAY_DETECT, + 0, + SECURITY_NATIVE_DREP, + &input_desc, + 0, + &sspi_context, + &output_desc, + &sspi_ret_flags, + &expiry); + + Curl_unicodefree(sname); + + if(sspi_recv_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + sspi_recv_token.pvBuffer = NULL; + sspi_recv_token.cbBuffer = 0; + } + + if(check_sspi_err(conn, status, "InitializeSecurityContext")) { + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + failf(data, "Failed to initialise security context."); + return CURLE_COULDNT_CONNECT; + } + + if(sspi_send_token.cbBuffer != 0) { + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 1; /* authentication message type */ + us_length = htons((short)sspi_send_token.cbBuffer); + memcpy(socksreq+2, &us_length, sizeof(short)); + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send SSPI authentication request."); + free(service_name); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, + sspi_send_token.cbBuffer, &written); + if(code || (sspi_send_token.cbBuffer != (size_t)written)) { + failf(data, "Failed to send SSPI authentication token."); + free(service_name); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + } + + if(sspi_send_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + sspi_send_token.pvBuffer = NULL; + } + sspi_send_token.cbBuffer = 0; + + if(sspi_recv_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + sspi_recv_token.pvBuffer = NULL; + } + sspi_recv_token.cbBuffer = 0; + + if(status != SEC_I_CONTINUE_NEEDED) + break; + + /* analyse response */ + + /* GSS-API response looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive SSPI authentication response."); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 1) { /* status / messgae type */ + failf(data, "Invalid SSPI authentication response type (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq+2, sizeof(short)); + us_length = ntohs(us_length); + + sspi_recv_token.cbBuffer = us_length; + sspi_recv_token.pvBuffer = malloc(us_length); + + if(!sspi_recv_token.pvBuffer) { + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer, + sspi_recv_token.cbBuffer, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive SSPI authentication token."); + free(service_name); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + context_handle = &sspi_context; + } + + free(service_name); + + /* Everything is good so far, user was authenticated! */ + status = s_pSecFn->QueryCredentialsAttributes(&cred_handle, + SECPKG_CRED_ATTR_NAMES, + &names); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + if(check_sspi_err(conn, status, "QueryCredentialAttributes")) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + s_pSecFn->FreeContextBuffer(names.sUserName); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n", + names.sUserName); + s_pSecFn->FreeContextBuffer(names.sUserName); + + /* Do encryption */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 2; /* encryption message type */ + + gss_enc = 0; /* no data protection */ + /* do confidentiality protection if supported */ + if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY) + gss_enc = 2; + /* else do integrity protection */ + else if(sspi_ret_flags & ISC_REQ_INTEGRITY) + gss_enc = 1; + + infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", + (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") ); + /* force to no data protection, avoid encryption/decryption for now */ + gss_enc = 0; + /* + * Sending the encryption type in clear seems wrong. It should be + * protected with gss_seal()/gss_wrap(). See RFC1961 extract below + * The NEC reference implementations on which this is based is + * therefore at fault + * + * +------+------+------+.......................+ + * + ver | mtyp | len | token | + * +------+------+------+.......................+ + * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | + * +------+------+------+.......................+ + * + * Where: + * + * - "ver" is the protocol version number, here 1 to represent the + * first version of the SOCKS/GSS-API protocol + * + * - "mtyp" is the message type, here 2 to represent a protection + * -level negotiation message + * + * - "len" is the length of the "token" field in octets + * + * - "token" is the GSS-API encapsulated protection level + * + * The token is produced by encapsulating an octet containing the + * required protection level using gss_seal()/gss_wrap() with conf_req + * set to FALSE. The token is verified using gss_unseal()/ + * gss_unwrap(). + * + */ + + if(data->set.socks5_gssapi_nec) { + us_length = htons((short)1); + memcpy(socksreq+2, &us_length, sizeof(short)); + } + else { + status = s_pSecFn->QueryContextAttributes(&sspi_context, + SECPKG_ATTR_SIZES, + &sspi_sizes); + if(check_sspi_err(conn, status, "QueryContextAttributes")) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + + sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer; + sspi_w_token[0].BufferType = SECBUFFER_TOKEN; + sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer); + + if(!sspi_w_token[0].pvBuffer) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + sspi_w_token[1].cbBuffer = 1; + sspi_w_token[1].pvBuffer = malloc(1); + if(!sspi_w_token[1].pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1); + sspi_w_token[2].BufferType = SECBUFFER_PADDING; + sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize; + sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize); + if(!sspi_w_token[2].pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + status = s_pSecFn->EncryptMessage(&sspi_context, + KERB_WRAP_NO_ENCRYPT, + &wrap_desc, + 0); + if(check_sspi_err(conn, status, "EncryptMessage")) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer + + sspi_w_token[1].cbBuffer + + sspi_w_token[2].cbBuffer; + sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer); + if(!sspi_send_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer, + sspi_w_token[0].cbBuffer); + memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer, + sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); + memcpy((PUCHAR) sspi_send_token.pvBuffer + +sspi_w_token[0].cbBuffer + +sspi_w_token[1].cbBuffer, + sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer); + + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + sspi_w_token[0].pvBuffer = NULL; + sspi_w_token[0].cbBuffer = 0; + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + sspi_w_token[1].pvBuffer = NULL; + sspi_w_token[1].cbBuffer = 0; + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + sspi_w_token[2].pvBuffer = NULL; + sspi_w_token[2].cbBuffer = 0; + + us_length = htons((short)sspi_send_token.cbBuffer); + memcpy(socksreq+2, &us_length, sizeof(short)); + } + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send SSPI encryption request."); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(data->set.socks5_gssapi_nec) { + memcpy(socksreq, &gss_enc, 1); + code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written); + if(code || (1 != written)) { + failf(data, "Failed to send SSPI encryption type."); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + } + else { + code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, + sspi_send_token.cbBuffer, &written); + if(code || (sspi_send_token.cbBuffer != (size_t)written)) { + failf(data, "Failed to send SSPI encryption type."); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + } + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive SSPI encryption response."); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 2) { /* status / message type */ + failf(data, "Invalid SSPI encryption response type (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq+2, sizeof(short)); + us_length = ntohs(us_length); + + sspi_w_token[0].cbBuffer = us_length; + sspi_w_token[0].pvBuffer = malloc(us_length); + if(!sspi_w_token[0].pvBuffer) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer, + sspi_w_token[0].cbBuffer, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive SSPI encryption type."); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + + if(!data->set.socks5_gssapi_nec) { + wrap_desc.cBuffers = 2; + sspi_w_token[0].BufferType = SECBUFFER_STREAM; + sspi_w_token[1].BufferType = SECBUFFER_DATA; + sspi_w_token[1].cbBuffer = 0; + sspi_w_token[1].pvBuffer = NULL; + + status = s_pSecFn->DecryptMessage(&sspi_context, + &wrap_desc, + 0, + &qop); + + if(check_sspi_err(conn, status, "DecryptMessage")) { + if(sspi_w_token[0].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + if(sspi_w_token[1].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + + if(sspi_w_token[1].cbBuffer != 1) { + failf(data, "Invalid SSPI encryption response length (%lu).", + (unsigned long)sspi_w_token[1].cbBuffer); + if(sspi_w_token[0].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + if(sspi_w_token[1].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + } + else { + if(sspi_w_token[0].cbBuffer != 1) { + failf(data, "Invalid SSPI encryption response length (%lu).", + (unsigned long)sspi_w_token[0].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + } + + infof(data, "SOCKS5 access with%s protection granted.\n", + (socksreq[0]==0)?"out GSS-API data": + ((socksreq[0]==1)?" GSS-API integrity":" GSS-API confidentiality")); + + /* For later use if encryption is required + conn->socks5_gssapi_enctype = socksreq[0]; + if(socksreq[0] != 0) + conn->socks5_sspi_context = sspi_context; + else { + s_pSecFn->DeleteSecurityContext(&sspi_context); + conn->socks5_sspi_context = sspi_context; + } + */ + return CURLE_OK; +} +#endif diff --git a/libcurl/src/lib/speedcheck.c b/libcurl/src/lib/speedcheck.c new file mode 100644 index 0000000..8c27417 --- /dev/null +++ b/libcurl/src/lib/speedcheck.c @@ -0,0 +1,74 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "sendf.h" +#include "multiif.h" +#include "speedcheck.h" + +CURL_STATIC void Curl_speedinit(struct SessionHandle *data) +{ + memset(&data->state.keeps_speed, 0, sizeof(struct timeval)); +} + +CURL_STATIC CURLcode Curl_speedcheck(struct SessionHandle *data, + struct timeval now) +{ + if((data->progress.current_speed >= 0) && + data->set.low_speed_time && + (Curl_tvlong(data->state.keeps_speed) != 0) && + (data->progress.current_speed < data->set.low_speed_limit)) { + long howlong = Curl_tvdiff(now, data->state.keeps_speed); + long nextcheck = (data->set.low_speed_time * 1000) - howlong; + + /* We are now below the "low speed limit". If we are below it + for "low speed time" seconds we consider that enough reason + to abort the download. */ + if(nextcheck <= 0) { + /* we have been this slow for long enough, now die */ + failf(data, + "Operation too slow. " + "Less than %ld bytes/sec transferred the last %ld seconds", + data->set.low_speed_limit, + data->set.low_speed_time); + return CURLE_OPERATION_TIMEDOUT; + } + else { + /* wait complete low_speed_time */ + Curl_expire_latest(data, nextcheck); + } + } + else { + /* we keep up the required speed all right */ + data->state.keeps_speed = now; + + if(data->set.low_speed_limit) + /* if there is a low speed limit enabled, we set the expire timer to + make this connection's speed get checked again no later than when + this time is up */ + Curl_expire_latest(data, data->set.low_speed_time*1000); + } + return CURLE_OK; +} diff --git a/libcurl/src/lib/speedcheck.h b/libcurl/src/lib/speedcheck.h new file mode 100644 index 0000000..f53bdd1 --- /dev/null +++ b/libcurl/src/lib/speedcheck.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_SPEEDCHECK_H +#define HEADER_CURL_SPEEDCHECK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "timeval.h" + +CURL_STATIC void Curl_speedinit(struct SessionHandle *data); +CURL_STATIC CURLcode Curl_speedcheck(struct SessionHandle *data, + struct timeval now); + +#endif /* HEADER_CURL_SPEEDCHECK_H */ diff --git a/libcurl/src/lib/splay.c b/libcurl/src/lib/splay.c new file mode 100644 index 0000000..6f8227e --- /dev/null +++ b/libcurl/src/lib/splay.c @@ -0,0 +1,288 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1997 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "splay.h" + +/* + * This macro compares two node keys i and j and returns: + * + * negative value: when i is smaller than j + * zero : when i is equal to j + * positive when : when i is larger than j + */ +#define compare(i,j) Curl_splaycomparekeys((i),(j)) + +/* + * Splay using the key i (which may or may not be in the tree.) The starting + * root is t. + */ +CURL_STATIC struct Curl_tree *Curl_splay(struct timeval i, + struct Curl_tree *t) +{ + struct Curl_tree N, *l, *r, *y; + long comp; + + if(t == NULL) + return t; + N.smaller = N.larger = NULL; + l = r = &N; + + for(;;) { + comp = compare(i, t->key); + if(comp < 0) { + if(t->smaller == NULL) + break; + if(compare(i, t->smaller->key) < 0) { + y = t->smaller; /* rotate smaller */ + t->smaller = y->larger; + y->larger = t; + t = y; + if(t->smaller == NULL) + break; + } + r->smaller = t; /* link smaller */ + r = t; + t = t->smaller; + } + else if(comp > 0) { + if(t->larger == NULL) + break; + if(compare(i, t->larger->key) > 0) { + y = t->larger; /* rotate larger */ + t->larger = y->smaller; + y->smaller = t; + t = y; + if(t->larger == NULL) + break; + } + l->larger = t; /* link larger */ + l = t; + t = t->larger; + } + else + break; + } + + l->larger = t->smaller; /* assemble */ + r->smaller = t->larger; + t->smaller = N.larger; + t->larger = N.smaller; + + return t; +} + +/* Insert key i into the tree t. Return a pointer to the resulting tree or + * NULL if something went wrong. + * + * @unittest: 1309 + */ +CURL_STATIC struct Curl_tree *Curl_splayinsert(struct timeval i, + struct Curl_tree *t, + struct Curl_tree *node) +{ + static const struct timeval KEY_NOTUSED = {-1, -1}; /* will *NEVER* appear */ + + if(node == NULL) + return t; + + if(t != NULL) { + t = Curl_splay(i, t); + if(compare(i, t->key)==0) { + /* There already exists a node in the tree with the very same key. Build + a linked list of nodes. We make the new 'node' struct the new master + node and make the previous node the first one in the 'same' list. */ + + node->same = t; + node->key = i; + node->smaller = t->smaller; + node->larger = t->larger; + + t->smaller = node; /* in the sub node for this same key, we use the + smaller pointer to point back to the master + node */ + + t->key = KEY_NOTUSED; /* and we set the key in the sub node to NOTUSED + to quickly identify this node as a subnode */ + + return node; /* new root node */ + } + } + + if(t == NULL) { + node->smaller = node->larger = NULL; + } + else if(compare(i, t->key) < 0) { + node->smaller = t->smaller; + node->larger = t; + t->smaller = NULL; + + } + else { + node->larger = t->larger; + node->smaller = t; + t->larger = NULL; + } + node->key = i; + + node->same = NULL; /* no identical node (yet) */ + return node; +} + +/* Finds and deletes the best-fit node from the tree. Return a pointer to the + resulting tree. best-fit means the node with the given or lower key */ +CURL_STATIC struct Curl_tree *Curl_splaygetbest(struct timeval i, + struct Curl_tree *t, + struct Curl_tree **removed) +{ + struct Curl_tree *x; + + if(!t) { + *removed = NULL; /* none removed since there was no root */ + return NULL; + } + + t = Curl_splay(i, t); + if(compare(i, t->key) < 0) { + /* too big node, try the smaller chain */ + if(t->smaller) + t=Curl_splay(t->smaller->key, t); + else { + /* fail */ + *removed = NULL; + return t; + } + } + + if(compare(i, t->key) >= 0) { /* found it */ + /* FIRST! Check if there is a list with identical keys */ + x = t->same; + if(x) { + /* there is, pick one from the list */ + + /* 'x' is the new root node */ + + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + + *removed = t; + return x; /* new root */ + } + + if(t->smaller == NULL) { + x = t->larger; + } + else { + x = Curl_splay(i, t->smaller); + x->larger = t->larger; + } + *removed = t; + + return x; + } + else { + *removed = NULL; /* no match */ + return t; /* It wasn't there */ + } +} + + +/* Deletes the very node we point out from the tree if it's there. Stores a + * pointer to the new resulting tree in 'newroot'. + * + * Returns zero on success and non-zero on errors! TODO: document error codes. + * When returning error, it does not touch the 'newroot' pointer. + * + * NOTE: when the last node of the tree is removed, there's no tree left so + * 'newroot' will be made to point to NULL. + * + * @unittest: 1309 + */ +CURL_STATIC int Curl_splayremovebyaddr(struct Curl_tree *t, + struct Curl_tree *removenode, + struct Curl_tree **newroot) +{ + static const struct timeval KEY_NOTUSED = {-1, -1}; /* will *NEVER* appear */ + struct Curl_tree *x; + + if(!t || !removenode) + return 1; + + if(compare(KEY_NOTUSED, removenode->key) == 0) { + /* Key set to NOTUSED means it is a subnode within a 'same' linked list + and thus we can unlink it easily. The 'smaller' link of a subnode + links to the parent node. */ + if(removenode->smaller == NULL) + return 3; + + removenode->smaller->same = removenode->same; + if(removenode->same) + removenode->same->smaller = removenode->smaller; + + /* Ensures that double-remove gets caught. */ + removenode->smaller = NULL; + + /* voila, we're done! */ + *newroot = t; /* return the same root */ + return 0; + } + + t = Curl_splay(removenode->key, t); + + /* First make sure that we got the same root node as the one we want + to remove, as otherwise we might be trying to remove a node that + isn't actually in the tree. + + We cannot just compare the keys here as a double remove in quick + succession of a node with key != KEY_NOTUSED && same != NULL + could return the same key but a different node. */ + if(t != removenode) + return 2; + + /* Check if there is a list with identical sizes, as then we're trying to + remove the root node of a list of nodes with identical keys. */ + x = t->same; + if(x) { + /* 'x' is the new root node, we just make it use the root node's + smaller/larger links */ + + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + } + else { + /* Remove the root node */ + if(t->smaller == NULL) + x = t->larger; + else { + x = Curl_splay(removenode->key, t->smaller); + x->larger = t->larger; + } + } + + *newroot = x; /* store new root pointer */ + + return 0; +} + diff --git a/libcurl/src/lib/splay.h b/libcurl/src/lib/splay.h new file mode 100644 index 0000000..7ca5ffa --- /dev/null +++ b/libcurl/src/lib/splay.h @@ -0,0 +1,66 @@ +#ifndef HEADER_CURL_SPLAY_H +#define HEADER_CURL_SPLAY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1997 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +struct Curl_tree { + struct Curl_tree *smaller; /* smaller node */ + struct Curl_tree *larger; /* larger node */ + struct Curl_tree *same; /* points to a node with identical key */ + struct timeval key; /* this node's "sort" key */ + void *payload; /* data the splay code doesn't care about */ +}; + +CURL_STATIC struct Curl_tree *Curl_splay(struct timeval i, + struct Curl_tree *t); + +CURL_STATIC struct Curl_tree *Curl_splayinsert(struct timeval key, + struct Curl_tree *t, + struct Curl_tree *newnode); + +#if 0 +CURL_STATIC struct Curl_tree *Curl_splayremove(struct timeval key, + struct Curl_tree *t, + struct Curl_tree **removed); +#endif + +CURL_STATIC struct Curl_tree *Curl_splaygetbest(struct timeval key, + struct Curl_tree *t, + struct Curl_tree **removed); + +CURL_STATIC int Curl_splayremovebyaddr(struct Curl_tree *t, + struct Curl_tree *removenode, + struct Curl_tree **newroot); + +#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \ + ( ((i.tv_sec) > (j.tv_sec)) ? 1 : \ + ( ((i.tv_usec) < (j.tv_usec)) ? -1 : \ + ( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0 )))) + +#ifdef DEBUGBUILD +CURL_STATIC void Curl_splayprint(struct Curl_tree * t, int d, char output); +#else +#define Curl_splayprint(x,y,z) Curl_nop_stmt +#endif + +#endif /* HEADER_CURL_SPLAY_H */ diff --git a/libcurl/src/lib/ssh.c b/libcurl/src/lib/ssh.c new file mode 100644 index 0000000..bd16c7f --- /dev/null +++ b/libcurl/src/lib/ssh.c @@ -0,0 +1,3341 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* #define CURL_LIBSSH2_DEBUG */ + +#include "curl_setup.h" + +#ifdef USE_LIBSSH2 + +#ifdef HAVE_LIMITS_H +# include +#endif + +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "ssh.h" +#include "url.h" +#include "speedcheck.h" +#include "getinfo.h" + +#include "strequal.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "strtoofft.h" +#include "multiif.h" +#include "select.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifdef WIN32 +# undef PATH_MAX +# define PATH_MAX MAX_PATH +# ifndef R_OK +# define R_OK 4 +# endif +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 /* just an extra precaution since there are systems that + have their definition hidden well */ +#endif + +#define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s)) + +#define sftp_libssh2_realpath(s,p,t,m) \ + libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \ + (t), (m), LIBSSH2_SFTP_REALPATH) + +/* Local functions: */ +static const char *sftp_libssh2_strerror(int err); +static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); +static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc); +static LIBSSH2_FREE_FUNC(my_libssh2_free); + +static CURLcode get_pathname(const char **cpp, char **path); + +static CURLcode ssh_connect(struct connectdata *conn, bool *done); +static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done); +static CURLcode ssh_do(struct connectdata *conn, bool *done); + +static CURLcode ssh_getworkingpath(struct connectdata *conn, + char *homedir, /* when SFTP is used */ + char **path); + +static CURLcode scp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode scp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection); + +static CURLcode sftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done); + +static int ssh_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks); + +static int ssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks); + +static CURLcode ssh_setup_connection(struct connectdata *conn); + +/* + * SCP protocol handler. + */ + +const struct Curl_handler Curl_handler_scp = { + "SCP", /* scheme */ + ssh_setup_connection, /* setup_connection */ + ssh_do, /* do_it */ + scp_done, /* done */ + ZERO_NULL, /* do_more */ + ssh_connect, /* connect_it */ + ssh_multi_statemach, /* connecting */ + scp_doing, /* doing */ + ssh_getsock, /* proto_getsock */ + ssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ssh_perform_getsock, /* perform_getsock */ + scp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + + +/* + * SFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_sftp = { + "SFTP", /* scheme */ + ssh_setup_connection, /* setup_connection */ + ssh_do, /* do_it */ + sftp_done, /* done */ + ZERO_NULL, /* do_more */ + ssh_connect, /* connect_it */ + ssh_multi_statemach, /* connecting */ + sftp_doing, /* doing */ + ssh_getsock, /* proto_getsock */ + ssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ssh_perform_getsock, /* perform_getsock */ + sftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + +static void +kbd_callback(const char *name, int name_len, const char *instruction, + int instruction_len, int num_prompts, + const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, + void **abstract) +{ + struct connectdata *conn = (struct connectdata *)*abstract; + +#ifdef CURL_LIBSSH2_DEBUG + fprintf(stderr, "name=%s\n", name); + fprintf(stderr, "name_len=%d\n", name_len); + fprintf(stderr, "instruction=%s\n", instruction); + fprintf(stderr, "instruction_len=%d\n", instruction_len); + fprintf(stderr, "num_prompts=%d\n", num_prompts); +#else + (void)name; + (void)name_len; + (void)instruction; + (void)instruction_len; +#endif /* CURL_LIBSSH2_DEBUG */ + if(num_prompts == 1) { + responses[0].text = strdup(conn->passwd); + responses[0].length = curlx_uztoui(strlen(conn->passwd)); + } + (void)prompts; + (void)abstract; +} /* kbd_callback */ + +static CURLcode sftp_libssh2_error_to_CURLE(int err) +{ + switch (err) { + case LIBSSH2_FX_OK: + return CURLE_OK; + + case LIBSSH2_FX_NO_SUCH_FILE: + case LIBSSH2_FX_NO_SUCH_PATH: + return CURLE_REMOTE_FILE_NOT_FOUND; + + case LIBSSH2_FX_PERMISSION_DENIED: + case LIBSSH2_FX_WRITE_PROTECT: + case LIBSSH2_FX_LOCK_CONFlICT: + return CURLE_REMOTE_ACCESS_DENIED; + + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + case LIBSSH2_FX_QUOTA_EXCEEDED: + return CURLE_REMOTE_DISK_FULL; + + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + return CURLE_REMOTE_FILE_EXISTS; + + case LIBSSH2_FX_DIR_NOT_EMPTY: + return CURLE_QUOTE_ERROR; + + default: + break; + } + + return CURLE_SSH; +} + +static CURLcode libssh2_session_error_to_CURLE(int err) +{ + switch (err) { + /* Ordered by order of appearance in libssh2.h */ + case LIBSSH2_ERROR_NONE: + return CURLE_OK; + + case LIBSSH2_ERROR_SOCKET_NONE: + return CURLE_COULDNT_CONNECT; + + case LIBSSH2_ERROR_ALLOC: + return CURLE_OUT_OF_MEMORY; + + case LIBSSH2_ERROR_SOCKET_SEND: + return CURLE_SEND_ERROR; + + case LIBSSH2_ERROR_HOSTKEY_INIT: + case LIBSSH2_ERROR_HOSTKEY_SIGN: + case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED: + case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: + return CURLE_PEER_FAILED_VERIFICATION; + + case LIBSSH2_ERROR_PASSWORD_EXPIRED: + return CURLE_LOGIN_DENIED; + + case LIBSSH2_ERROR_SOCKET_TIMEOUT: + case LIBSSH2_ERROR_TIMEOUT: + return CURLE_OPERATION_TIMEDOUT; + + case LIBSSH2_ERROR_EAGAIN: + return CURLE_AGAIN; + } + + /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode + error code, and possibly add a few new SSH-related one. We must however + not return or even depend on libssh2 errors in the public libcurl API */ + + return CURLE_SSH; +} + +static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc) +{ + (void)abstract; /* arg not used */ + return malloc(count); +} + +static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc) +{ + (void)abstract; /* arg not used */ + return realloc(ptr, count); +} + +static LIBSSH2_FREE_FUNC(my_libssh2_free) +{ + (void)abstract; /* arg not used */ + if(ptr) /* ssh2 agent sometimes call free with null ptr */ + free(ptr); +} + +/* + * SSH State machine related code + */ +/* This is the ONLY way to change SSH state! */ +static void state(struct connectdata *conn, sshstate nowstate) +{ + struct ssh_conn *sshc = &conn->proto.sshc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "SSH_STOP", + "SSH_INIT", + "SSH_S_STARTUP", + "SSH_HOSTKEY", + "SSH_AUTHLIST", + "SSH_AUTH_PKEY_INIT", + "SSH_AUTH_PKEY", + "SSH_AUTH_PASS_INIT", + "SSH_AUTH_PASS", + "SSH_AUTH_AGENT_INIT", + "SSH_AUTH_AGENT_LIST", + "SSH_AUTH_AGENT", + "SSH_AUTH_HOST_INIT", + "SSH_AUTH_HOST", + "SSH_AUTH_KEY_INIT", + "SSH_AUTH_KEY", + "SSH_AUTH_DONE", + "SSH_SFTP_INIT", + "SSH_SFTP_REALPATH", + "SSH_SFTP_QUOTE_INIT", + "SSH_SFTP_POSTQUOTE_INIT", + "SSH_SFTP_QUOTE", + "SSH_SFTP_NEXT_QUOTE", + "SSH_SFTP_QUOTE_STAT", + "SSH_SFTP_QUOTE_SETSTAT", + "SSH_SFTP_QUOTE_SYMLINK", + "SSH_SFTP_QUOTE_MKDIR", + "SSH_SFTP_QUOTE_RENAME", + "SSH_SFTP_QUOTE_RMDIR", + "SSH_SFTP_QUOTE_UNLINK", + "SSH_SFTP_TRANS_INIT", + "SSH_SFTP_UPLOAD_INIT", + "SSH_SFTP_CREATE_DIRS_INIT", + "SSH_SFTP_CREATE_DIRS", + "SSH_SFTP_CREATE_DIRS_MKDIR", + "SSH_SFTP_READDIR_INIT", + "SSH_SFTP_READDIR", + "SSH_SFTP_READDIR_LINK", + "SSH_SFTP_READDIR_BOTTOM", + "SSH_SFTP_READDIR_DONE", + "SSH_SFTP_DOWNLOAD_INIT", + "SSH_SFTP_DOWNLOAD_STAT", + "SSH_SFTP_CLOSE", + "SSH_SFTP_SHUTDOWN", + "SSH_SCP_TRANS_INIT", + "SSH_SCP_UPLOAD_INIT", + "SSH_SCP_DOWNLOAD_INIT", + "SSH_SCP_DONE", + "SSH_SCP_SEND_EOF", + "SSH_SCP_WAIT_EOF", + "SSH_SCP_WAIT_CLOSE", + "SSH_SCP_CHANNEL_FREE", + "SSH_SESSION_DISCONNECT", + "SSH_SESSION_FREE", + "QUIT" + }; + + if(sshc->state != nowstate) { + infof(conn->data, "SFTP %p state change from %s to %s\n", + (void *)sshc, names[sshc->state], names[nowstate]); + } +#endif + + sshc->state = nowstate; +} + +/* figure out the path to work with in this particular request */ +static CURLcode ssh_getworkingpath(struct connectdata *conn, + char *homedir, /* when SFTP is used */ + char **path) /* returns the allocated + real path to work with */ +{ + struct SessionHandle *data = conn->data; + char *real_path = NULL; + char *working_path; + int working_path_len; + + working_path = curl_easy_unescape(data, data->state.path, 0, + &working_path_len); + if(!working_path) + return CURLE_OUT_OF_MEMORY; + + /* Check for /~/ , indicating relative to the user's home directory */ + if(conn->handler->protocol & CURLPROTO_SCP) { + real_path = malloc(working_path_len+1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) + /* It is referenced to the home directory, so strip the leading '/~/' */ + memcpy(real_path, working_path+3, 4 + working_path_len-3); + else + memcpy(real_path, working_path, 1 + working_path_len); + } + else if(conn->handler->protocol & CURLPROTO_SFTP) { + if((working_path_len > 1) && (working_path[1] == '~')) { + size_t homelen = strlen(homedir); + real_path = malloc(homelen + working_path_len + 1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + /* It is referenced to the home directory, so strip the + leading '/' */ + memcpy(real_path, homedir, homelen); + real_path[homelen] = '/'; + real_path[homelen+1] = '\0'; + if(working_path_len > 3) { + memcpy(real_path+homelen+1, working_path + 3, + 1 + working_path_len -3); + } + } + else { + real_path = malloc(working_path_len+1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + memcpy(real_path, working_path, 1+working_path_len); + } + } + + free(working_path); + + /* store the pointer for the caller to receive */ + *path = real_path; + + return CURLE_OK; +} + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API +static int sshkeycallback(CURL *easy, + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch match, + void *clientp) +{ + (void)easy; + (void)knownkey; + (void)foundkey; + (void)clientp; + + /* we only allow perfect matches, and we reject everything else */ + return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE; +} +#endif + +/* + * Earlier libssh2 versions didn't have the ability to seek to 64bit positions + * with 32bit size_t. + */ +#ifdef HAVE_LIBSSH2_SFTP_SEEK64 +#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y) +#else +#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y) +#endif + +/* + * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit + * architectures so we check of the necessary function is present. + */ +#ifndef HAVE_LIBSSH2_SCP_SEND64 +#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0) +#else +#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \ + (libssh2_uint64_t)d, 0, 0) +#endif + +/* + * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64. + */ +#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE +#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y) +#endif + +static CURLcode ssh_knownhost(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + struct SessionHandle *data = conn->data; + + if(data->set.str[STRING_SSH_KNOWNHOSTS]) { + /* we're asked to verify the host against a file */ + struct ssh_conn *sshc = &conn->proto.sshc; + int rc; + int keytype; + size_t keylen; + const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, + &keylen, &keytype); + int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE; + int keybit = 0; + + if(remotekey) { + /* + * A subject to figure out is what host name we need to pass in here. + * What host name does OpenSSH store in its file if an IDN name is + * used? + */ + struct libssh2_knownhost *host; + enum curl_khmatch keymatch; + curl_sshkeycallback func = + data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback; + struct curl_khkey knownkey; + struct curl_khkey *knownkeyp = NULL; + struct curl_khkey foundkey; + + keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS; + +#ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP + keycheck = libssh2_knownhost_checkp(sshc->kh, + conn->host.name, + (conn->remote_port != PORT_SSH)? + conn->remote_port:-1, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, + &host); +#else + keycheck = libssh2_knownhost_check(sshc->kh, + conn->host.name, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, + &host); +#endif + + infof(data, "SSH host check: %d, key: %s\n", keycheck, + (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? + host->key:""); + + /* setup 'knownkey' */ + if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) { + knownkey.key = host->key; + knownkey.len = 0; + knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + CURLKHTYPE_RSA : CURLKHTYPE_DSS; + knownkeyp = &knownkey; + } + + /* setup 'foundkey' */ + foundkey.key = remotekey; + foundkey.len = keylen; + foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + CURLKHTYPE_RSA : CURLKHTYPE_DSS; + + /* + * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the + * curl_khmatch enum are ever modified, we need to introduce a + * translation table here! + */ + keymatch = (enum curl_khmatch)keycheck; + + /* Ask the callback how to behave */ + rc = func(data, knownkeyp, /* from the knownhosts file */ + &foundkey, /* from the remote host */ + keymatch, data->set.ssh_keyfunc_userp); + } + else + /* no remotekey means failure! */ + rc = CURLKHSTAT_REJECT; + + switch(rc) { + default: /* unknown return codes will equal reject */ + /* FALLTHROUGH */ + case CURLKHSTAT_REJECT: + state(conn, SSH_SESSION_FREE); + /* FALLTHROUGH */ + case CURLKHSTAT_DEFER: + /* DEFER means bail out but keep the SSH_HOSTKEY state */ + result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + break; + case CURLKHSTAT_FINE: + case CURLKHSTAT_FINE_ADD_TO_FILE: + /* proceed */ + if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { + /* the found host+key didn't match but has been told to be fine + anyway so we add it in memory */ + int addrc = libssh2_knownhost_add(sshc->kh, + conn->host.name, NULL, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, NULL); + if(addrc) + infof(data, "Warning adding the known host %s failed!\n", + conn->host.name); + else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) { + /* now we write the entire in-memory list of known hosts to the + known_hosts file */ + int wrc = + libssh2_knownhost_writefile(sshc->kh, + data->set.str[STRING_SSH_KNOWNHOSTS], + LIBSSH2_KNOWNHOST_FILE_OPENSSH); + if(wrc) { + infof(data, "Warning, writing %s failed!\n", + data->set.str[STRING_SSH_KNOWNHOSTS]); + } + } + } + break; + } + } +#else /* HAVE_LIBSSH2_KNOWNHOST_API */ + (void)conn; +#endif + return result; +} + +static CURLcode ssh_check_fingerprint(struct connectdata *conn) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + struct SessionHandle *data = conn->data; + const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; + char md5buffer[33]; + int i; + + const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session, + LIBSSH2_HOSTKEY_HASH_MD5); + + if(fingerprint) { + /* The fingerprint points to static storage (!), don't free() it. */ + for(i = 0; i < 16; i++) + snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]); + infof(data, "SSH MD5 fingerprint: %s\n", md5buffer); + } + + /* Before we authenticate we check the hostkey's MD5 fingerprint + * against a known fingerprint, if available. + */ + if(pubkey_md5 && strlen(pubkey_md5) == 32) { + if(!fingerprint || !strequal(md5buffer, pubkey_md5)) { + if(fingerprint) + failf(data, + "Denied establishing ssh session: mismatch md5 fingerprint. " + "Remote %s is not equal to %s", md5buffer, pubkey_md5); + else + failf(data, + "Denied establishing ssh session: md5 fingerprint not available"); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + return sshc->actualcode; + } + else { + infof(data, "MD5 checksum match!\n"); + /* as we already matched, we skip the check for known hosts */ + return CURLE_OK; + } + } + else + return ssh_knownhost(conn); +} + +/* + * ssh_statemach_act() runs the SSH state machine as far as it can without + * blocking and without reaching the end. The data the pointer 'block' points + * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN + * meaning it wants to be called again when the socket is ready + */ + +static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct SSHPROTO *sftp_scp = data->req.protop; + struct ssh_conn *sshc = &conn->proto.sshc; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + char *new_readdir_line; + int rc = LIBSSH2_ERROR_NONE; + int err; + int seekerr = CURL_SEEKFUNC_OK; + *block = 0; /* we're not blocking by default */ + + do { + + switch(sshc->state) { + case SSH_INIT: + sshc->secondCreateDirs = 0; + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_OK; + + /* Set libssh2 to non-blocking, since everything internally is + non-blocking */ + libssh2_session_set_blocking(sshc->ssh_session, 0); + + state(conn, SSH_S_STARTUP); + /* fall-through */ + + case SSH_S_STARTUP: + rc = libssh2_session_startup(sshc->ssh_session, (int)sock); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc) { + failf(data, "Failure establishing ssh session"); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_FAILED_INIT; + break; + } + + state(conn, SSH_HOSTKEY); + + /* fall-through */ + case SSH_HOSTKEY: + /* + * Before we authenticate we should check the hostkey's fingerprint + * against our known hosts. How that is handled (reading from file, + * whatever) is up to us. + */ + result = ssh_check_fingerprint(conn); + if(!result) + state(conn, SSH_AUTHLIST); + /* ssh_check_fingerprint sets state appropriately on error */ + break; + + case SSH_AUTHLIST: + /* + * Figure out authentication methods + * NB: As soon as we have provided a username to an openssh server we + * must never change it later. Thus, always specify the correct username + * here, even though the libssh2 docs kind of indicate that it should be + * possible to get a 'generic' list (not user-specific) of authentication + * methods, presumably with a blank username. That won't work in my + * experience. + * So always specify it here. + */ + sshc->authlist = libssh2_userauth_list(sshc->ssh_session, + conn->user, + curlx_uztoui(strlen(conn->user))); + + if(!sshc->authlist) { + if(libssh2_userauth_authenticated(sshc->ssh_session)) { + sshc->authed = TRUE; + infof(data, "SSH user accepted with no authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + else if((err = libssh2_session_last_errno(sshc->ssh_session)) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + else { + state(conn, SSH_SESSION_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(err); + break; + } + } + infof(data, "SSH authentication methods available: %s\n", + sshc->authlist); + + state(conn, SSH_AUTH_PKEY_INIT); + break; + + case SSH_AUTH_PKEY_INIT: + /* + * Check the supported auth types in the order I feel is most secure + * with the requested type of authentication + */ + sshc->authed = FALSE; + + if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && + (strstr(sshc->authlist, "publickey") != NULL)) { + char *home = NULL; + bool out_of_memory = FALSE; + + sshc->rsa_pub = sshc->rsa = NULL; + + /* To ponder about: should really the lib be messing about with the + HOME environment variable etc? */ + home = curl_getenv("HOME"); + + if(data->set.str[STRING_SSH_PRIVATE_KEY]) + sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); + else { + /* If no private key file is specified, try some common paths. */ + if(home) { + /* Try ~/.ssh first. */ + sshc->rsa = aprintf("%s/.ssh/id_rsa", home); + if(!sshc->rsa) + out_of_memory = TRUE; + else if(access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + sshc->rsa = aprintf("%s/.ssh/id_dsa", home); + if(!sshc->rsa) + out_of_memory = TRUE; + else if(access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + } + } + } + if(!out_of_memory && !sshc->rsa) { + /* Nothing found; try the current dir. */ + sshc->rsa = strdup("id_rsa"); + if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + sshc->rsa = strdup("id_dsa"); + if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + /* Out of guesses. Set to the empty string to avoid + * surprising info messages. */ + sshc->rsa = strdup(""); + } + } + } + } + + /* + * Unless the user explicitly specifies a public key file, let + * libssh2 extract the public key from the private key file. + * This is done by simply passing sshc->rsa_pub = NULL. + */ + if(data->set.str[STRING_SSH_PUBLIC_KEY]) { + sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); + if(!sshc->rsa_pub) + out_of_memory = TRUE; + } + + if(out_of_memory || sshc->rsa == NULL) { + free(home); + Curl_safefree(sshc->rsa); + Curl_safefree(sshc->rsa_pub); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + sshc->passphrase = data->set.str[STRING_KEY_PASSWD]; + if(!sshc->passphrase) + sshc->passphrase = ""; + + free(home); + + infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); + infof(data, "Using SSH private key file '%s'\n", sshc->rsa); + + state(conn, SSH_AUTH_PKEY); + } + else { + state(conn, SSH_AUTH_PASS_INIT); + } + break; + + case SSH_AUTH_PKEY: + /* The function below checks if the files exists, no need to stat() here. + */ + rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session, + conn->user, + curlx_uztoui( + strlen(conn->user)), + sshc->rsa_pub, + sshc->rsa, sshc->passphrase); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + + Curl_safefree(sshc->rsa_pub); + Curl_safefree(sshc->rsa); + + if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized SSH public key authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + char *err_msg; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "SSH public key authentication failed: %s\n", err_msg); + state(conn, SSH_AUTH_PASS_INIT); + } + break; + + case SSH_AUTH_PASS_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) && + (strstr(sshc->authlist, "password") != NULL)) { + state(conn, SSH_AUTH_PASS); + } + else { + state(conn, SSH_AUTH_HOST_INIT); + } + break; + + case SSH_AUTH_PASS: + rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user, + curlx_uztoui(strlen(conn->user)), + conn->passwd, + curlx_uztoui(strlen(conn->passwd)), + NULL); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized password authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + state(conn, SSH_AUTH_HOST_INIT); + } + break; + + case SSH_AUTH_HOST_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && + (strstr(sshc->authlist, "hostbased") != NULL)) { + state(conn, SSH_AUTH_HOST); + } + else { + state(conn, SSH_AUTH_AGENT_INIT); + } + break; + + case SSH_AUTH_HOST: + state(conn, SSH_AUTH_AGENT_INIT); + break; + + case SSH_AUTH_AGENT_INIT: +#ifdef HAVE_LIBSSH2_AGENT_API + if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT) + && (strstr(sshc->authlist, "publickey") != NULL)) { + + /* Connect to the ssh-agent */ + /* The agent could be shared by a curl thread i believe + but nothing obvious as keys can be added/removed at any time */ + if(!sshc->ssh_agent) { + sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session); + if(!sshc->ssh_agent) { + infof(data, "Could not create agent object\n"); + + state(conn, SSH_AUTH_KEY_INIT); + break; + } + } + + rc = libssh2_agent_connect(sshc->ssh_agent); + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + if(rc < 0) { + infof(data, "Failure connecting to agent\n"); + state(conn, SSH_AUTH_KEY_INIT); + } + else { + state(conn, SSH_AUTH_AGENT_LIST); + } + } + else +#endif /* HAVE_LIBSSH2_AGENT_API */ + state(conn, SSH_AUTH_KEY_INIT); + break; + + case SSH_AUTH_AGENT_LIST: +#ifdef HAVE_LIBSSH2_AGENT_API + rc = libssh2_agent_list_identities(sshc->ssh_agent); + + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + if(rc < 0) { + infof(data, "Failure requesting identities to agent\n"); + state(conn, SSH_AUTH_KEY_INIT); + } + else { + state(conn, SSH_AUTH_AGENT); + sshc->sshagent_prev_identity = NULL; + } +#endif + break; + + case SSH_AUTH_AGENT: +#ifdef HAVE_LIBSSH2_AGENT_API + /* as prev_identity evolves only after an identity user auth finished we + can safely request it again as long as EAGAIN is returned here or by + libssh2_agent_userauth */ + rc = libssh2_agent_get_identity(sshc->ssh_agent, + &sshc->sshagent_identity, + sshc->sshagent_prev_identity); + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + + if(rc == 0) { + rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user, + sshc->sshagent_identity); + + if(rc < 0) { + if(rc != LIBSSH2_ERROR_EAGAIN) { + /* tried and failed? go to next identity */ + sshc->sshagent_prev_identity = sshc->sshagent_identity; + } + break; + } + } + + if(rc < 0) + infof(data, "Failure requesting identities to agent\n"); + else if(rc == 1) + infof(data, "No identity would match\n"); + + if(rc == LIBSSH2_ERROR_NONE) { + sshc->authed = TRUE; + infof(data, "Agent based authentication successful\n"); + state(conn, SSH_AUTH_DONE); + } + else + state(conn, SSH_AUTH_KEY_INIT); +#endif + break; + + case SSH_AUTH_KEY_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) + && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { + state(conn, SSH_AUTH_KEY); + } + else { + state(conn, SSH_AUTH_DONE); + } + break; + + case SSH_AUTH_KEY: + /* Authentication failed. Continue with keyboard-interactive now. */ + rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session, + conn->user, + curlx_uztoui( + strlen(conn->user)), + &kbd_callback); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized keyboard interactive authentication\n"); + } + state(conn, SSH_AUTH_DONE); + break; + + case SSH_AUTH_DONE: + if(!sshc->authed) { + failf(data, "Authentication failure"); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_LOGIN_DENIED; + break; + } + + /* + * At this point we have an authenticated ssh session. + */ + infof(data, "Authentication complete\n"); + + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ + + conn->sockfd = sock; + conn->writesockfd = CURL_SOCKET_BAD; + + if(conn->handler->protocol == CURLPROTO_SFTP) { + state(conn, SSH_SFTP_INIT); + break; + } + infof(data, "SSH CONNECT phase done\n"); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_INIT: + /* + * Start the libssh2 sftp session + */ + sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session); + if(!sshc->sftp_session) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + else { + char *err_msg; + + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + failf(data, "Failure initializing sftp session: %s", err_msg); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_FAILED_INIT; + break; + } + } + state(conn, SSH_SFTP_REALPATH); + break; + + case SSH_SFTP_REALPATH: + { + char tempHome[PATH_MAX]; + + /* + * Get the "home" directory + */ + rc = sftp_libssh2_realpath(sshc->sftp_session, ".", + tempHome, PATH_MAX-1); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc > 0) { + /* It seems that this string is not always NULL terminated */ + tempHome[rc] = '\0'; + sshc->homedir = strdup(tempHome); + if(!sshc->homedir) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + conn->data->state.most_recent_ftp_entrypath = sshc->homedir; + } + else { + /* Return the error type */ + err = sftp_libssh2_last_error(sshc->sftp_session); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + DEBUGF(infof(data, "error = %d makes libcurl = %d\n", + err, (int)result)); + state(conn, SSH_STOP); + break; + } + } + /* This is the last step in the SFTP connect phase. Do note that while + we get the homedir here, we get the "workingpath" in the DO action + since the homedir will remain the same between request but the + working path will not. */ + DEBUGF(infof(data, "SSH CONNECT phase done\n")); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_QUOTE_INIT: + + result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.quote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.quote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_SFTP_TRANS_INIT); + } + break; + + case SSH_SFTP_POSTQUOTE_INIT: + if(data->set.postquote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.postquote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_QUOTE: + /* Send any quote commands */ + { + const char *cp; + + /* + * Support some of the "FTP" commands + */ + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + if(curl_strequal("pwd", cmd)) { + /* output debug output if that is requested */ + char *tmp = aprintf("257 \"%s\" is current directory.\n", + sftp_scp->path); + if(!tmp) { + result = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + break; + } + if(data->set.verbose) { + Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn); + Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn); + } + /* this sends an FTP-like "header" to the header callback so that the + current directory can be read very similar to how it is read when + using ordinary FTP. */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + else + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + } + else if(cmd) { + /* + * the arguments following the command must be separated from the + * command with a space so we can check for it unconditionally + */ + cp = strchr(cmd, ' '); + if(cp == NULL) { + failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + + /* + * also, every command takes at least one argument so we get that + * first argument right now + */ + result = get_pathname(&cp, &sshc->quote_path1); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error: Bad first parameter"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + + /* + * SFTP is a binary protocol, so we don't send text commands + * to the server. Instead, we scan for commands used by + * OpenSSH's sftp program and call the appropriate libssh2 + * functions. + */ + if(curl_strnequal(cmd, "chgrp ", 6) || + curl_strnequal(cmd, "chmod ", 6) || + curl_strnequal(cmd, "chown ", 6) ) { + /* attribute change */ + + /* sshc->quote_path1 contains the mode to set */ + /* get the destination */ + result = get_pathname(&cp, &sshc->quote_path2); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in chgrp/chmod/chown: " + "Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); + state(conn, SSH_SFTP_QUOTE_STAT); + break; + } + else if(curl_strnequal(cmd, "ln ", 3) || + curl_strnequal(cmd, "symlink ", 8)) { + /* symbolic linking */ + /* sshc->quote_path1 is the source */ + /* get the destination */ + result = get_pathname(&cp, &sshc->quote_path2); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, + "Syntax error in ln/symlink: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + state(conn, SSH_SFTP_QUOTE_SYMLINK); + break; + } + else if(curl_strnequal(cmd, "mkdir ", 6)) { + /* create dir */ + state(conn, SSH_SFTP_QUOTE_MKDIR); + break; + } + else if(curl_strnequal(cmd, "rename ", 7)) { + /* rename file */ + /* first param is the source path */ + /* second param is the dest. path */ + result = get_pathname(&cp, &sshc->quote_path2); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in rename: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + state(conn, SSH_SFTP_QUOTE_RENAME); + break; + } + else if(curl_strnequal(cmd, "rmdir ", 6)) { + /* delete dir */ + state(conn, SSH_SFTP_QUOTE_RMDIR); + break; + } + else if(curl_strnequal(cmd, "rm ", 3)) { + state(conn, SSH_SFTP_QUOTE_UNLINK); + break; + } + + failf(data, "Unknown SFTP command"); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + if(!sshc->quote_item) { + state(conn, SSH_SFTP_TRANS_INIT); + } + break; + + case SSH_SFTP_NEXT_QUOTE: + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + + sshc->quote_item = sshc->quote_item->next; + + if(sshc->quote_item) { + state(conn, SSH_SFTP_QUOTE); + } + else { + if(sshc->nextstate != SSH_NO_STATE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_NO_STATE; + } + else { + state(conn, SSH_SFTP_TRANS_INIT); + } + } + break; + + case SSH_SFTP_QUOTE_STAT: + { + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + if(!curl_strnequal(cmd, "chmod", 5)) { + /* Since chown and chgrp only set owner OR group but libssh2 wants to + * set them both at once, we need to obtain the current ownership + * first. This takes an extra protocol round trip. + */ + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_STAT, + &sshc->quote_attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */ + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to get SFTP stats failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + + /* Now set the new attributes... */ + if(curl_strnequal(cmd, "chgrp", 5)) { + sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; + if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chgrp gid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + else if(curl_strnequal(cmd, "chmod", 5)) { + sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; + /* permissions are octal */ + if(sshc->quote_attrs.permissions == 0 && + !ISDIGIT(sshc->quote_path1[0])) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chmod permissions not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + else if(curl_strnequal(cmd, "chown", 5)) { + sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; + if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chown uid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + + /* Now send the completed structure... */ + state(conn, SSH_SFTP_QUOTE_SETSTAT); + break; + } + + case SSH_SFTP_QUOTE_SETSTAT: + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_SETSTAT, + &sshc->quote_attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to set SFTP stats failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_SYMLINK: + rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_SYMLINK); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "symlink command failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_MKDIR: + rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + data->set.new_directory_perms); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RENAME: + rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_RENAME_OVERWRITE | + LIBSSH2_SFTP_RENAME_ATOMIC | + LIBSSH2_SFTP_RENAME_NATIVE); + + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "rename command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RMDIR: + rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1))); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_UNLINK: + rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1))); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "rm command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_TRANS_INIT: + if(data->set.upload) + state(conn, SSH_SFTP_UPLOAD_INIT); + else { + if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') + state(conn, SSH_SFTP_READDIR_INIT); + else + state(conn, SSH_SFTP_DOWNLOAD_INIT); + } + break; + + case SSH_SFTP_UPLOAD_INIT: + { + unsigned long flags; + /* + * NOTE!!! libssh2 requires that the destination path is a full path + * that includes the destination file and name OR ends in a "/" + * If this is not done the destination file will be named the + * same name as the last directory in the path. + */ + + if(data->state.resume_from != 0) { + LIBSSH2_SFTP_ATTRIBUTES attrs; + if(data->state.resume_from < 0) { + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_SFTP_STAT, &attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc) { + data->state.resume_from = 0; + } + else { + curl_off_t size = attrs.filesize; + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + data->state.resume_from = attrs.filesize; + } + } + } + + if(data->set.ftp_append) + /* Try to open for append, but create if nonexisting */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND; + else if(data->state.resume_from > 0) + /* If we have restart position then open for append */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND; + else + /* Clear file before writing (normal behaviour) */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC; + + sshc->sftp_handle = + libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + flags, data->set.new_file_perms, + LIBSSH2_SFTP_OPENFILE); + + if(!sshc->sftp_handle) { + rc = libssh2_session_last_errno(sshc->ssh_session); + + if(LIBSSH2_ERROR_EAGAIN == rc) + break; + else { + if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) + /* only when there was an SFTP protocol error can we extract + the sftp error! */ + err = sftp_libssh2_last_error(sshc->sftp_session); + else + err = -1; /* not an sftp error at all */ + + if(sshc->secondCreateDirs) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; + failf(data, "Creating the dir/file failed: %s", + sftp_libssh2_strerror(err)); + break; + } + else if(((err == LIBSSH2_FX_NO_SUCH_FILE) || + (err == LIBSSH2_FX_FAILURE) || + (err == LIBSSH2_FX_NO_SUCH_PATH)) && + (data->set.ftp_create_missing_dirs && + (strlen(sftp_scp->path) > 1))) { + /* try to create the path remotely */ + sshc->secondCreateDirs = 1; + state(conn, SSH_SFTP_CREATE_DIRS_INIT); + break; + } + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; + if(!sshc->actualcode) { + /* Sometimes, for some reason libssh2_sftp_last_error() returns + zero even though libssh2_sftp_open() failed previously! We need + to work around that! */ + sshc->actualcode = CURLE_SSH; + err=-1; + } + failf(data, "Upload failed: %s (%d/%d)", + err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error", + err, rc); + break; + } + } + + /* If we have a restart point then we need to seek to the correct + position. */ + if(data->state.resume_from > 0) { + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + else { + curl_off_t passed=0; + do { + size_t readthisamountnow = + (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? + BUFSIZE : curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + conn->fread_func(data->state.buffer, 1, readthisamountnow, + conn->fread_in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); + } + } + + /* now, decrease the size of the read */ + if(data->state.infilesize > 0) { + data->state.infilesize -= data->state.resume_from; + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + + SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); + } + if(data->state.infilesize > 0) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + /* upload data */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh2 sftp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + /* since we don't really wait for anything at this point, we want the + state machine to move on as soon as possible so we set a very short + timeout here */ + Curl_expire(data, 1); + + state(conn, SSH_STOP); + } + break; + } + + case SSH_SFTP_CREATE_DIRS_INIT: + if(strlen(sftp_scp->path) > 1) { + sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */ + state(conn, SSH_SFTP_CREATE_DIRS); + } + else { + state(conn, SSH_SFTP_UPLOAD_INIT); + } + break; + + case SSH_SFTP_CREATE_DIRS: + sshc->slash_pos = strchr(sshc->slash_pos, '/'); + if(sshc->slash_pos) { + *sshc->slash_pos = 0; + + infof(data, "Creating directory '%s'\n", sftp_scp->path); + state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); + break; + } + else { + state(conn, SSH_SFTP_UPLOAD_INIT); + } + break; + + case SSH_SFTP_CREATE_DIRS_MKDIR: + /* 'mode' - parameter is preliminary - default to 0644 */ + rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + data->set.new_directory_perms); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + *sshc->slash_pos = '/'; + ++sshc->slash_pos; + if(rc == -1) { + /* + * Abort if failure wasn't that the dir already exists or the + * permission was denied (creation might succeed further down the + * path) - retry on unspecific FAILURE also + */ + err = sftp_libssh2_last_error(sshc->sftp_session); + if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) && + (err != LIBSSH2_FX_FAILURE) && + (err != LIBSSH2_FX_PERMISSION_DENIED)) { + result = sftp_libssh2_error_to_CURLE(err); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + } + state(conn, SSH_SFTP_CREATE_DIRS); + break; + + case SSH_SFTP_READDIR_INIT: + Curl_pgrsSetDownloadSize(data, -1); + if(data->set.opt_no_body) { + state(conn, SSH_STOP); + break; + } + + /* + * This is a directory that we are trying to get, so produce a directory + * listing + */ + sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session, + sftp_scp->path, + curlx_uztoui( + strlen(sftp_scp->path)), + 0, 0, LIBSSH2_SFTP_OPENDIR); + if(!sshc->sftp_handle) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + else { + err = sftp_libssh2_last_error(sshc->sftp_session); + failf(data, "Could not open directory for reading: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + } + if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) { + Curl_safefree(sshc->readdir_filename); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR: + sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle, + sshc->readdir_filename, + PATH_MAX, + sshc->readdir_longentry, + PATH_MAX, + &sshc->readdir_attrs); + if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + if(sshc->readdir_len > 0) { + sshc->readdir_filename[sshc->readdir_len] = '\0'; + + if(data->set.ftp_list_only) { + char *tmpLine; + + tmpLine = aprintf("%s\n", sshc->readdir_filename); + if(tmpLine == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + result = Curl_client_write(conn, CLIENTWRITE_BODY, + tmpLine, sshc->readdir_len+1); + free(tmpLine); + + if(result) { + state(conn, SSH_STOP); + break; + } + /* since this counts what we send to the client, we include the + newline in this counter */ + data->req.bytecount += sshc->readdir_len+1; + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename, + sshc->readdir_len, conn); + } + } + else { + sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry); + sshc->readdir_totalLen = 80 + sshc->readdir_currLen; + sshc->readdir_line = calloc(sshc->readdir_totalLen, 1); + if(!sshc->readdir_line) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + memcpy(sshc->readdir_line, sshc->readdir_longentry, + sshc->readdir_currLen); + if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && + ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == + LIBSSH2_SFTP_S_IFLNK)) { + sshc->readdir_linkPath = malloc(PATH_MAX + 1); + if(sshc->readdir_linkPath == NULL) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path, + sshc->readdir_filename); + state(conn, SSH_SFTP_READDIR_LINK); + break; + } + state(conn, SSH_SFTP_READDIR_BOTTOM); + break; + } + } + else if(sshc->readdir_len == 0) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_READDIR_DONE); + break; + } + else if(sshc->readdir_len <= 0) { + err = sftp_libssh2_last_error(sshc->sftp_session); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + failf(data, "Could not open remote file for reading: %s :: %d", + sftp_libssh2_strerror(err), + libssh2_session_last_errno(sshc->ssh_session)); + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + break; + } + break; + + case SSH_SFTP_READDIR_LINK: + sshc->readdir_len = + libssh2_sftp_symlink_ex(sshc->sftp_session, + sshc->readdir_linkPath, + curlx_uztoui(strlen(sshc->readdir_linkPath)), + sshc->readdir_filename, + PATH_MAX, LIBSSH2_SFTP_READLINK); + if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + Curl_safefree(sshc->readdir_linkPath); + + /* get room for the filename and extra output */ + sshc->readdir_totalLen += 4 + sshc->readdir_len; + new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen); + if(!new_readdir_line) { + Curl_safefree(sshc->readdir_line); + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + sshc->readdir_line = new_readdir_line; + + sshc->readdir_currLen += snprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, + " -> %s", + sshc->readdir_filename); + + state(conn, SSH_SFTP_READDIR_BOTTOM); + break; + + case SSH_SFTP_READDIR_BOTTOM: + sshc->readdir_currLen += snprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, "\n"); + result = Curl_client_write(conn, CLIENTWRITE_BODY, + sshc->readdir_line, + sshc->readdir_currLen); + + if(!result) { + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line, + sshc->readdir_currLen, conn); + } + data->req.bytecount += sshc->readdir_currLen; + } + Curl_safefree(sshc->readdir_line); + if(result) { + state(conn, SSH_STOP); + } + else + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR_DONE: + if(libssh2_sftp_closedir(sshc->sftp_handle) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + sshc->sftp_handle = NULL; + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_DOWNLOAD_INIT: + /* + * Work on getting the specified file + */ + sshc->sftp_handle = + libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_FXF_READ, data->set.new_file_perms, + LIBSSH2_SFTP_OPENFILE); + if(!sshc->sftp_handle) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + else { + err = sftp_libssh2_last_error(sshc->sftp_session); + failf(data, "Could not open remote file for reading: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + } + state(conn, SSH_SFTP_DOWNLOAD_STAT); + break; + + case SSH_SFTP_DOWNLOAD_STAT: + { + LIBSSH2_SFTP_ATTRIBUTES attrs; + + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_SFTP_STAT, &attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc || + !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) || + (attrs.filesize == 0)) { + /* + * libssh2_sftp_open() didn't return an error, so maybe the server + * just doesn't support stat() + * OR the server doesn't return a file size with a stat() + * OR file size is 0 + */ + data->req.size = -1; + data->req.maxdownload = -1; + Curl_pgrsSetDownloadSize(data, -1); + } + else { + curl_off_t size = attrs.filesize; + + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(conn->data->state.use_range) { + curl_off_t from, to; + char *ptr; + char *ptr2; + + from=curlx_strtoofft(conn->data->state.range, &ptr, 0); + while(*ptr && (ISSPACE(*ptr) || (*ptr=='-'))) + ptr++; + to=curlx_strtoofft(ptr, &ptr2, 0); + if((ptr == ptr2) /* no "to" value given */ + || (to >= size)) { + to = size - 1; + } + if(from < 0) { + /* from is relative to end of file */ + from += size; + } + if(from >= size) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(from > to) { + from = to; + size = 0; + } + else { + size = to - from + 1; + } + + SFTP_SEEK(conn->proto.sshc.sftp_handle, from); + } + data->req.size = size; + data->req.maxdownload = size; + Curl_pgrsSetDownloadSize(data, size); + } + + /* We can resume if we can seek to the resume position */ + if(data->state.resume_from) { + if(data->state.resume_from < 0) { + /* We're supposed to download the last abs(from) bytes */ + if((curl_off_t)attrs.filesize < -data->state.resume_from) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* download from where? */ + data->state.resume_from += attrs.filesize; + } + else { + if((curl_off_t)attrs.filesize < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + } + /* Does a completed file need to be seeked and started or closed ? */ + /* Now store the number of bytes we are expected to download */ + data->req.size = attrs.filesize - data->state.resume_from; + data->req.maxdownload = attrs.filesize - data->state.resume_from; + Curl_pgrsSetDownloadSize(data, + attrs.filesize - data->state.resume_from); + SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); + } + } + + /* Setup the actual download */ + if(data->req.size == 0) { + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + infof(data, "File already completely downloaded\n"); + state(conn, SSH_STOP); + break; + } + else { + Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, + FALSE, NULL, -1, NULL); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh2 recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + } + if(result) { + /* this should never occur; the close state should be entered + at the time the error occurs */ + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_CLOSE: + if(sshc->sftp_handle) { + rc = libssh2_sftp_close(sshc->sftp_handle); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc < 0) { + infof(data, "Failed to close libssh2 file\n"); + } + sshc->sftp_handle = NULL; + } + if(sftp_scp) + Curl_safefree(sftp_scp->path); + + DEBUGF(infof(data, "SFTP DONE done\n")); + + /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT + After nextstate is executed, the control should come back to + SSH_SFTP_CLOSE to pass the correct result back */ + if(sshc->nextstate != SSH_NO_STATE && + sshc->nextstate != SSH_SFTP_CLOSE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_SFTP_CLOSE; + } + else { + state(conn, SSH_STOP); + result = sshc->actualcode; + } + break; + + case SSH_SFTP_SHUTDOWN: + /* during times we get here due to a broken transfer and then the + sftp_handle might not have been taken down so make sure that is done + before we proceed */ + + if(sshc->sftp_handle) { + rc = libssh2_sftp_close(sshc->sftp_handle); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc < 0) { + infof(data, "Failed to close libssh2 file\n"); + } + sshc->sftp_handle = NULL; + } + if(sshc->sftp_session) { + rc = libssh2_sftp_shutdown(sshc->sftp_session); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc < 0) { + infof(data, "Failed to stop libssh2 sftp subsystem\n"); + } + sshc->sftp_session = NULL; + } + + Curl_safefree(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_DISCONNECT); + break; + + case SSH_SCP_TRANS_INIT: + result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.upload) { + if(data->state.infilesize < 0) { + failf(data, "SCP requires a known file size for upload"); + sshc->actualcode = CURLE_UPLOAD_FAILED; + state(conn, SSH_SCP_CHANNEL_FREE); + break; + } + state(conn, SSH_SCP_UPLOAD_INIT); + } + else { + state(conn, SSH_SCP_DOWNLOAD_INIT); + } + break; + + case SSH_SCP_UPLOAD_INIT: + /* + * libssh2 requires that the destination path is a full path that + * includes the destination file and name OR ends in a "/" . If this is + * not done the destination file will be named the same name as the last + * directory in the path. + */ + sshc->ssh_channel = + SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, + data->state.infilesize); + if(!sshc->ssh_channel) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + else { + int ssh_err; + char *err_msg; + + ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0)); + failf(conn->data, "%s", err_msg); + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + break; + } + } + + /* upload data */ + Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL, + FIRSTSOCKET, NULL); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + if(result) { + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = result; + } + else { + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh2 scp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + state(conn, SSH_STOP); + } + break; + + case SSH_SCP_DOWNLOAD_INIT: + { + /* + * We must check the remote file; if it is a directory no values will + * be set in sb + */ + struct stat sb; + curl_off_t bytecount; + + /* clear the struct scp recv will fill in */ + memset(&sb, 0, sizeof(struct stat)); + + /* get a fresh new channel from the ssh layer */ + sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session, + sftp_scp->path, &sb); + if(!sshc->ssh_channel) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + else { + int ssh_err; + char *err_msg; + + ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0)); + failf(conn->data, "%s", err_msg); + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + break; + } + } + + /* download data */ + bytecount = (curl_off_t)sb.st_size; + data->req.maxdownload = (curl_off_t)sb.st_size; + Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh2 recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + if(result) { + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = result; + } + else + state(conn, SSH_STOP); + } + break; + + case SSH_SCP_DONE: + if(data->set.upload) + state(conn, SSH_SCP_SEND_EOF); + else + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_SEND_EOF: + if(sshc->ssh_channel) { + rc = libssh2_channel_send_eof(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc) { + infof(data, "Failed to send libssh2 channel EOF\n"); + } + } + state(conn, SSH_SCP_WAIT_EOF); + break; + + case SSH_SCP_WAIT_EOF: + if(sshc->ssh_channel) { + rc = libssh2_channel_wait_eof(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc) { + infof(data, "Failed to get channel EOF: %d\n", rc); + } + } + state(conn, SSH_SCP_WAIT_CLOSE); + break; + + case SSH_SCP_WAIT_CLOSE: + if(sshc->ssh_channel) { + rc = libssh2_channel_wait_closed(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc) { + infof(data, "Channel failed to close: %d\n", rc); + } + } + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_CHANNEL_FREE: + if(sshc->ssh_channel) { + rc = libssh2_channel_free(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc < 0) { + infof(data, "Failed to free libssh2 scp subsystem\n"); + } + sshc->ssh_channel = NULL; + } + DEBUGF(infof(data, "SCP DONE phase complete\n")); +#if 0 /* PREV */ + state(conn, SSH_SESSION_DISCONNECT); +#endif + state(conn, SSH_STOP); + result = sshc->actualcode; + break; + + case SSH_SESSION_DISCONNECT: + /* during weird times when we've been prematurely aborted, the channel + is still alive when we reach this state and we MUST kill the channel + properly first */ + if(sshc->ssh_channel) { + rc = libssh2_channel_free(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc < 0) { + infof(data, "Failed to free libssh2 scp subsystem\n"); + } + sshc->ssh_channel = NULL; + } + + if(sshc->ssh_session) { + rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown"); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc < 0) { + infof(data, "Failed to disconnect libssh2 session\n"); + } + } + + Curl_safefree(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_FREE); + break; + + case SSH_SESSION_FREE: +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + if(sshc->kh) { + libssh2_knownhost_free(sshc->kh); + sshc->kh = NULL; + } +#endif + +#ifdef HAVE_LIBSSH2_AGENT_API + if(sshc->ssh_agent) { + rc = libssh2_agent_disconnect(sshc->ssh_agent); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc < 0) { + infof(data, "Failed to disconnect from libssh2 agent\n"); + } + libssh2_agent_free (sshc->ssh_agent); + sshc->ssh_agent = NULL; + + /* NB: there is no need to free identities, they are part of internal + agent stuff */ + sshc->sshagent_identity = NULL; + sshc->sshagent_prev_identity = NULL; + } +#endif + + if(sshc->ssh_session) { + rc = libssh2_session_free(sshc->ssh_session); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + else if(rc < 0) { + infof(data, "Failed to free libssh2 session\n"); + } + sshc->ssh_session = NULL; + } + + /* worst-case scenario cleanup */ + + DEBUGASSERT(sshc->ssh_session == NULL); + DEBUGASSERT(sshc->ssh_channel == NULL); + DEBUGASSERT(sshc->sftp_session == NULL); + DEBUGASSERT(sshc->sftp_handle == NULL); +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + DEBUGASSERT(sshc->kh == NULL); +#endif +#ifdef HAVE_LIBSSH2_AGENT_API + DEBUGASSERT(sshc->ssh_agent == NULL); +#endif + + Curl_safefree(sshc->rsa_pub); + Curl_safefree(sshc->rsa); + + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + + Curl_safefree(sshc->homedir); + + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + Curl_safefree(sshc->readdir_line); + Curl_safefree(sshc->readdir_linkPath); + + /* the code we are about to return */ + result = sshc->actualcode; + + memset(sshc, 0, sizeof(struct ssh_conn)); + + connclose(conn, "SSH session free"); + sshc->state = SSH_SESSION_FREE; /* current */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + + case SSH_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + } + + } while(!rc && (sshc->state != SSH_STOP)); + + if(rc == LIBSSH2_ERROR_EAGAIN) { + /* we would block, we need to wait for the socket to be ready (in the + right direction too)! */ + *block = TRUE; + } + + return result; +} + +/* called by the multi interface to figure out what socket(s) to wait for and + for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ +static int ssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + int bitmap = GETSOCK_BLANK; + (void)numsocks; + + sock[0] = conn->sock[FIRSTSOCKET]; + + if(conn->waitfor & KEEP_RECV) + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + + if(conn->waitfor & KEEP_SEND) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +#else + /* if we don't know the direction we can use the generic *_getsock() + function even for the protocol_connect and doing states */ + return Curl_single_getsock(conn, sock, numsocks); +#endif +} + +/* Generic function called by the multi interface to figure out what socket(s) + to wait for and for what actions during the DOING and PROTOCONNECT states*/ +static int ssh_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks) +{ +#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + (void)conn; + (void)sock; + (void)numsocks; + /* if we don't know any direction we can just play along as we used to and + not provide any sensible info */ + return GETSOCK_BLANK; +#else + /* if we know the direction we can use the generic *_getsock() function even + for the protocol_connect and doing states */ + return ssh_perform_getsock(conn, sock, numsocks); +#endif +} + +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION +/* + * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this + * function is used to figure out in what direction and stores this info so + * that the multi interface can take advantage of it. Make sure to call this + * function in all cases so that when it _doesn't_ return EAGAIN we can + * restore the default wait bits. + */ +static void ssh_block2waitfor(struct connectdata *conn, bool block) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + int dir; + if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) { + /* translate the libssh2 define bits into our own bit defines */ + conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | + ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); + } + else + /* It didn't block or libssh2 didn't reveal in which direction, put back + the original set */ + conn->waitfor = sshc->orig_waitfor; +} +#else + /* no libssh2 directional support so we simply don't know */ +#define ssh_block2waitfor(x,y) Curl_nop_stmt +#endif + +/* called repeatedly until done from multi.c */ +static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + bool block; /* we store the status and use that to provide a ssh_getsock() + implementation */ + + result = ssh_statemach_act(conn, &block); + *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + ssh_block2waitfor(conn, block); + + return result; +} + +static CURLcode ssh_block_statemach(struct connectdata *conn, + bool duringconnect) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + while((sshc->state != SSH_STOP) && !result) { + bool block; + long left; + + result = ssh_statemach_act(conn, &block); + if(result) + break; + + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + else { + struct timeval now = Curl_tvnow(); + result = Curl_speedcheck(data, now); + if(result) + break; + } + + left = Curl_timeleft(data, NULL, duringconnect); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } + +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + if(!result && block) { + int dir = libssh2_session_block_directions(sshc->ssh_session); + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + curl_socket_t fd_read = CURL_SOCKET_BAD; + curl_socket_t fd_write = CURL_SOCKET_BAD; + if(LIBSSH2_SESSION_BLOCK_INBOUND & dir) + fd_read = sock; + if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) + fd_write = sock; + /* wait for the socket to become ready */ + Curl_socket_ready(fd_read, fd_write, + left>1000?1000:left); /* ignore result */ + } +#endif + + } + + return result; +} + +/* + * SSH setup and connection + */ +static CURLcode ssh_setup_connection(struct connectdata *conn) +{ + struct SSHPROTO *ssh; + + conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO)); + if(!ssh) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +static Curl_recv scp_recv, sftp_recv; +static Curl_send scp_send, sftp_send; + +/* + * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to + * do protocol-specific actions at connect-time. + */ +static CURLcode ssh_connect(struct connectdata *conn, bool *done) +{ +#ifdef CURL_LIBSSH2_DEBUG + curl_socket_t sock; +#endif + struct ssh_conn *ssh; + CURLcode result; + struct SessionHandle *data = conn->data; + + /* initialize per-handle data if not already */ + if(!data->req.protop) + ssh_setup_connection(conn); + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "SSH default"); + + if(conn->handler->protocol & CURLPROTO_SCP) { + conn->recv[FIRSTSOCKET] = scp_recv; + conn->send[FIRSTSOCKET] = scp_send; + } + else { + conn->recv[FIRSTSOCKET] = sftp_recv; + conn->send[FIRSTSOCKET] = sftp_send; + } + ssh = &conn->proto.sshc; + +#ifdef CURL_LIBSSH2_DEBUG + if(conn->user) { + infof(data, "User: %s\n", conn->user); + } + if(conn->passwd) { + infof(data, "Password: %s\n", conn->passwd); + } + sock = conn->sock[FIRSTSOCKET]; +#endif /* CURL_LIBSSH2_DEBUG */ + + ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, + my_libssh2_free, + my_libssh2_realloc, conn); + if(ssh->ssh_session == NULL) { + failf(data, "Failure initialising ssh session"); + return CURLE_FAILED_INIT; + } + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + if(data->set.str[STRING_SSH_KNOWNHOSTS]) { + int rc; + ssh->kh = libssh2_knownhost_init(ssh->ssh_session); + if(!ssh->kh) { + /* eeek. TODO: free the ssh_session! */ + return CURLE_FAILED_INIT; + } + + /* read all known hosts from there */ + rc = libssh2_knownhost_readfile(ssh->kh, + data->set.str[STRING_SSH_KNOWNHOSTS], + LIBSSH2_KNOWNHOST_FILE_OPENSSH); + if(rc < 0) + infof(data, "Failed to read known hosts from %s\n", + data->set.str[STRING_SSH_KNOWNHOSTS]); + } +#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ + +#ifdef CURL_LIBSSH2_DEBUG + libssh2_trace(ssh->ssh_session, ~0); + infof(data, "SSH socket: %d\n", (int)sock); +#endif /* CURL_LIBSSH2_DEBUG */ + + state(conn, SSH_INIT); + + result = ssh_multi_statemach(conn, done); + + return result; +} + +/* + *********************************************************************** + * + * scp_perform() + * + * This is the actual DO function for SCP. Get a file according to + * the options previously setup. + */ + +static +CURLcode scp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SCP_TRANS_INIT); + + /* run the state-machine */ + result = ssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode scp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result; + result = ssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* + * The DO function is generic for both protocols. There was previously two + * separate ones but this way means less duplicated code. + */ + +static CURLcode ssh_do(struct connectdata *conn, bool *done) +{ + CURLcode result; + bool connected = 0; + struct SessionHandle *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + + *done = FALSE; /* default to false */ + + data->req.size = -1; /* make sure this is unknown at this point */ + + sshc->actualcode = CURLE_OK; /* reset error code */ + sshc->secondCreateDirs =0; /* reset the create dir attempt state + variable */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + if(conn->handler->protocol & CURLPROTO_SCP) + result = scp_perform(conn, &connected, done); + else + result = sftp_perform(conn, &connected, done); + + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + struct ssh_conn *ssh = &conn->proto.sshc; + (void) dead_connection; + + Curl_safefree(conn->data->req.protop); + + if(ssh->ssh_session) { + /* only if there's a session still around to use! */ + + state(conn, SSH_SESSION_DISCONNECT); + + result = ssh_block_statemach(conn, FALSE); + } + + return result; +} + +/* generic done function for both SCP and SFTP called from their specific + done functions */ +static CURLcode ssh_done(struct connectdata *conn, CURLcode status) +{ + CURLcode result = CURLE_OK; + struct SSHPROTO *sftp_scp = conn->data->req.protop; + + if(!status) { + /* run the state-machine + + TODO: when the multi interface is used, this _really_ should be using + the ssh_multi_statemach function but we have no general support for + non-blocking DONE operations, not in the multi state machine and with + Curl_done() invokes on several places in the code! + */ + result = ssh_block_statemach(conn, FALSE); + } + else + result = status; + + if(sftp_scp) + Curl_safefree(sftp_scp->path); + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + conn->data->req.keepon = 0; /* clear all bits */ + return result; +} + + +static CURLcode scp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void)premature; /* not used */ + + if(!status) + state(conn, SSH_SCP_DONE); + + return ssh_done(conn, status); + +} + +/* return number of received (decrypted) bytes */ +static ssize_t scp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite; + (void)sockindex; /* we only support SCP on the fixed known primary socket */ + + /* libssh2_channel_write() returns int! */ + nwrite = (ssize_t) + libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len); + + ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nwrite == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nwrite = 0; + } + else if(nwrite < LIBSSH2_ERROR_NONE) { + *err = libssh2_session_error_to_CURLE((int)nwrite); + nwrite = -1; + } + + return nwrite; +} + +/* + * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return + * a regular CURLcode value. + */ +static ssize_t scp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void)sockindex; /* we only support SCP on the fixed known primary socket */ + + /* libssh2_channel_read() returns int */ + nread = (ssize_t) + libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len); + + ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + if(nread == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nread = -1; + } + + return nread; +} + +/* + * =============== SFTP =============== + */ + +/* + *********************************************************************** + * + * sftp_perform() + * + * This is the actual DO function for SFTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SFTP_QUOTE_INIT); + + /* run the state-machine */ + result = ssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = ssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + (void) dead_connection; + + DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + + Curl_safefree(conn->data->req.protop); + + if(conn->proto.sshc.ssh_session) { + /* only if there's a session still around to use! */ + state(conn, SSH_SFTP_SHUTDOWN); + result = ssh_block_statemach(conn, FALSE); + } + + DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + + return result; + +} + +static CURLcode sftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + + if(!status) { + /* Post quote commands are executed after the SFTP_CLOSE state to avoid + errors that could happen due to open file handles during POSTQUOTE + operation */ + if(!status && !premature && conn->data->set.postquote) { + sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; + state(conn, SSH_SFTP_CLOSE); + } + else + state(conn, SSH_SFTP_CLOSE); + } + return ssh_done(conn, status); +} + +/* return number of sent bytes */ +static ssize_t sftp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 + but is changed to ssize_t in 0.15. These days we don't + support libssh2 0.15*/ + (void)sockindex; + + nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len); + + ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nwrite == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nwrite = 0; + } + else if(nwrite < LIBSSH2_ERROR_NONE) { + *err = libssh2_session_error_to_CURLE((int)nwrite); + nwrite = -1; + } + + return nwrite; +} + +/* + * Return number of received (decrypted) bytes + * or <0 on error + */ +static ssize_t sftp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void)sockindex; + + nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len); + + ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nread == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nread = -1; + + } + else if(nread < 0) { + *err = libssh2_session_error_to_CURLE((int)nread); + } + return nread; +} + +/* The get_pathname() function is being borrowed from OpenSSH sftp.c + version 4.6p1. */ +/* + * Copyright (c) 2001-2004 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +static CURLcode +get_pathname(const char **cpp, char **path) +{ + const char *cp = *cpp, *end; + char quot; + unsigned int i, j; + static const char WHITESPACE[] = " \t\r\n"; + + cp += strspn(cp, WHITESPACE); + if(!*cp) { + *cpp = cp; + *path = NULL; + return CURLE_QUOTE_ERROR; + } + + *path = malloc(strlen(cp) + 1); + if(*path == NULL) + return CURLE_OUT_OF_MEMORY; + + /* Check for quoted filenames */ + if(*cp == '\"' || *cp == '\'') { + quot = *cp++; + + /* Search for terminating quote, unescape some chars */ + for(i = j = 0; i <= strlen(cp); i++) { + if(cp[i] == quot) { /* Found quote */ + i++; + (*path)[j] = '\0'; + break; + } + if(cp[i] == '\0') { /* End of string */ + /*error("Unterminated quote");*/ + goto fail; + } + if(cp[i] == '\\') { /* Escaped characters */ + i++; + if(cp[i] != '\'' && cp[i] != '\"' && + cp[i] != '\\') { + /*error("Bad escaped character '\\%c'", + cp[i]);*/ + goto fail; + } + } + (*path)[j++] = cp[i]; + } + + if(j == 0) { + /*error("Empty quotes");*/ + goto fail; + } + *cpp = cp + i + strspn(cp + i, WHITESPACE); + } + else { + /* Read to end of filename */ + end = strpbrk(cp, WHITESPACE); + if(end == NULL) + end = strchr(cp, '\0'); + *cpp = end + strspn(end, WHITESPACE); + + memcpy(*path, cp, end - cp); + (*path)[end - cp] = '\0'; + } + return CURLE_OK; + + fail: + Curl_safefree(*path); + return CURLE_QUOTE_ERROR; +} + + +static const char *sftp_libssh2_strerror(int err) +{ + switch (err) { + case LIBSSH2_FX_NO_SUCH_FILE: + return "No such file or directory"; + + case LIBSSH2_FX_PERMISSION_DENIED: + return "Permission denied"; + + case LIBSSH2_FX_FAILURE: + return "Operation failed"; + + case LIBSSH2_FX_BAD_MESSAGE: + return "Bad message from SFTP server"; + + case LIBSSH2_FX_NO_CONNECTION: + return "Not connected to SFTP server"; + + case LIBSSH2_FX_CONNECTION_LOST: + return "Connection to SFTP server lost"; + + case LIBSSH2_FX_OP_UNSUPPORTED: + return "Operation not supported by SFTP server"; + + case LIBSSH2_FX_INVALID_HANDLE: + return "Invalid handle"; + + case LIBSSH2_FX_NO_SUCH_PATH: + return "No such file or directory"; + + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + return "File already exists"; + + case LIBSSH2_FX_WRITE_PROTECT: + return "File is write protected"; + + case LIBSSH2_FX_NO_MEDIA: + return "No media"; + + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + return "Disk full"; + + case LIBSSH2_FX_QUOTA_EXCEEDED: + return "User quota exceeded"; + + case LIBSSH2_FX_UNKNOWN_PRINCIPLE: + return "Unknown principle"; + + case LIBSSH2_FX_LOCK_CONFlICT: + return "File lock conflict"; + + case LIBSSH2_FX_DIR_NOT_EMPTY: + return "Directory not empty"; + + case LIBSSH2_FX_NOT_A_DIRECTORY: + return "Not a directory"; + + case LIBSSH2_FX_INVALID_FILENAME: + return "Invalid filename"; + + case LIBSSH2_FX_LINK_LOOP: + return "Link points to itself"; + } + return "Unknown error in libssh2"; +} + +#endif /* USE_LIBSSH2 */ diff --git a/libcurl/src/lib/ssh.h b/libcurl/src/lib/ssh.h new file mode 100644 index 0000000..b3cc54c --- /dev/null +++ b/libcurl/src/lib/ssh.h @@ -0,0 +1,195 @@ +#ifndef HEADER_CURL_SSH_H +#define HEADER_CURL_SSH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_LIBSSH2_H +#include +#include +#endif /* HAVE_LIBSSH2_H */ + +/**************************************************************************** + * SSH unique setup + ***************************************************************************/ +typedef enum { + SSH_NO_STATE = -1, /* Used for "nextState" so say there is none */ + SSH_STOP = 0, /* do nothing state, stops the state machine */ + + SSH_INIT, /* First state in SSH-CONNECT */ + SSH_S_STARTUP, /* Session startup */ + SSH_HOSTKEY, /* verify hostkey */ + SSH_AUTHLIST, + SSH_AUTH_PKEY_INIT, + SSH_AUTH_PKEY, + SSH_AUTH_PASS_INIT, + SSH_AUTH_PASS, + SSH_AUTH_AGENT_INIT, /* initialize then wait for connection to agent */ + SSH_AUTH_AGENT_LIST, /* ask for list then wait for entire list to come */ + SSH_AUTH_AGENT, /* attempt one key at a time */ + SSH_AUTH_HOST_INIT, + SSH_AUTH_HOST, + SSH_AUTH_KEY_INIT, + SSH_AUTH_KEY, + SSH_AUTH_DONE, + SSH_SFTP_INIT, + SSH_SFTP_REALPATH, /* Last state in SSH-CONNECT */ + + SSH_SFTP_QUOTE_INIT, /* First state in SFTP-DO */ + SSH_SFTP_POSTQUOTE_INIT, /* (Possibly) First state in SFTP-DONE */ + SSH_SFTP_QUOTE, + SSH_SFTP_NEXT_QUOTE, + SSH_SFTP_QUOTE_STAT, + SSH_SFTP_QUOTE_SETSTAT, + SSH_SFTP_QUOTE_SYMLINK, + SSH_SFTP_QUOTE_MKDIR, + SSH_SFTP_QUOTE_RENAME, + SSH_SFTP_QUOTE_RMDIR, + SSH_SFTP_QUOTE_UNLINK, + SSH_SFTP_TRANS_INIT, + SSH_SFTP_UPLOAD_INIT, + SSH_SFTP_CREATE_DIRS_INIT, + SSH_SFTP_CREATE_DIRS, + SSH_SFTP_CREATE_DIRS_MKDIR, + SSH_SFTP_READDIR_INIT, + SSH_SFTP_READDIR, + SSH_SFTP_READDIR_LINK, + SSH_SFTP_READDIR_BOTTOM, + SSH_SFTP_READDIR_DONE, + SSH_SFTP_DOWNLOAD_INIT, + SSH_SFTP_DOWNLOAD_STAT, /* Last state in SFTP-DO */ + SSH_SFTP_CLOSE, /* Last state in SFTP-DONE */ + SSH_SFTP_SHUTDOWN, /* First state in SFTP-DISCONNECT */ + SSH_SCP_TRANS_INIT, /* First state in SCP-DO */ + SSH_SCP_UPLOAD_INIT, + SSH_SCP_DOWNLOAD_INIT, + SSH_SCP_DONE, + SSH_SCP_SEND_EOF, + SSH_SCP_WAIT_EOF, + SSH_SCP_WAIT_CLOSE, + SSH_SCP_CHANNEL_FREE, /* Last state in SCP-DONE */ + SSH_SESSION_DISCONNECT, /* First state in SCP-DISCONNECT */ + SSH_SESSION_FREE, /* Last state in SCP/SFTP-DISCONNECT */ + SSH_QUIT, + SSH_LAST /* never used */ +} sshstate; + +/* this struct is used in the HandleData struct which is part of the + SessionHandle, which means this is used on a per-easy handle basis. + Everything that is strictly related to a connection is banned from this + struct. */ +struct SSHPROTO { + char *path; /* the path we operate on */ +}; + +/* ssh_conn is used for struct connection-oriented data in the connectdata + struct */ +struct ssh_conn { + const char *authlist; /* List of auth. methods, managed by libssh2 */ +#ifdef USE_LIBSSH2 + const char *passphrase; /* pass-phrase to use */ + char *rsa_pub; /* path name */ + char *rsa; /* path name */ + bool authed; /* the connection has been authenticated fine */ + sshstate state; /* always use ssh.c:state() to change state! */ + sshstate nextstate; /* the state to goto after stopping */ + CURLcode actualcode; /* the actual error code */ + struct curl_slist *quote_item; /* for the quote option */ + char *quote_path1; /* two generic pointers for the QUOTE stuff */ + char *quote_path2; + LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */ + bool acceptfail; /* used by the SFTP_QUOTE (continue if + quote command fails) */ + char *homedir; /* when doing SFTP we figure out home dir in the + connect phase */ + + /* Here's a set of struct members used by the SFTP_READDIR state */ + LIBSSH2_SFTP_ATTRIBUTES readdir_attrs; + char *readdir_filename; + char *readdir_longentry; + int readdir_len, readdir_totalLen, readdir_currLen; + char *readdir_line; + char *readdir_linkPath; + /* end of READDIR stuff */ + + int secondCreateDirs; /* counter use by the code to see if the + second attempt has been made to change + to/create a directory */ + char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ + LIBSSH2_SESSION *ssh_session; /* Secure Shell session */ + LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */ + LIBSSH2_SFTP *sftp_session; /* SFTP handle */ + LIBSSH2_SFTP_HANDLE *sftp_handle; + int orig_waitfor; /* default READ/WRITE bits wait for */ + +#ifdef HAVE_LIBSSH2_AGENT_API + LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */ + struct libssh2_agent_publickey *sshagent_identity, + *sshagent_prev_identity; +#endif + + /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h + header */ +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + LIBSSH2_KNOWNHOSTS *kh; +#endif +#endif /* USE_LIBSSH2 */ +}; + +#ifdef USE_LIBSSH2 + +/* Feature detection based on version numbers to better work with + non-configure platforms */ + +#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000) +# error "SCP/SFTP protocols require libssh2 0.16 or later" +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010000 +#define HAVE_LIBSSH2_SFTP_SEEK64 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010100 +#define HAVE_LIBSSH2_VERSION 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010205 +#define HAVE_LIBSSH2_INIT 1 +#define HAVE_LIBSSH2_EXIT 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010206 +#define HAVE_LIBSSH2_KNOWNHOST_CHECKP 1 +#define HAVE_LIBSSH2_SCP_SEND64 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010208 +#define HAVE_LIBSSH2_SESSION_HANDSHAKE 1 +#endif + +extern const struct Curl_handler Curl_handler_scp; +extern const struct Curl_handler Curl_handler_sftp; + +#endif /* USE_LIBSSH2 */ + +#endif /* HEADER_CURL_SSH_H */ diff --git a/libcurl/src/lib/strdup.c b/libcurl/src/lib/strdup.c new file mode 100644 index 0000000..807ddac --- /dev/null +++ b/libcurl/src/lib/strdup.c @@ -0,0 +1,73 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +#include "strdup.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef HAVE_STRDUP +CURL_STATIC char *curlx_strdup(const char *str) +{ + size_t len; + char *newstr; + + if(!str) + return (char *)NULL; + + len = strlen(str); + + if(len >= ((size_t)-1) / sizeof(char)) + return (char *)NULL; + + newstr = malloc((len+1)*sizeof(char)); + if(!newstr) + return (char *)NULL; + + memcpy(newstr, str, (len+1)*sizeof(char)); + + return newstr; + +} +#endif + +/*************************************************************************** + * + * Curl_memdup(source, length) + * + * Copies the 'source' data to a newly allocated buffer (that is + * returned). Copies 'length' bytes. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +CURL_STATIC char *Curl_memdup(const char *src, size_t length) +{ + char *buffer = malloc(length); + if(!buffer) + return NULL; /* fail */ + + memcpy(buffer, src, length); + + return buffer; +} diff --git a/libcurl/src/lib/strdup.h b/libcurl/src/lib/strdup.h new file mode 100644 index 0000000..9058e33 --- /dev/null +++ b/libcurl/src/lib/strdup.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_STRDUP_H +#define HEADER_CURL_STRDUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef HAVE_STRDUP +extern CURL_STATIC char *curlx_strdup(const char *str); +#endif +CURL_STATIC char *Curl_memdup(const char *src, size_t buffer_length); + +#endif /* HEADER_CURL_STRDUP_H */ diff --git a/libcurl/src/lib/strequal.c b/libcurl/src/lib/strequal.c new file mode 100644 index 0000000..5f2f508 --- /dev/null +++ b/libcurl/src/lib/strequal.c @@ -0,0 +1,79 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_STRINGS_H +#include +#endif + +#include "strequal.h" + +/* + * @unittest: 1301 + */ +int curl_strequal(const char *first, const char *second) +{ +#if defined(HAVE_STRCASECMP) + return !(strcasecmp)(first, second); +#elif defined(HAVE_STRCMPI) + return !(strcmpi)(first, second); +#elif defined(HAVE_STRICMP) + return !(stricmp)(first, second); +#else + while(*first && *second) { + if(toupper(*first) != toupper(*second)) { + break; + } + first++; + second++; + } + return toupper(*first) == toupper(*second); +#endif +} + +/* + * @unittest: 1301 + */ +int curl_strnequal(const char *first, const char *second, size_t max) +{ +#if defined(HAVE_STRNCASECMP) + return !strncasecmp(first, second, max); +#elif defined(HAVE_STRNCMPI) + return !strncmpi(first, second, max); +#elif defined(HAVE_STRNICMP) + return !strnicmp(first, second, max); +#else + while(*first && *second && max) { + if(toupper(*first) != toupper(*second)) { + break; + } + max--; + first++; + second++; + } + if(0 == max) + return 1; /* they are equal this far */ + + return toupper(*first) == toupper(*second); +#endif +} diff --git a/libcurl/src/lib/strequal.h b/libcurl/src/lib/strequal.h new file mode 100644 index 0000000..117a305 --- /dev/null +++ b/libcurl/src/lib/strequal.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_STREQUAL_H +#define HEADER_CURL_STREQUAL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#define strequal(a,b) curl_strequal(a,b) +#define strnequal(a,b,c) curl_strnequal(a,b,c) + +#endif /* HEADER_CURL_STREQUAL_H */ + diff --git a/libcurl/src/lib/strerror.c b/libcurl/src/lib/strerror.c new file mode 100644 index 0000000..b07a534 --- /dev/null +++ b/libcurl/src/lib/strerror.c @@ -0,0 +1,1139 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2004 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_STRERROR_R +# if (!defined(HAVE_POSIX_STRERROR_R) && \ + !defined(HAVE_GLIBC_STRERROR_R) && \ + !defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)) +# error "strerror_r MUST be either POSIX, glibc or vxworks-style" +# endif +#endif + +#include + +#ifdef USE_LIBIDN +#include +#endif + +#include "strerror.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +const char * +curl_easy_strerror(CURLcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch (error) { + case CURLE_OK: + return "No error"; + + case CURLE_UNSUPPORTED_PROTOCOL: + return "Unsupported protocol"; + + case CURLE_FAILED_INIT: + return "Failed initialization"; + + case CURLE_URL_MALFORMAT: + return "URL using bad/illegal format or missing URL"; + + case CURLE_NOT_BUILT_IN: + return "A requested feature, protocol or option was not found built-in in" + " this libcurl due to a build-time decision."; + + case CURLE_COULDNT_RESOLVE_PROXY: + return "Couldn't resolve proxy name"; + + case CURLE_COULDNT_RESOLVE_HOST: + return "Couldn't resolve host name"; + + case CURLE_COULDNT_CONNECT: + return "Couldn't connect to server"; + + case CURLE_FTP_WEIRD_SERVER_REPLY: + return "FTP: weird server reply"; + + case CURLE_REMOTE_ACCESS_DENIED: + return "Access denied to remote resource"; + + case CURLE_FTP_ACCEPT_FAILED: + return "FTP: The server failed to connect to data port"; + + case CURLE_FTP_ACCEPT_TIMEOUT: + return "FTP: Accepting server connect has timed out"; + + case CURLE_FTP_PRET_FAILED: + return "FTP: The server did not accept the PRET command."; + + case CURLE_FTP_WEIRD_PASS_REPLY: + return "FTP: unknown PASS reply"; + + case CURLE_FTP_WEIRD_PASV_REPLY: + return "FTP: unknown PASV reply"; + + case CURLE_FTP_WEIRD_227_FORMAT: + return "FTP: unknown 227 response format"; + + case CURLE_FTP_CANT_GET_HOST: + return "FTP: can't figure out the host in the PASV response"; + + case CURLE_HTTP2: + return "Error in the HTTP2 framing layer"; + + case CURLE_FTP_COULDNT_SET_TYPE: + return "FTP: couldn't set file type"; + + case CURLE_PARTIAL_FILE: + return "Transferred a partial file"; + + case CURLE_FTP_COULDNT_RETR_FILE: + return "FTP: couldn't retrieve (RETR failed) the specified file"; + + case CURLE_QUOTE_ERROR: + return "Quote command returned error"; + + case CURLE_HTTP_RETURNED_ERROR: + return "HTTP response code said error"; + + case CURLE_WRITE_ERROR: + return "Failed writing received data to disk/application"; + + case CURLE_UPLOAD_FAILED: + return "Upload failed (at start/before it took off)"; + + case CURLE_READ_ERROR: + return "Failed to open/read local data from file/application"; + + case CURLE_OUT_OF_MEMORY: + return "Out of memory"; + + case CURLE_OPERATION_TIMEDOUT: + return "Timeout was reached"; + + case CURLE_FTP_PORT_FAILED: + return "FTP: command PORT failed"; + + case CURLE_FTP_COULDNT_USE_REST: + return "FTP: command REST failed"; + + case CURLE_RANGE_ERROR: + return "Requested range was not delivered by the server"; + + case CURLE_HTTP_POST_ERROR: + return "Internal problem setting up the POST"; + + case CURLE_SSL_CONNECT_ERROR: + return "SSL connect error"; + + case CURLE_BAD_DOWNLOAD_RESUME: + return "Couldn't resume download"; + + case CURLE_FILE_COULDNT_READ_FILE: + return "Couldn't read a file:// file"; + + case CURLE_LDAP_CANNOT_BIND: + return "LDAP: cannot bind"; + + case CURLE_LDAP_SEARCH_FAILED: + return "LDAP: search failed"; + + case CURLE_FUNCTION_NOT_FOUND: + return "A required function in the library was not found"; + + case CURLE_ABORTED_BY_CALLBACK: + return "Operation was aborted by an application callback"; + + case CURLE_BAD_FUNCTION_ARGUMENT: + return "A libcurl function was given a bad argument"; + + case CURLE_INTERFACE_FAILED: + return "Failed binding local connection end"; + + case CURLE_TOO_MANY_REDIRECTS : + return "Number of redirects hit maximum amount"; + + case CURLE_UNKNOWN_OPTION: + return "An unknown option was passed in to libcurl"; + + case CURLE_TELNET_OPTION_SYNTAX : + return "Malformed telnet option"; + + case CURLE_PEER_FAILED_VERIFICATION: + return "SSL peer certificate or SSH remote key was not OK"; + + case CURLE_GOT_NOTHING: + return "Server returned nothing (no headers, no data)"; + + case CURLE_SSL_ENGINE_NOTFOUND: + return "SSL crypto engine not found"; + + case CURLE_SSL_ENGINE_SETFAILED: + return "Can not set SSL crypto engine as default"; + + case CURLE_SSL_ENGINE_INITFAILED: + return "Failed to initialise SSL crypto engine"; + + case CURLE_SEND_ERROR: + return "Failed sending data to the peer"; + + case CURLE_RECV_ERROR: + return "Failure when receiving data from the peer"; + + case CURLE_SSL_CERTPROBLEM: + return "Problem with the local SSL certificate"; + + case CURLE_SSL_CIPHER: + return "Couldn't use specified SSL cipher"; + + case CURLE_SSL_CACERT: + return "Peer certificate cannot be authenticated with given CA " + "certificates"; + + case CURLE_SSL_CACERT_BADFILE: + return "Problem with the SSL CA cert (path? access rights?)"; + + case CURLE_BAD_CONTENT_ENCODING: + return "Unrecognized or bad HTTP Content or Transfer-Encoding"; + + case CURLE_LDAP_INVALID_URL: + return "Invalid LDAP URL"; + + case CURLE_FILESIZE_EXCEEDED: + return "Maximum file size exceeded"; + + case CURLE_USE_SSL_FAILED: + return "Requested SSL level failed"; + + case CURLE_SSL_SHUTDOWN_FAILED: + return "Failed to shut down the SSL connection"; + + case CURLE_SSL_CRL_BADFILE: + return "Failed to load CRL file (path? access rights?, format?)"; + + case CURLE_SSL_ISSUER_ERROR: + return "Issuer check against peer certificate failed"; + + case CURLE_SEND_FAIL_REWIND: + return "Send failed since rewinding of the data stream failed"; + + case CURLE_LOGIN_DENIED: + return "Login denied"; + + case CURLE_TFTP_NOTFOUND: + return "TFTP: File Not Found"; + + case CURLE_TFTP_PERM: + return "TFTP: Access Violation"; + + case CURLE_REMOTE_DISK_FULL: + return "Disk full or allocation exceeded"; + + case CURLE_TFTP_ILLEGAL: + return "TFTP: Illegal operation"; + + case CURLE_TFTP_UNKNOWNID: + return "TFTP: Unknown transfer ID"; + + case CURLE_REMOTE_FILE_EXISTS: + return "Remote file already exists"; + + case CURLE_TFTP_NOSUCHUSER: + return "TFTP: No such user"; + + case CURLE_CONV_FAILED: + return "Conversion failed"; + + case CURLE_CONV_REQD: + return "Caller must register CURLOPT_CONV_ callback options"; + + case CURLE_REMOTE_FILE_NOT_FOUND: + return "Remote file not found"; + + case CURLE_SSH: + return "Error in the SSH layer"; + + case CURLE_AGAIN: + return "Socket not ready for send/recv"; + + case CURLE_RTSP_CSEQ_ERROR: + return "RTSP CSeq mismatch or invalid CSeq"; + + case CURLE_RTSP_SESSION_ERROR: + return "RTSP session error"; + + case CURLE_FTP_BAD_FILE_LIST: + return "Unable to parse FTP file list"; + + case CURLE_CHUNK_FAILED: + return "Chunk callback failed"; + + case CURLE_NO_CONNECTION_AVAILABLE: + return "The max connection limit is reached"; + + case CURLE_SSL_PINNEDPUBKEYNOTMATCH: + return "SSL public key does not match pinned public key"; + + case CURLE_SSL_INVALIDCERTSTATUS: + return "SSL server certificate status verification FAILED"; + + /* error codes not used by current libcurl */ + case CURLE_OBSOLETE20: + case CURLE_OBSOLETE24: + case CURLE_OBSOLETE29: + case CURLE_OBSOLETE32: + case CURLE_OBSOLETE40: + case CURLE_OBSOLETE44: + case CURLE_OBSOLETE46: + case CURLE_OBSOLETE50: + case CURLE_OBSOLETE57: + case CURL_LAST: + break; + } + /* + * By using a switch, gcc -Wall will complain about enum values + * which do not appear, helping keep this function up-to-date. + * By using gcc -Wall -Werror, you can't forget. + * + * A table would not have the same benefit. Most compilers will + * generate code very similar to a table in any case, so there + * is little performance gain from a table. And something is broken + * for the user's application, anyways, so does it matter how fast + * it _doesn't_ work? + * + * The line number for the error will be near this comment, which + * is why it is here, and not at the start of the switch. + */ + return "Unknown error"; +#else + if(!error) + return "No error"; + else + return "Error"; +#endif +} + +const char * +curl_multi_strerror(CURLMcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch (error) { + case CURLM_CALL_MULTI_PERFORM: + return "Please call curl_multi_perform() soon"; + + case CURLM_OK: + return "No error"; + + case CURLM_BAD_HANDLE: + return "Invalid multi handle"; + + case CURLM_BAD_EASY_HANDLE: + return "Invalid easy handle"; + + case CURLM_OUT_OF_MEMORY: + return "Out of memory"; + + case CURLM_INTERNAL_ERROR: + return "Internal error"; + + case CURLM_BAD_SOCKET: + return "Invalid socket argument"; + + case CURLM_UNKNOWN_OPTION: + return "Unknown option"; + + case CURLM_ADDED_ALREADY: + return "The easy handle is already added to a multi handle"; + + case CURLM_LAST: + break; + } + + return "Unknown error"; +#else + if(error == CURLM_OK) + return "No error"; + else + return "Error"; +#endif +} + +const char * +curl_share_strerror(CURLSHcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch (error) { + case CURLSHE_OK: + return "No error"; + + case CURLSHE_BAD_OPTION: + return "Unknown share option"; + + case CURLSHE_IN_USE: + return "Share currently in use"; + + case CURLSHE_INVALID: + return "Invalid share handle"; + + case CURLSHE_NOMEM: + return "Out of memory"; + + case CURLSHE_NOT_BUILT_IN: + return "Feature not enabled in this library"; + + case CURLSHE_LAST: + break; + } + + return "CURLSHcode unknown"; +#else + if(error == CURLSHE_OK) + return "No error"; + else + return "Error"; +#endif +} + +#ifdef USE_WINSOCK + +/* This function handles most / all (?) Winsock errors cURL is able to produce. + */ +static const char * +get_winsock_error (int err, char *buf, size_t len) +{ + const char *p; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch (err) { + case WSAEINTR: + p = "Call interrupted"; + break; + case WSAEBADF: + p = "Bad file"; + break; + case WSAEACCES: + p = "Bad access"; + break; + case WSAEFAULT: + p = "Bad argument"; + break; + case WSAEINVAL: + p = "Invalid arguments"; + break; + case WSAEMFILE: + p = "Out of file descriptors"; + break; + case WSAEWOULDBLOCK: + p = "Call would block"; + break; + case WSAEINPROGRESS: + case WSAEALREADY: + p = "Blocking call in progress"; + break; + case WSAENOTSOCK: + p = "Descriptor is not a socket"; + break; + case WSAEDESTADDRREQ: + p = "Need destination address"; + break; + case WSAEMSGSIZE: + p = "Bad message size"; + break; + case WSAEPROTOTYPE: + p = "Bad protocol"; + break; + case WSAENOPROTOOPT: + p = "Protocol option is unsupported"; + break; + case WSAEPROTONOSUPPORT: + p = "Protocol is unsupported"; + break; + case WSAESOCKTNOSUPPORT: + p = "Socket is unsupported"; + break; + case WSAEOPNOTSUPP: + p = "Operation not supported"; + break; + case WSAEAFNOSUPPORT: + p = "Address family not supported"; + break; + case WSAEPFNOSUPPORT: + p = "Protocol family not supported"; + break; + case WSAEADDRINUSE: + p = "Address already in use"; + break; + case WSAEADDRNOTAVAIL: + p = "Address not available"; + break; + case WSAENETDOWN: + p = "Network down"; + break; + case WSAENETUNREACH: + p = "Network unreachable"; + break; + case WSAENETRESET: + p = "Network has been reset"; + break; + case WSAECONNABORTED: + p = "Connection was aborted"; + break; + case WSAECONNRESET: + p = "Connection was reset"; + break; + case WSAENOBUFS: + p = "No buffer space"; + break; + case WSAEISCONN: + p = "Socket is already connected"; + break; + case WSAENOTCONN: + p = "Socket is not connected"; + break; + case WSAESHUTDOWN: + p = "Socket has been shut down"; + break; + case WSAETOOMANYREFS: + p = "Too many references"; + break; + case WSAETIMEDOUT: + p = "Timed out"; + break; + case WSAECONNREFUSED: + p = "Connection refused"; + break; + case WSAELOOP: + p = "Loop??"; + break; + case WSAENAMETOOLONG: + p = "Name too long"; + break; + case WSAEHOSTDOWN: + p = "Host down"; + break; + case WSAEHOSTUNREACH: + p = "Host unreachable"; + break; + case WSAENOTEMPTY: + p = "Not empty"; + break; + case WSAEPROCLIM: + p = "Process limit reached"; + break; + case WSAEUSERS: + p = "Too many users"; + break; + case WSAEDQUOT: + p = "Bad quota"; + break; + case WSAESTALE: + p = "Something is stale"; + break; + case WSAEREMOTE: + p = "Remote error"; + break; +#ifdef WSAEDISCON /* missing in SalfordC! */ + case WSAEDISCON: + p = "Disconnected"; + break; +#endif + /* Extended Winsock errors */ + case WSASYSNOTREADY: + p = "Winsock library is not ready"; + break; + case WSANOTINITIALISED: + p = "Winsock library not initialised"; + break; + case WSAVERNOTSUPPORTED: + p = "Winsock version not supported"; + break; + + /* getXbyY() errors (already handled in herrmsg): + * Authoritative Answer: Host not found */ + case WSAHOST_NOT_FOUND: + p = "Host not found"; + break; + + /* Non-Authoritative: Host not found, or SERVERFAIL */ + case WSATRY_AGAIN: + p = "Host not found, try again"; + break; + + /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ + case WSANO_RECOVERY: + p = "Unrecoverable error in call to nameserver"; + break; + + /* Valid name, no data record of requested type */ + case WSANO_DATA: + p = "No data record of requested type"; + break; + + default: + return NULL; + } +#else + if(!err) + return NULL; + else + p = "error"; +#endif + strncpy (buf, p, len); + buf [len-1] = '\0'; + return buf; +} +#endif /* USE_WINSOCK */ + +/* + * Our thread-safe and smart strerror() replacement. + * + * The 'err' argument passed in to this function MUST be a true errno number + * as reported on this system. We do no range checking on the number before + * we pass it to the "number-to-message" conversion function and there might + * be systems that don't do proper range checking in there themselves. + * + * We don't do range checking (on systems other than Windows) since there is + * no good reliable and portable way to do it. + */ +CURL_STATIC const char *Curl_strerror(struct connectdata *conn, int err) +{ + char *buf, *p; + size_t max; + int old_errno = ERRNO; + + DEBUGASSERT(conn); + DEBUGASSERT(err >= 0); + + buf = conn->syserr_buf; + max = sizeof(conn->syserr_buf)-1; + *buf = '\0'; + +#ifdef USE_WINSOCK + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL); + wcstombs(buf, wbuf, max); + } +#elif defined(CURL_WINRT) + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, wbuf, sizeof(wbuf) / sizeof(wchar_t), NULL); + wcstombs(buf, wbuf, max); + } +#else + /* 'sys_nerr' is the maximum errno number, it is not widely portable */ + if(err >= 0 && err < sys_nerr) + strncpy(buf, strerror(err), max); + else { + if(!get_winsock_error(err, buf, max) && + !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, buf, (DWORD)max, NULL)) + snprintf(buf, max, "Unknown error %d (%#x)", err, err); + } +#endif + +#else /* not USE_WINSOCK coming up */ + +#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R) + /* + * The POSIX-style strerror_r() may set errno to ERANGE if insufficient + * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated + * message string, or EINVAL if 'errnum' is not a valid error number. + */ + if(0 != strerror_r(err, buf, max)) { + if('\0' == buf[0]) + snprintf(buf, max, "Unknown error %d", err); + } +#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R) + /* + * The glibc-style strerror_r() only *might* use the buffer we pass to + * the function, but it always returns the error message as a pointer, + * so we must copy that string unconditionally (if non-NULL). + */ + { + char buffer[256]; + char *msg = strerror_r(err, buffer, sizeof(buffer)); + if(msg) + strncpy(buf, msg, max); + else + snprintf(buf, max, "Unknown error %d", err); + } +#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R) + /* + * The vxworks-style strerror_r() does use the buffer we pass to the function. + * The buffer size should be at least NAME_MAX (256) + */ + { + char buffer[256]; + if(OK == strerror_r(err, buffer)) + strncpy(buf, buffer, max); + else + snprintf(buf, max, "Unknown error %d", err); + } +#else + { + char *msg = strerror(err); + if(msg) + strncpy(buf, msg, max); + else + snprintf(buf, max, "Unknown error %d", err); + } +#endif + +#endif /* end of ! USE_WINSOCK */ + + buf[max] = '\0'; /* make sure the string is zero terminated */ + + /* strip trailing '\r\n' or '\n'. */ + if((p = strrchr(buf, '\n')) != NULL && (p - buf) >= 2) + *p = '\0'; + if((p = strrchr(buf, '\r')) != NULL && (p - buf) >= 1) + *p = '\0'; + + if(old_errno != ERRNO) + SET_ERRNO(old_errno); + + return buf; +} + +#ifdef USE_LIBIDN +/* + * Return error-string for libidn status as returned from idna_to_ascii_lz(). + */ +CURL_STATIC const char *Curl_idn_strerror (struct connectdata *conn, int err) +{ +#ifdef HAVE_IDNA_STRERROR + (void)conn; + return idna_strerror((Idna_rc) err); +#else + const char *str; + char *buf; + size_t max; + + DEBUGASSERT(conn); + + buf = conn->syserr_buf; + max = sizeof(conn->syserr_buf)-1; + *buf = '\0'; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch ((Idna_rc)err) { + case IDNA_SUCCESS: + str = "No error"; + break; + case IDNA_STRINGPREP_ERROR: + str = "Error in string preparation"; + break; + case IDNA_PUNYCODE_ERROR: + str = "Error in Punycode operation"; + break; + case IDNA_CONTAINS_NON_LDH: + str = "Illegal ASCII characters"; + break; + case IDNA_CONTAINS_MINUS: + str = "Contains minus"; + break; + case IDNA_INVALID_LENGTH: + str = "Invalid output length"; + break; + case IDNA_NO_ACE_PREFIX: + str = "No ACE prefix (\"xn--\")"; + break; + case IDNA_ROUNDTRIP_VERIFY_ERROR: + str = "Round trip verify error"; + break; + case IDNA_CONTAINS_ACE_PREFIX: + str = "Already have ACE prefix (\"xn--\")"; + break; + case IDNA_ICONV_ERROR: + str = "Locale conversion failed"; + break; + case IDNA_MALLOC_ERROR: + str = "Allocation failed"; + break; + case IDNA_DLOPEN_ERROR: + str = "dlopen() error"; + break; + default: + snprintf(buf, max, "error %d", err); + str = NULL; + break; + } +#else + if((Idna_rc)err == IDNA_SUCCESS) + str = "No error"; + else + str = "Error"; +#endif + if(str) + strncpy(buf, str, max); + buf[max] = '\0'; + return (buf); +#endif +} +#endif /* USE_LIBIDN */ + +#ifdef USE_WINDOWS_SSPI +CURL_STATIC const char *Curl_sspi_strerror (struct connectdata *conn, int err) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + char txtbuf[80]; + char msgbuf[sizeof(conn->syserr_buf)]; + char *p, *str, *msg = NULL; + bool msg_formatted = FALSE; + int old_errno; +#endif + const char *txt; + char *outbuf; + size_t outmax; + + DEBUGASSERT(conn); + + outbuf = conn->syserr_buf; + outmax = sizeof(conn->syserr_buf)-1; + *outbuf = '\0'; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + + old_errno = ERRNO; + + switch (err) { + case SEC_E_OK: + txt = "No error"; + break; + case SEC_E_ALGORITHM_MISMATCH: + txt = "SEC_E_ALGORITHM_MISMATCH"; + break; + case SEC_E_BAD_BINDINGS: + txt = "SEC_E_BAD_BINDINGS"; + break; + case SEC_E_BAD_PKGID: + txt = "SEC_E_BAD_PKGID"; + break; + case SEC_E_BUFFER_TOO_SMALL: + txt = "SEC_E_BUFFER_TOO_SMALL"; + break; + case SEC_E_CANNOT_INSTALL: + txt = "SEC_E_CANNOT_INSTALL"; + break; + case SEC_E_CANNOT_PACK: + txt = "SEC_E_CANNOT_PACK"; + break; + case SEC_E_CERT_EXPIRED: + txt = "SEC_E_CERT_EXPIRED"; + break; + case SEC_E_CERT_UNKNOWN: + txt = "SEC_E_CERT_UNKNOWN"; + break; + case SEC_E_CERT_WRONG_USAGE: + txt = "SEC_E_CERT_WRONG_USAGE"; + break; + case SEC_E_CONTEXT_EXPIRED: + txt = "SEC_E_CONTEXT_EXPIRED"; + break; + case SEC_E_CROSSREALM_DELEGATION_FAILURE: + txt = "SEC_E_CROSSREALM_DELEGATION_FAILURE"; + break; + case SEC_E_CRYPTO_SYSTEM_INVALID: + txt = "SEC_E_CRYPTO_SYSTEM_INVALID"; + break; + case SEC_E_DECRYPT_FAILURE: + txt = "SEC_E_DECRYPT_FAILURE"; + break; + case SEC_E_DELEGATION_POLICY: + txt = "SEC_E_DELEGATION_POLICY"; + break; + case SEC_E_DELEGATION_REQUIRED: + txt = "SEC_E_DELEGATION_REQUIRED"; + break; + case SEC_E_DOWNGRADE_DETECTED: + txt = "SEC_E_DOWNGRADE_DETECTED"; + break; + case SEC_E_ENCRYPT_FAILURE: + txt = "SEC_E_ENCRYPT_FAILURE"; + break; + case SEC_E_ILLEGAL_MESSAGE: + txt = "SEC_E_ILLEGAL_MESSAGE"; + break; + case SEC_E_INCOMPLETE_CREDENTIALS: + txt = "SEC_E_INCOMPLETE_CREDENTIALS"; + break; + case SEC_E_INCOMPLETE_MESSAGE: + txt = "SEC_E_INCOMPLETE_MESSAGE"; + break; + case SEC_E_INSUFFICIENT_MEMORY: + txt = "SEC_E_INSUFFICIENT_MEMORY"; + break; + case SEC_E_INTERNAL_ERROR: + txt = "SEC_E_INTERNAL_ERROR"; + break; + case SEC_E_INVALID_HANDLE: + txt = "SEC_E_INVALID_HANDLE"; + break; + case SEC_E_INVALID_PARAMETER: + txt = "SEC_E_INVALID_PARAMETER"; + break; + case SEC_E_INVALID_TOKEN: + txt = "SEC_E_INVALID_TOKEN"; + break; + case SEC_E_ISSUING_CA_UNTRUSTED: + txt = "SEC_E_ISSUING_CA_UNTRUSTED"; + break; + case SEC_E_ISSUING_CA_UNTRUSTED_KDC: + txt = "SEC_E_ISSUING_CA_UNTRUSTED_KDC"; + break; + case SEC_E_KDC_CERT_EXPIRED: + txt = "SEC_E_KDC_CERT_EXPIRED"; + break; + case SEC_E_KDC_CERT_REVOKED: + txt = "SEC_E_KDC_CERT_REVOKED"; + break; + case SEC_E_KDC_INVALID_REQUEST: + txt = "SEC_E_KDC_INVALID_REQUEST"; + break; + case SEC_E_KDC_UNABLE_TO_REFER: + txt = "SEC_E_KDC_UNABLE_TO_REFER"; + break; + case SEC_E_KDC_UNKNOWN_ETYPE: + txt = "SEC_E_KDC_UNKNOWN_ETYPE"; + break; + case SEC_E_LOGON_DENIED: + txt = "SEC_E_LOGON_DENIED"; + break; + case SEC_E_MAX_REFERRALS_EXCEEDED: + txt = "SEC_E_MAX_REFERRALS_EXCEEDED"; + break; + case SEC_E_MESSAGE_ALTERED: + txt = "SEC_E_MESSAGE_ALTERED"; + break; + case SEC_E_MULTIPLE_ACCOUNTS: + txt = "SEC_E_MULTIPLE_ACCOUNTS"; + break; + case SEC_E_MUST_BE_KDC: + txt = "SEC_E_MUST_BE_KDC"; + break; + case SEC_E_NOT_OWNER: + txt = "SEC_E_NOT_OWNER"; + break; + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + txt = "SEC_E_NO_AUTHENTICATING_AUTHORITY"; + break; + case SEC_E_NO_CREDENTIALS: + txt = "SEC_E_NO_CREDENTIALS"; + break; + case SEC_E_NO_IMPERSONATION: + txt = "SEC_E_NO_IMPERSONATION"; + break; + case SEC_E_NO_IP_ADDRESSES: + txt = "SEC_E_NO_IP_ADDRESSES"; + break; + case SEC_E_NO_KERB_KEY: + txt = "SEC_E_NO_KERB_KEY"; + break; + case SEC_E_NO_PA_DATA: + txt = "SEC_E_NO_PA_DATA"; + break; + case SEC_E_NO_S4U_PROT_SUPPORT: + txt = "SEC_E_NO_S4U_PROT_SUPPORT"; + break; + case SEC_E_NO_TGT_REPLY: + txt = "SEC_E_NO_TGT_REPLY"; + break; + case SEC_E_OUT_OF_SEQUENCE: + txt = "SEC_E_OUT_OF_SEQUENCE"; + break; + case SEC_E_PKINIT_CLIENT_FAILURE: + txt = "SEC_E_PKINIT_CLIENT_FAILURE"; + break; + case SEC_E_PKINIT_NAME_MISMATCH: + txt = "SEC_E_PKINIT_NAME_MISMATCH"; + break; + case SEC_E_POLICY_NLTM_ONLY: + txt = "SEC_E_POLICY_NLTM_ONLY"; + break; + case SEC_E_QOP_NOT_SUPPORTED: + txt = "SEC_E_QOP_NOT_SUPPORTED"; + break; + case SEC_E_REVOCATION_OFFLINE_C: + txt = "SEC_E_REVOCATION_OFFLINE_C"; + break; + case SEC_E_REVOCATION_OFFLINE_KDC: + txt = "SEC_E_REVOCATION_OFFLINE_KDC"; + break; + case SEC_E_SECPKG_NOT_FOUND: + txt = "SEC_E_SECPKG_NOT_FOUND"; + break; + case SEC_E_SECURITY_QOS_FAILED: + txt = "SEC_E_SECURITY_QOS_FAILED"; + break; + case SEC_E_SHUTDOWN_IN_PROGRESS: + txt = "SEC_E_SHUTDOWN_IN_PROGRESS"; + break; + case SEC_E_SMARTCARD_CERT_EXPIRED: + txt = "SEC_E_SMARTCARD_CERT_EXPIRED"; + break; + case SEC_E_SMARTCARD_CERT_REVOKED: + txt = "SEC_E_SMARTCARD_CERT_REVOKED"; + break; + case SEC_E_SMARTCARD_LOGON_REQUIRED: + txt = "SEC_E_SMARTCARD_LOGON_REQUIRED"; + break; + case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED: + txt = "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED"; + break; + case SEC_E_TARGET_UNKNOWN: + txt = "SEC_E_TARGET_UNKNOWN"; + break; + case SEC_E_TIME_SKEW: + txt = "SEC_E_TIME_SKEW"; + break; + case SEC_E_TOO_MANY_PRINCIPALS: + txt = "SEC_E_TOO_MANY_PRINCIPALS"; + break; + case SEC_E_UNFINISHED_CONTEXT_DELETED: + txt = "SEC_E_UNFINISHED_CONTEXT_DELETED"; + break; + case SEC_E_UNKNOWN_CREDENTIALS: + txt = "SEC_E_UNKNOWN_CREDENTIALS"; + break; + case SEC_E_UNSUPPORTED_FUNCTION: + txt = "SEC_E_UNSUPPORTED_FUNCTION"; + break; + case SEC_E_UNSUPPORTED_PREAUTH: + txt = "SEC_E_UNSUPPORTED_PREAUTH"; + break; + case SEC_E_UNTRUSTED_ROOT: + txt = "SEC_E_UNTRUSTED_ROOT"; + break; + case SEC_E_WRONG_CREDENTIAL_HANDLE: + txt = "SEC_E_WRONG_CREDENTIAL_HANDLE"; + break; + case SEC_E_WRONG_PRINCIPAL: + txt = "SEC_E_WRONG_PRINCIPAL"; + break; + case SEC_I_COMPLETE_AND_CONTINUE: + txt = "SEC_I_COMPLETE_AND_CONTINUE"; + break; + case SEC_I_COMPLETE_NEEDED: + txt = "SEC_I_COMPLETE_NEEDED"; + break; + case SEC_I_CONTEXT_EXPIRED: + txt = "SEC_I_CONTEXT_EXPIRED"; + break; + case SEC_I_CONTINUE_NEEDED: + txt = "SEC_I_CONTINUE_NEEDED"; + break; + case SEC_I_INCOMPLETE_CREDENTIALS: + txt = "SEC_I_INCOMPLETE_CREDENTIALS"; + break; + case SEC_I_LOCAL_LOGON: + txt = "SEC_I_LOCAL_LOGON"; + break; + case SEC_I_NO_LSA_CONTEXT: + txt = "SEC_I_NO_LSA_CONTEXT"; + break; + case SEC_I_RENEGOTIATE: + txt = "SEC_I_RENEGOTIATE"; + break; + case SEC_I_SIGNATURE_NEEDED: + txt = "SEC_I_SIGNATURE_NEEDED"; + break; + default: + txt = "Unknown error"; + } + + if(err == SEC_E_OK) + strncpy(outbuf, txt, outmax); + else { + str = txtbuf; + snprintf(txtbuf, sizeof(txtbuf), "%s (0x%04X%04X)", + txt, (err >> 16) & 0xffff, err & 0xffff); + txtbuf[sizeof(txtbuf)-1] = '\0'; + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) { + wcstombs(msgbuf, wbuf, sizeof(msgbuf)-1); + msg_formatted = TRUE; + } + } +#else + if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + msgbuf, sizeof(msgbuf)-1, NULL)) { + msg_formatted = TRUE; + } +#endif + if(msg_formatted) { + msgbuf[sizeof(msgbuf)-1] = '\0'; + /* strip trailing '\r\n' or '\n' */ + if((p = strrchr(msgbuf, '\n')) != NULL && (p - msgbuf) >= 2) + *p = '\0'; + if((p = strrchr(msgbuf, '\r')) != NULL && (p - msgbuf) >= 1) + *p = '\0'; + msg = msgbuf; + } + if(msg) + snprintf(outbuf, outmax, "%s - %s", str, msg); + else + strncpy(outbuf, str, outmax); + } + + if(old_errno != ERRNO) + SET_ERRNO(old_errno); + +#else + + if(err == SEC_E_OK) + txt = "No error"; + else + txt = "Error"; + + strncpy(outbuf, txt, outmax); + +#endif + + outbuf[outmax] = '\0'; + + return outbuf; +} +#endif /* USE_WINDOWS_SSPI */ diff --git a/libcurl/src/lib/strerror.h b/libcurl/src/lib/strerror.h new file mode 100644 index 0000000..b0f1675 --- /dev/null +++ b/libcurl/src/lib/strerror.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_STRERROR_H +#define HEADER_CURL_STRERROR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "urldata.h" + +CURL_STATIC const char *Curl_strerror (struct connectdata *conn, int err); + +#ifdef USE_LIBIDN +CURL_STATIC const char *Curl_idn_strerror (struct connectdata *conn, int err); +#endif + +#ifdef USE_WINDOWS_SSPI +CURL_STATIC const char *Curl_sspi_strerror (struct connectdata *conn, int err); +#endif + +#endif /* HEADER_CURL_STRERROR_H */ diff --git a/libcurl/src/lib/strtok.c b/libcurl/src/lib/strtok.c new file mode 100644 index 0000000..9a1fdf1 --- /dev/null +++ b/libcurl/src/lib/strtok.c @@ -0,0 +1,66 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef HAVE_STRTOK_R +#include + +#include "strtok.h" + +CURL_STATIC char * +Curl_strtok_r(char *ptr, const char *sep, char **end) +{ + if(!ptr) + /* we got NULL input so then we get our last position instead */ + ptr = *end; + + /* pass all letters that are including in the separator string */ + while(*ptr && strchr(sep, *ptr)) + ++ptr; + + if(*ptr) { + /* so this is where the next piece of string starts */ + char *start = ptr; + + /* set the end pointer to the first byte after the start */ + *end = start + 1; + + /* scan through the string to find where it ends, it ends on a + null byte or a character that exists in the separator string */ + while(**end && !strchr(sep, **end)) + ++*end; + + if(**end) { + /* the end is not a null byte */ + **end = '\0'; /* zero terminate it! */ + ++*end; /* advance the last pointer to beyond the null byte */ + } + + return start; /* return the position where the string starts */ + } + + /* we ended up on a null byte, there are no more strings to find! */ + return NULL; +} + +#endif /* this was only compiled if strtok_r wasn't present */ diff --git a/libcurl/src/lib/strtok.h b/libcurl/src/lib/strtok.h new file mode 100644 index 0000000..c2fa92d --- /dev/null +++ b/libcurl/src/lib/strtok.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_STRTOK_H +#define HEADER_CURL_STRTOK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +#include + +#ifndef HAVE_STRTOK_R +CURL_STATIC char *Curl_strtok_r(char *s, const char *delim, char **last); +#define strtok_r Curl_strtok_r +#else +#include +#endif + +#endif /* HEADER_CURL_STRTOK_H */ diff --git a/libcurl/src/lib/strtoofft.c b/libcurl/src/lib/strtoofft.c new file mode 100644 index 0000000..e6da0af --- /dev/null +++ b/libcurl/src/lib/strtoofft.c @@ -0,0 +1,188 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "strtoofft.h" + +/* + * NOTE: + * + * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we + * could use in case strtoll() doesn't exist... See + * http://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html + */ + +#ifdef NEED_CURL_STRTOLL + +/* Range tests can be used for alphanum decoding if characters are consecutive, + like in ASCII. Else an array is scanned. Determine this condition now. */ + +#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25 + +#define NO_RANGE_TEST + +static const char valchars[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +#endif + +static int get_char(char c, int base); + +/** + * Emulated version of the strtoll function. This extracts a long long + * value from the given input string and returns it. + */ +CURL_STATIC curl_off_t +curlx_strtoll(const char *nptr, char **endptr, int base) +{ + char *end; + int is_negative = 0; + int overflow; + int i; + curl_off_t value = 0; + curl_off_t newval; + + /* Skip leading whitespace. */ + end = (char *)nptr; + while(ISSPACE(end[0])) { + end++; + } + + /* Handle the sign, if any. */ + if(end[0] == '-') { + is_negative = 1; + end++; + } + else if(end[0] == '+') { + end++; + } + else if(end[0] == '\0') { + /* We had nothing but perhaps some whitespace -- there was no number. */ + if(endptr) { + *endptr = end; + } + return 0; + } + + /* Handle special beginnings, if present and allowed. */ + if(end[0] == '0' && end[1] == 'x') { + if(base == 16 || base == 0) { + end += 2; + base = 16; + } + } + else if(end[0] == '0') { + if(base == 8 || base == 0) { + end++; + base = 8; + } + } + + /* Matching strtol, if the base is 0 and it doesn't look like + * the number is octal or hex, we assume it's base 10. + */ + if(base == 0) { + base = 10; + } + + /* Loop handling digits. */ + value = 0; + overflow = 0; + for(i = get_char(end[0], base); + i != -1; + end++, i = get_char(end[0], base)) { + newval = base * value + i; + if(newval < value) { + /* We've overflowed. */ + overflow = 1; + break; + } + else + value = newval; + } + + if(!overflow) { + if(is_negative) { + /* Fix the sign. */ + value *= -1; + } + } + else { + if(is_negative) + value = CURL_OFF_T_MIN; + else + value = CURL_OFF_T_MAX; + + SET_ERRNO(ERANGE); + } + + if(endptr) + *endptr = end; + + return value; +} + +/** + * Returns the value of c in the given base, or -1 if c cannot + * be interpreted properly in that base (i.e., is out of range, + * is a null, etc.). + * + * @param c the character to interpret according to base + * @param base the base in which to interpret c + * + * @return the value of c in base, or -1 if c isn't in range + */ +static int get_char(char c, int base) +{ +#ifndef NO_RANGE_TEST + int value = -1; + if(c <= '9' && c >= '0') { + value = c - '0'; + } + else if(c <= 'Z' && c >= 'A') { + value = c - 'A' + 10; + } + else if(c <= 'z' && c >= 'a') { + value = c - 'a' + 10; + } +#else + const char * cp; + int value; + + cp = memchr(valchars, c, 10 + 26 + 26); + + if(!cp) + return -1; + + value = cp - valchars; + + if(value >= 10 + 26) + value -= 26; /* Lowercase. */ +#endif + + if(value >= base) { + value = -1; + } + + return value; +} +#endif /* Only present if we need strtoll, but don't have it. */ diff --git a/libcurl/src/lib/strtoofft.h b/libcurl/src/lib/strtoofft.h new file mode 100644 index 0000000..e1c3bda --- /dev/null +++ b/libcurl/src/lib/strtoofft.h @@ -0,0 +1,75 @@ +#ifndef HEADER_CURL_STRTOOFFT_H +#define HEADER_CURL_STRTOOFFT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * Determine which string to integral data type conversion function we use + * to implement string conversion to our curl_off_t integral data type. + * + * Notice that curl_off_t might be 64 or 32 bit wide, and that it might use + * an underlying data type which might be 'long', 'int64_t', 'long long' or + * '__int64' and more remotely other data types. + * + * On systems where the size of curl_off_t is greater than the size of 'long' + * the conversion function to use is strtoll() if it is available, otherwise, + * we emulate its functionality with our own clone. + * + * On systems where the size of curl_off_t is smaller or equal than the size + * of 'long' the conversion function to use is strtol(). + */ + +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) +# ifdef HAVE_STRTOLL +# define curlx_strtoofft strtoll +# else +# if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64) +# if defined(_SAL_VERSION) + _Check_return_ _CRTIMP __int64 __cdecl _strtoi64( + _In_z_ const char *_String, + _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix); +# else + _CRTIMP __int64 __cdecl _strtoi64(const char *_String, + char **_EndPtr, int _Radix); +# endif +# define curlx_strtoofft _strtoi64 +# else + CURL_STATIC curl_off_t curlx_strtoll(const char *nptr, char **endptr, int base); +# define curlx_strtoofft curlx_strtoll +# define NEED_CURL_STRTOLL 1 +# endif +# endif +#else +# define curlx_strtoofft strtol +#endif + +#if (CURL_SIZEOF_CURL_OFF_T == 4) +# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF) +#else + /* assume CURL_SIZEOF_CURL_OFF_T == 8 */ +# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) +#endif +#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1)) + +#endif /* HEADER_CURL_STRTOOFFT_H */ diff --git a/libcurl/src/lib/telnet.c b/libcurl/src/lib/telnet.c new file mode 100644 index 0000000..91863c0 --- /dev/null +++ b/libcurl/src/lib/telnet.c @@ -0,0 +1,1674 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_TELNET + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "telnet.h" +#include "connect.h" +#include "progress.h" +#include "curl_printf.h" + +#define TELOPTS +#define TELCMDS + +#include "arpa_telnet.h" +#include "select.h" +#include "strequal.h" +#include "rawstr.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define SUBBUFSIZE 512 + +#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer +#define CURL_SB_TERM(x) \ + do { \ + x->subend = x->subpointer; \ + CURL_SB_CLEAR(x); \ + } WHILE_FALSE +#define CURL_SB_ACCUM(x,c) \ + do { \ + if(x->subpointer < (x->subbuffer+sizeof x->subbuffer)) \ + *x->subpointer++ = (c); \ + } WHILE_FALSE + +#define CURL_SB_GET(x) ((*x->subpointer++)&0xff) +#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) +#define CURL_SB_EOF(x) (x->subpointer >= x->subend) +#define CURL_SB_LEN(x) (x->subend - x->subpointer) + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define printoption(a,b,c,d) Curl_nop_stmt +#endif + +#ifdef USE_WINSOCK +typedef FARPROC WSOCK2_FUNC; +static CURLcode check_wsock2 ( struct SessionHandle *data ); +#endif + +static +CURLcode telrcv(struct connectdata *, + const unsigned char *inbuf, /* Data received from socket */ + ssize_t count); /* Number of bytes received */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void printoption(struct SessionHandle *data, + const char *direction, + int cmd, int option); +#endif + +static void negotiate(struct connectdata *); +static void send_negotiation(struct connectdata *, int cmd, int option); +static void set_local_option(struct connectdata *, int cmd, int option); +static void set_remote_option(struct connectdata *, int cmd, int option); + +static void printsub(struct SessionHandle *data, + int direction, unsigned char *pointer, + size_t length); +static void suboption(struct connectdata *); +static void sendsuboption(struct connectdata *conn, int option); + +static CURLcode telnet_do(struct connectdata *conn, bool *done); +static CURLcode telnet_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode send_telnet_data(struct connectdata *conn, + char *buffer, ssize_t nread); + +/* For negotiation compliant to RFC 1143 */ +#define CURL_NO 0 +#define CURL_YES 1 +#define CURL_WANTYES 2 +#define CURL_WANTNO 3 + +#define CURL_EMPTY 0 +#define CURL_OPPOSITE 1 + +/* + * Telnet receiver states for fsm + */ +typedef enum +{ + CURL_TS_DATA = 0, + CURL_TS_IAC, + CURL_TS_WILL, + CURL_TS_WONT, + CURL_TS_DO, + CURL_TS_DONT, + CURL_TS_CR, + CURL_TS_SB, /* sub-option collection */ + CURL_TS_SE /* looking for sub-option end */ +} TelnetReceive; + +struct TELNET { + int please_negotiate; + int already_negotiated; + int us[256]; + int usq[256]; + int us_preferred[256]; + int him[256]; + int himq[256]; + int him_preferred[256]; + int subnegotiation[256]; + char subopt_ttype[32]; /* Set with suboption TTYPE */ + char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */ + unsigned short subopt_wsx; /* Set with suboption NAWS */ + unsigned short subopt_wsy; /* Set with suboption NAWS */ + struct curl_slist *telnet_vars; /* Environment variables */ + + /* suboptions */ + unsigned char subbuffer[SUBBUFSIZE]; + unsigned char *subpointer, *subend; /* buffer for sub-options */ + + TelnetReceive telrcv_state; +}; + + +/* + * TELNET protocol handler. + */ + +const struct Curl_handler Curl_handler_telnet = { + "TELNET", /* scheme */ + ZERO_NULL, /* setup_connection */ + telnet_do, /* do_it */ + telnet_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_TELNET, /* defport */ + CURLPROTO_TELNET, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + + +#ifdef USE_WINSOCK +static CURLcode +check_wsock2 ( struct SessionHandle *data ) +{ + int err; + WORD wVersionRequested; + WSADATA wsaData; + + DEBUGASSERT(data); + + /* telnet requires at least WinSock 2.0 so ask for it. */ + wVersionRequested = MAKEWORD(2, 0); + + err = WSAStartup(wVersionRequested, &wsaData); + + /* We must've called this once already, so this call */ + /* should always succeed. But, just in case... */ + if(err != 0) { + failf(data,"WSAStartup failed (%d)",err); + return CURLE_FAILED_INIT; + } + + /* We have to have a WSACleanup call for every successful */ + /* WSAStartup call. */ + WSACleanup(); + + /* Check that our version is supported */ + if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) { + /* Our version isn't supported */ + failf(data, "insufficient winsock version to support " + "telnet"); + return CURLE_FAILED_INIT; + } + + /* Our version is supported */ + return CURLE_OK; +} +#endif + +static +CURLcode init_telnet(struct connectdata *conn) +{ + struct TELNET *tn; + + tn = calloc(1, sizeof(struct TELNET)); + if(!tn) + return CURLE_OUT_OF_MEMORY; + + conn->data->req.protop = tn; /* make us known */ + + tn->telrcv_state = CURL_TS_DATA; + + /* Init suboptions */ + CURL_SB_CLEAR(tn); + + /* Set the options we want by default */ + tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES; + tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES; + + /* To be compliant with previous releases of libcurl + we enable this option by default. This behaviour + can be changed thanks to the "BINARY" option in + CURLOPT_TELNETOPTIONS + */ + tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES; + tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES; + + /* We must allow the server to echo what we sent + but it is not necessary to request the server + to do so (it might forces the server to close + the connection). Hence, we ignore ECHO in the + negotiate function + */ + tn->him_preferred[CURL_TELOPT_ECHO] = CURL_YES; + + /* Set the subnegotiation fields to send information + just after negotiation passed (do/will) + + Default values are (0,0) initialized by calloc. + According to the RFC1013 it is valid: + A value equal to zero is acceptable for the width (or height), + and means that no character width (or height) is being sent. + In this case, the width (or height) that will be assumed by the + Telnet server is operating system specific (it will probably be + based upon the terminal type information that may have been sent + using the TERMINAL TYPE Telnet option). */ + tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES; + return CURLE_OK; +} + +static void negotiate(struct connectdata *conn) +{ + int i; + struct TELNET *tn = (struct TELNET *) conn->data->req.protop; + + for(i = 0;i < CURL_NTELOPTS;i++) { + if(i==CURL_TELOPT_ECHO) + continue; + + if(tn->us_preferred[i] == CURL_YES) + set_local_option(conn, i, CURL_YES); + + if(tn->him_preferred[i] == CURL_YES) + set_remote_option(conn, i, CURL_YES); + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void printoption(struct SessionHandle *data, + const char *direction, int cmd, int option) +{ + const char *fmt; + const char *opt; + + if(data->set.verbose) { + if(cmd == CURL_IAC) { + if(CURL_TELCMD_OK(option)) + infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option)); + else + infof(data, "%s IAC %d\n", direction, option); + } + else { + fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" : + (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0; + if(fmt) { + if(CURL_TELOPT_OK(option)) + opt = CURL_TELOPT(option); + else if(option == CURL_TELOPT_EXOPL) + opt = "EXOPL"; + else + opt = NULL; + + if(opt) + infof(data, "%s %s %s\n", direction, fmt, opt); + else + infof(data, "%s %s %d\n", direction, fmt, option); + } + else + infof(data, "%s %d %d\n", direction, cmd, option); + } + } +} +#endif + +static void send_negotiation(struct connectdata *conn, int cmd, int option) +{ + unsigned char buf[3]; + ssize_t bytes_written; + int err; + struct SessionHandle *data = conn->data; + + buf[0] = CURL_IAC; + buf[1] = (unsigned char)cmd; + buf[2] = (unsigned char)option; + + bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + + printoption(conn->data, "SENT", cmd, option); +} + +static +void set_remote_option(struct connectdata *conn, int option, int newstate) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + if(newstate == CURL_YES) { + switch(tn->him[option]) { + case CURL_NO: + tn->him[option] = CURL_WANTYES; + send_negotiation(conn, CURL_DO, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Already negotiating for CURL_YES, queue the request */ + tn->himq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + /* Error: already queued an enable request */ + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Error: already negotiating for enable */ + break; + case CURL_OPPOSITE: + tn->himq[option] = CURL_EMPTY; + break; + } + break; + } + } + else { /* NO */ + switch(tn->him[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->him[option] = CURL_WANTNO; + send_negotiation(conn, CURL_DONT, option); + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Already negotiating for NO */ + break; + case CURL_OPPOSITE: + tn->himq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->himq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + break; + } + break; + } + } +} + +static +void rec_will(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->him[option]) { + case CURL_NO: + if(tn->him_preferred[option] == CURL_YES) { + tn->him[option] = CURL_YES; + send_negotiation(conn, CURL_DO, option); + } + else + send_negotiation(conn, CURL_DONT, option); + + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Error: DONT answered by WILL */ + tn->him[option] = CURL_NO; + break; + case CURL_OPPOSITE: + /* Error: DONT answered by WILL */ + tn->him[option] = CURL_YES; + tn->himq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_YES; + break; + case CURL_OPPOSITE: + tn->him[option] = CURL_WANTNO; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_DONT, option); + break; + } + break; + } +} + +static +void rec_wont(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->him[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->him[option] = CURL_NO; + send_negotiation(conn, CURL_DONT, option); + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_NO; + break; + + case CURL_OPPOSITE: + tn->him[option] = CURL_WANTYES; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_DO, option); + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_NO; + break; + case CURL_OPPOSITE: + tn->him[option] = CURL_NO; + tn->himq[option] = CURL_EMPTY; + break; + } + break; + } +} + +static void +set_local_option(struct connectdata *conn, int option, int newstate) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + if(newstate == CURL_YES) { + switch(tn->us[option]) { + case CURL_NO: + tn->us[option] = CURL_WANTYES; + send_negotiation(conn, CURL_WILL, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Already negotiating for CURL_YES, queue the request */ + tn->usq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + /* Error: already queued an enable request */ + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Error: already negotiating for enable */ + break; + case CURL_OPPOSITE: + tn->usq[option] = CURL_EMPTY; + break; + } + break; + } + } + else { /* NO */ + switch(tn->us[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->us[option] = CURL_WANTNO; + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Already negotiating for NO */ + break; + case CURL_OPPOSITE: + tn->usq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->usq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + break; + } + break; + } + } +} + +static +void rec_do(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->us[option]) { + case CURL_NO: + if(tn->us_preferred[option] == CURL_YES) { + tn->us[option] = CURL_YES; + send_negotiation(conn, CURL_WILL, option); + if(tn->subnegotiation[option] == CURL_YES) + /* transmission of data option */ + sendsuboption(conn, option); + } + else if(tn->subnegotiation[option] == CURL_YES) { + /* send information to achieve this option*/ + tn->us[option] = CURL_YES; + send_negotiation(conn, CURL_WILL, option); + sendsuboption(conn, option); + } + else + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Error: DONT answered by WILL */ + tn->us[option] = CURL_NO; + break; + case CURL_OPPOSITE: + /* Error: DONT answered by WILL */ + tn->us[option] = CURL_YES; + tn->usq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_YES; + if(tn->subnegotiation[option] == CURL_YES) { + /* transmission of data option */ + sendsuboption(conn, option); + } + break; + case CURL_OPPOSITE: + tn->us[option] = CURL_WANTNO; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_WONT, option); + break; + } + break; + } +} + +static +void rec_dont(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->us[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->us[option] = CURL_NO; + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_NO; + break; + + case CURL_OPPOSITE: + tn->us[option] = CURL_WANTYES; + tn->usq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_WILL, option); + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_NO; + break; + case CURL_OPPOSITE: + tn->us[option] = CURL_NO; + tn->usq[option] = CURL_EMPTY; + break; + } + break; + } +} + + +static void printsub(struct SessionHandle *data, + int direction, /* '<' or '>' */ + unsigned char *pointer, /* where suboption data is */ + size_t length) /* length of suboption data */ +{ + unsigned int i = 0; + + if(data->set.verbose) { + if(direction) { + infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT"); + if(length >= 3) { + int j; + + i = pointer[length-2]; + j = pointer[length-1]; + + if(i != CURL_IAC || j != CURL_SE) { + infof(data, "(terminated by "); + if(CURL_TELOPT_OK(i)) + infof(data, "%s ", CURL_TELOPT(i)); + else if(CURL_TELCMD_OK(i)) + infof(data, "%s ", CURL_TELCMD(i)); + else + infof(data, "%u ", i); + if(CURL_TELOPT_OK(j)) + infof(data, "%s", CURL_TELOPT(j)); + else if(CURL_TELCMD_OK(j)) + infof(data, "%s", CURL_TELCMD(j)); + else + infof(data, "%d", j); + infof(data, ", not IAC SE!) "); + } + } + length -= 2; + } + if(length < 1) { + infof(data, "(Empty suboption?)"); + return; + } + + if(CURL_TELOPT_OK(pointer[0])) { + switch(pointer[0]) { + case CURL_TELOPT_TTYPE: + case CURL_TELOPT_XDISPLOC: + case CURL_TELOPT_NEW_ENVIRON: + case CURL_TELOPT_NAWS: + infof(data, "%s", CURL_TELOPT(pointer[0])); + break; + default: + infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0])); + break; + } + } + else + infof(data, "%d (unknown)", pointer[i]); + + switch(pointer[0]) { + case CURL_TELOPT_NAWS: + if(length > 4) + infof(data, "Width: %hu ; Height: %hu", (pointer[1]<<8) | pointer[2], + (pointer[3]<<8) | pointer[4]); + break; + default: + switch(pointer[1]) { + case CURL_TELQUAL_IS: + infof(data, " IS"); + break; + case CURL_TELQUAL_SEND: + infof(data, " SEND"); + break; + case CURL_TELQUAL_INFO: + infof(data, " INFO/REPLY"); + break; + case CURL_TELQUAL_NAME: + infof(data, " NAME"); + break; + } + + switch(pointer[0]) { + case CURL_TELOPT_TTYPE: + case CURL_TELOPT_XDISPLOC: + pointer[length] = 0; + infof(data, " \"%s\"", &pointer[2]); + break; + case CURL_TELOPT_NEW_ENVIRON: + if(pointer[1] == CURL_TELQUAL_IS) { + infof(data, " "); + for(i = 3;i < length;i++) { + switch(pointer[i]) { + case CURL_NEW_ENV_VAR: + infof(data, ", "); + break; + case CURL_NEW_ENV_VALUE: + infof(data, " = "); + break; + default: + infof(data, "%c", pointer[i]); + break; + } + } + } + break; + default: + for(i = 2; i < length; i++) + infof(data, " %.2x", pointer[i]); + break; + } + } + if(direction) + infof(data, "\n"); + } +} + +static CURLcode check_telnet_options(struct connectdata *conn) +{ + struct curl_slist *head; + struct curl_slist *beg; + char option_keyword[128] = ""; + char option_arg[256] = ""; + struct SessionHandle *data = conn->data; + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + CURLcode result = CURLE_OK; + int binary_option; + + /* Add the user name as an environment variable if it + was given on the command line */ + if(conn->bits.user_passwd) { + snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); + beg = curl_slist_append(tn->telnet_vars, option_arg); + if(!beg) { + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + return CURLE_OUT_OF_MEMORY; + } + tn->telnet_vars = beg; + tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; + } + + for(head = data->set.telnet_options; head; head=head->next) { + if(sscanf(head->data, "%127[^= ]%*[ =]%255s", + option_keyword, option_arg) == 2) { + + /* Terminal type */ + if(Curl_raw_equal(option_keyword, "TTYPE")) { + strncpy(tn->subopt_ttype, option_arg, 31); + tn->subopt_ttype[31] = 0; /* String termination */ + tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES; + continue; + } + + /* Display variable */ + if(Curl_raw_equal(option_keyword, "XDISPLOC")) { + strncpy(tn->subopt_xdisploc, option_arg, 127); + tn->subopt_xdisploc[127] = 0; /* String termination */ + tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES; + continue; + } + + /* Environment variable */ + if(Curl_raw_equal(option_keyword, "NEW_ENV")) { + beg = curl_slist_append(tn->telnet_vars, option_arg); + if(!beg) { + result = CURLE_OUT_OF_MEMORY; + break; + } + tn->telnet_vars = beg; + tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; + continue; + } + + /* Window Size */ + if(Curl_raw_equal(option_keyword, "WS")) { + if(sscanf(option_arg, "%hu%*[xX]%hu", + &tn->subopt_wsx, &tn->subopt_wsy) == 2) + tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES; + else { + failf(data, "Syntax error in telnet option: %s", head->data); + result = CURLE_TELNET_OPTION_SYNTAX; + break; + } + continue; + } + + /* To take care or not of the 8th bit in data exchange */ + if(Curl_raw_equal(option_keyword, "BINARY")) { + binary_option=atoi(option_arg); + if(binary_option!=1) { + tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO; + tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO; + } + continue; + } + + failf(data, "Unknown telnet option %s", head->data); + result = CURLE_UNKNOWN_TELNET_OPTION; + break; + } + else { + failf(data, "Syntax error in telnet option: %s", head->data); + result = CURLE_TELNET_OPTION_SYNTAX; + break; + } + } + + if(result) { + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + } + + return result; +} + +/* + * suboption() + * + * Look at the sub-option buffer, and try to be helpful to the other + * side. + */ + +static void suboption(struct connectdata *conn) +{ + struct curl_slist *v; + unsigned char temp[2048]; + ssize_t bytes_written; + size_t len; + size_t tmplen; + int err; + char varname[128] = ""; + char varval[128] = ""; + struct SessionHandle *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + + printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2); + switch (CURL_SB_GET(tn)) { + case CURL_TELOPT_TTYPE: + len = strlen(tn->subopt_ttype) + 4 + 2; + snprintf((char *)temp, sizeof(temp), + "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE, + CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE); + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + case CURL_TELOPT_XDISPLOC: + len = strlen(tn->subopt_xdisploc) + 4 + 2; + snprintf((char *)temp, sizeof(temp), + "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC, + CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE); + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + case CURL_TELOPT_NEW_ENVIRON: + snprintf((char *)temp, sizeof(temp), + "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON, + CURL_TELQUAL_IS); + len = 4; + + for(v = tn->telnet_vars;v;v = v->next) { + tmplen = (strlen(v->data) + 1); + /* Add the variable only if it fits */ + if(len + tmplen < (int)sizeof(temp)-6) { + if(sscanf(v->data, "%127[^,],%127s", varname, varval)) { + snprintf((char *)&temp[len], sizeof(temp) - len, + "%c%s%c%s", CURL_NEW_ENV_VAR, varname, + CURL_NEW_ENV_VALUE, varval); + len += tmplen; + } + } + } + snprintf((char *)&temp[len], sizeof(temp) - len, + "%c%c", CURL_IAC, CURL_SE); + len += 2; + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + } + return; +} + + +/* + * sendsuboption() + * + * Send suboption information to the server side. + */ + +static void sendsuboption(struct connectdata *conn, int option) +{ + ssize_t bytes_written; + int err; + unsigned short x, y; + unsigned char*uc1, *uc2; + + struct SessionHandle *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + + switch (option) { + case CURL_TELOPT_NAWS: + /* We prepare data to be sent */ + CURL_SB_CLEAR(tn); + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SB); + CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS); + /* We must deal either with litte or big endien processors */ + /* Window size must be sent according to the 'network order' */ + x=htons(tn->subopt_wsx); + y=htons(tn->subopt_wsy); + uc1 = (unsigned char*)&x; + uc2 = (unsigned char*)&y; + CURL_SB_ACCUM(tn, uc1[0]); + CURL_SB_ACCUM(tn, uc1[1]); + CURL_SB_ACCUM(tn, uc2[0]); + CURL_SB_ACCUM(tn, uc2[1]); + + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SE); + CURL_SB_TERM(tn); + /* data suboption is now ready */ + + printsub(data, '>', (unsigned char *)tn->subbuffer+2, + CURL_SB_LEN(tn)-2); + + /* we send the header of the suboption... */ + bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + /* ... then the window size with the send_telnet_data() function + to deal with 0xFF cases ... */ + send_telnet_data(conn, (char *)tn->subbuffer+3, 4); + /* ... and the footer */ + bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer+7, 2); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + break; + } +} + + +static +CURLcode telrcv(struct connectdata *conn, + const unsigned char *inbuf, /* Data received from socket */ + ssize_t count) /* Number of bytes received */ +{ + unsigned char c; + CURLcode result; + int in = 0; + int startwrite=-1; + struct SessionHandle *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + +#define startskipping() \ + if(startwrite >= 0) { \ + result = Curl_client_write(conn, \ + CLIENTWRITE_BODY, \ + (char *)&inbuf[startwrite], \ + in-startwrite); \ + if(result) \ + return result; \ + } \ + startwrite = -1 + +#define writebyte() \ + if(startwrite < 0) \ + startwrite = in + +#define bufferflush() startskipping() + + while(count--) { + c = inbuf[in]; + + switch (tn->telrcv_state) { + case CURL_TS_CR: + tn->telrcv_state = CURL_TS_DATA; + if(c == '\0') { + startskipping(); + break; /* Ignore \0 after CR */ + } + writebyte(); + break; + + case CURL_TS_DATA: + if(c == CURL_IAC) { + tn->telrcv_state = CURL_TS_IAC; + startskipping(); + break; + } + else if(c == '\r') + tn->telrcv_state = CURL_TS_CR; + writebyte(); + break; + + case CURL_TS_IAC: + process_iac: + DEBUGASSERT(startwrite < 0); + switch (c) { + case CURL_WILL: + tn->telrcv_state = CURL_TS_WILL; + break; + case CURL_WONT: + tn->telrcv_state = CURL_TS_WONT; + break; + case CURL_DO: + tn->telrcv_state = CURL_TS_DO; + break; + case CURL_DONT: + tn->telrcv_state = CURL_TS_DONT; + break; + case CURL_SB: + CURL_SB_CLEAR(tn); + tn->telrcv_state = CURL_TS_SB; + break; + case CURL_IAC: + tn->telrcv_state = CURL_TS_DATA; + writebyte(); + break; + case CURL_DM: + case CURL_NOP: + case CURL_GA: + default: + tn->telrcv_state = CURL_TS_DATA; + printoption(data, "RCVD", CURL_IAC, c); + break; + } + break; + + case CURL_TS_WILL: + printoption(data, "RCVD", CURL_WILL, c); + tn->please_negotiate = 1; + rec_will(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_WONT: + printoption(data, "RCVD", CURL_WONT, c); + tn->please_negotiate = 1; + rec_wont(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_DO: + printoption(data, "RCVD", CURL_DO, c); + tn->please_negotiate = 1; + rec_do(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_DONT: + printoption(data, "RCVD", CURL_DONT, c); + tn->please_negotiate = 1; + rec_dont(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_SB: + if(c == CURL_IAC) + tn->telrcv_state = CURL_TS_SE; + else + CURL_SB_ACCUM(tn, c); + break; + + case CURL_TS_SE: + if(c != CURL_SE) { + if(c != CURL_IAC) { + /* + * This is an error. We only expect to get "IAC IAC" or "IAC SE". + * Several things may have happened. An IAC was not doubled, the + * IAC SE was left off, or another option got inserted into the + * suboption are all possibilities. If we assume that the IAC was + * not doubled, and really the IAC SE was left off, we could get + * into an infinate loop here. So, instead, we terminate the + * suboption, and process the partial suboption if we can. + */ + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, c); + tn->subpointer -= 2; + CURL_SB_TERM(tn); + + printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); + suboption(conn); /* handle sub-option */ + tn->telrcv_state = CURL_TS_IAC; + goto process_iac; + } + CURL_SB_ACCUM(tn, c); + tn->telrcv_state = CURL_TS_SB; + } + else + { + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SE); + tn->subpointer -= 2; + CURL_SB_TERM(tn); + suboption(conn); /* handle sub-option */ + tn->telrcv_state = CURL_TS_DATA; + } + break; + } + ++in; + } + bufferflush(); + return CURLE_OK; +} + +/* Escape and send a telnet data block */ +/* TODO: write large chunks of data instead of one byte at a time */ +static CURLcode send_telnet_data(struct connectdata *conn, + char *buffer, ssize_t nread) +{ + unsigned char outbuf[2]; + ssize_t bytes_written, total_written; + int out_count; + CURLcode result = CURLE_OK; + + while(!result && nread--) { + outbuf[0] = *buffer++; + out_count = 1; + if(outbuf[0] == CURL_IAC) + outbuf[out_count++] = CURL_IAC; + + total_written = 0; + do { + /* Make sure socket is writable to avoid EWOULDBLOCK condition */ + struct pollfd pfd[1]; + pfd[0].fd = conn->sock[FIRSTSOCKET]; + pfd[0].events = POLLOUT; + switch (Curl_poll(pfd, 1, -1)) { + case -1: /* error, abort writing */ + case 0: /* timeout (will never happen) */ + result = CURLE_SEND_ERROR; + break; + default: /* write! */ + bytes_written = 0; + result = Curl_write(conn, conn->sock[FIRSTSOCKET], + outbuf+total_written, out_count-total_written, + &bytes_written); + total_written += bytes_written; + break; + } + /* handle partial write */ + } while(!result && total_written < out_count); + } + return result; +} + +static CURLcode telnet_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + (void)status; /* unused */ + (void)premature; /* not used */ + + if(!tn) + return CURLE_OK; + + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + + Curl_safefree(conn->data->req.protop); + + return CURLE_OK; +} + +static CURLcode telnet_do(struct connectdata *conn, bool *done) +{ + CURLcode result; + struct SessionHandle *data = conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; +#ifdef USE_WINSOCK + HMODULE wsock2; + WSOCK2_FUNC close_event_func; + WSOCK2_FUNC create_event_func; + WSOCK2_FUNC event_select_func; + WSOCK2_FUNC enum_netevents_func; + WSAEVENT event_handle; + WSANETWORKEVENTS events; + HANDLE stdin_handle; + HANDLE objs[2]; + DWORD obj_count; + DWORD wait_timeout; + DWORD waitret; + DWORD readfile_read; + int err; +#else + int interval_ms; + struct pollfd pfd[2]; + int poll_cnt; + curl_off_t total_dl = 0; + curl_off_t total_ul = 0; +#endif + ssize_t nread; + struct timeval now; + bool keepon = TRUE; + char *buf = data->state.buffer; + struct TELNET *tn; + + *done = TRUE; /* unconditionally */ + + result = init_telnet(conn); + if(result) + return result; + + tn = (struct TELNET *)data->req.protop; + + result = check_telnet_options(conn); + if(result) + return result; + +#ifdef USE_WINSOCK + /* + ** This functionality only works with WinSock >= 2.0. So, + ** make sure have it. + */ + result = check_wsock2(data); + if(result) + return result; + + /* OK, so we have WinSock 2.0. We need to dynamically */ + /* load ws2_32.dll and get the function pointers we need. */ + wsock2 = LoadLibrary(TEXT("WS2_32.DLL")); + if(wsock2 == NULL) { + failf(data, "failed to load WS2_32.DLL (%d)", ERRNO); + return CURLE_FAILED_INIT; + } + + /* Grab a pointer to WSACreateEvent */ + create_event_func = GetProcAddress(wsock2, "WSACreateEvent"); + if(create_event_func == NULL) { + failf(data, "failed to find WSACreateEvent function (%d)", ERRNO); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSACloseEvent */ + close_event_func = GetProcAddress(wsock2, "WSACloseEvent"); + if(close_event_func == NULL) { + failf(data, "failed to find WSACloseEvent function (%d)", ERRNO); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSAEventSelect */ + event_select_func = GetProcAddress(wsock2, "WSAEventSelect"); + if(event_select_func == NULL) { + failf(data, "failed to find WSAEventSelect function (%d)", ERRNO); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSAEnumNetworkEvents */ + enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents"); + if(enum_netevents_func == NULL) { + failf(data, "failed to find WSAEnumNetworkEvents function (%d)", ERRNO); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* We want to wait for both stdin and the socket. Since + ** the select() function in winsock only works on sockets + ** we have to use the WaitForMultipleObjects() call. + */ + + /* First, create a sockets event object */ + event_handle = (WSAEVENT)create_event_func(); + if(event_handle == WSA_INVALID_EVENT) { + failf(data, "WSACreateEvent failed (%d)", SOCKERRNO); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* Tell winsock what events we want to listen to */ + if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == + SOCKET_ERROR) { + close_event_func(event_handle); + FreeLibrary(wsock2); + return CURLE_OK; + } + + /* The get the Windows file handle for stdin */ + stdin_handle = GetStdHandle(STD_INPUT_HANDLE); + + /* Create the list of objects to wait for */ + objs[0] = event_handle; + objs[1] = stdin_handle; + + /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, + else use the old WaitForMultipleObjects() way */ + if(GetFileType(stdin_handle) == FILE_TYPE_PIPE || + data->set.is_fread_set) { + /* Don't wait for stdin_handle, just wait for event_handle */ + obj_count = 1; + /* Check stdin_handle per 100 milliseconds */ + wait_timeout = 100; + } + else { + obj_count = 2; + wait_timeout = 1000; + } + + /* Keep on listening and act on events */ + while(keepon) { + waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout); + switch(waitret) { + case WAIT_TIMEOUT: + { + for(;;) { + if(data->set.is_fread_set) { + /* read from user-supplied method */ + result = (int) conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in); + if(result == CURL_READFUNC_ABORT) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + if(result == CURL_READFUNC_PAUSE) + break; + + if(result == 0) /* no bytes */ + break; + + readfile_read = result; /* fall thru with number of bytes read */ + } + else { + /* read from stdin */ + if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + if(!readfile_read) + break; + + if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + } + + result = send_telnet_data(conn, buf, readfile_read); + if(result) { + keepon = FALSE; + break; + } + } + } + break; + + case WAIT_OBJECT_0 + 1: + { + if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + result = send_telnet_data(conn, buf, readfile_read); + if(result) { + keepon = FALSE; + break; + } + } + break; + + case WAIT_OBJECT_0: + + events.lNetworkEvents = 0; + if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { + if((err = SOCKERRNO) != EINPROGRESS) { + infof(data, "WSAEnumNetworkEvents failed (%d)", err); + keepon = FALSE; + result = CURLE_READ_ERROR; + } + break; + } + if(events.lNetworkEvents & FD_READ) { + /* read data from network */ + result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); + /* read would've blocked. Loop again */ + if(result == CURLE_AGAIN) + break; + /* returned not-zero, this an error */ + else if(result) { + keepon = FALSE; + break; + } + /* returned zero but actually received 0 or less here, + the server closed the connection and we bail out */ + else if(nread <= 0) { + keepon = FALSE; + break; + } + + result = telrcv(conn, (unsigned char *) buf, nread); + if(result) { + keepon = FALSE; + break; + } + + /* Negotiate if the peer has started negotiating, + otherwise don't. We don't want to speak telnet with + non-telnet servers, like POP or SMTP. */ + if(tn->please_negotiate && !tn->already_negotiated) { + negotiate(conn); + tn->already_negotiated = 1; + } + } + if(events.lNetworkEvents & FD_CLOSE) { + keepon = FALSE; + } + break; + + } + + if(data->set.timeout) { + now = Curl_tvnow(); + if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { + failf(data, "Time-out"); + result = CURLE_OPERATION_TIMEDOUT; + keepon = FALSE; + } + } + } + + /* We called WSACreateEvent, so call WSACloseEvent */ + if(!close_event_func(event_handle)) { + infof(data, "WSACloseEvent failed (%d)", SOCKERRNO); + } + + /* "Forget" pointers into the library we're about to free */ + create_event_func = NULL; + close_event_func = NULL; + event_select_func = NULL; + enum_netevents_func = NULL; + + /* We called LoadLibrary, so call FreeLibrary */ + if(!FreeLibrary(wsock2)) + infof(data, "FreeLibrary(wsock2) failed (%d)", ERRNO); +#else + pfd[0].fd = sockfd; + pfd[0].events = POLLIN; + + if(conn->fread_func != (curl_read_callback)fread) { + poll_cnt = 1; + interval_ms = 100; /* poll user-supplied read function */ + } + else { + /* really using fread, so infile is a FILE* */ + pfd[1].fd = fileno((FILE *)conn->fread_in); + pfd[1].events = POLLIN; + poll_cnt = 2; + interval_ms = 1 * 1000; + } + + while(keepon) { + switch (Curl_poll(pfd, poll_cnt, interval_ms)) { + case -1: /* error, stop reading */ + keepon = FALSE; + continue; + case 0: /* timeout */ + pfd[0].revents = 0; + pfd[1].revents = 0; + /* fall through */ + default: /* read! */ + if(pfd[0].revents & POLLIN) { + /* read data from network */ + result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); + /* read would've blocked. Loop again */ + if(result == CURLE_AGAIN) + break; + /* returned not-zero, this an error */ + else if(result) { + keepon = FALSE; + break; + } + /* returned zero but actually received 0 or less here, + the server closed the connection and we bail out */ + else if(nread <= 0) { + keepon = FALSE; + break; + } + + total_dl += nread; + Curl_pgrsSetDownloadCounter(data, total_dl); + result = telrcv(conn, (unsigned char *)buf, nread); + if(result) { + keepon = FALSE; + break; + } + + /* Negotiate if the peer has started negotiating, + otherwise don't. We don't want to speak telnet with + non-telnet servers, like POP or SMTP. */ + if(tn->please_negotiate && !tn->already_negotiated) { + negotiate(conn); + tn->already_negotiated = 1; + } + } + + nread = 0; + if(poll_cnt == 2) { + if(pfd[1].revents & POLLIN) { /* read from in file */ + nread = read(pfd[1].fd, buf, BUFSIZE - 1); + } + } + else { + /* read from user-supplied method */ + nread = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in); + if(nread == CURL_READFUNC_ABORT) { + keepon = FALSE; + break; + } + if(nread == CURL_READFUNC_PAUSE) + break; + } + + if(nread > 0) { + result = send_telnet_data(conn, buf, nread); + if(result) { + keepon = FALSE; + break; + } + total_ul += nread; + Curl_pgrsSetUploadCounter(data, total_ul); + } + else if(nread < 0) + keepon = FALSE; + + break; + } /* poll switch statement */ + + if(data->set.timeout) { + now = Curl_tvnow(); + if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { + failf(data, "Time-out"); + result = CURLE_OPERATION_TIMEDOUT; + keepon = FALSE; + } + } + + if(Curl_pgrsUpdate(conn)) { + result = CURLE_ABORTED_BY_CALLBACK; + break; + } + } +#endif + /* mark this as "no further transfer wanted" */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + + return result; +} +#endif diff --git a/libcurl/src/lib/telnet.h b/libcurl/src/lib/telnet.h new file mode 100644 index 0000000..ddb9e54 --- /dev/null +++ b/libcurl/src/lib/telnet.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_TELNET_H +#define HEADER_CURL_TELNET_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET +extern const struct Curl_handler Curl_handler_telnet; +#endif + +#endif /* HEADER_CURL_TELNET_H */ + diff --git a/libcurl/src/lib/tftp.c b/libcurl/src/lib/tftp.c new file mode 100644 index 0000000..4c5796f --- /dev/null +++ b/libcurl/src/lib/tftp.c @@ -0,0 +1,1376 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_TFTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "tftp.h" +#include "progress.h" +#include "connect.h" +#include "strerror.h" +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "multiif.h" +#include "url.h" +#include "rawstr.h" +#include "speedcheck.h" +#include "curl_printf.h" +#include "select.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* RFC2348 allows the block size to be negotiated */ +#define TFTP_BLKSIZE_DEFAULT 512 +#define TFTP_BLKSIZE_MIN 8 +#define TFTP_BLKSIZE_MAX 65464 +#define TFTP_OPTION_BLKSIZE "blksize" + +/* from RFC2349: */ +#define TFTP_OPTION_TSIZE "tsize" +#define TFTP_OPTION_INTERVAL "timeout" + +typedef enum { + TFTP_MODE_NETASCII=0, + TFTP_MODE_OCTET +} tftp_mode_t; + +typedef enum { + TFTP_STATE_START=0, + TFTP_STATE_RX, + TFTP_STATE_TX, + TFTP_STATE_FIN +} tftp_state_t; + +typedef enum { + TFTP_EVENT_NONE = -1, + TFTP_EVENT_INIT = 0, + TFTP_EVENT_RRQ = 1, + TFTP_EVENT_WRQ = 2, + TFTP_EVENT_DATA = 3, + TFTP_EVENT_ACK = 4, + TFTP_EVENT_ERROR = 5, + TFTP_EVENT_OACK = 6, + TFTP_EVENT_TIMEOUT +} tftp_event_t; + +typedef enum { + TFTP_ERR_UNDEF=0, + TFTP_ERR_NOTFOUND, + TFTP_ERR_PERM, + TFTP_ERR_DISKFULL, + TFTP_ERR_ILLEGAL, + TFTP_ERR_UNKNOWNID, + TFTP_ERR_EXISTS, + TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */ + + /* The remaining error codes are internal to curl */ + TFTP_ERR_NONE = -100, + TFTP_ERR_TIMEOUT, + TFTP_ERR_NORESPONSE +} tftp_error_t; + +typedef struct tftp_packet { + unsigned char *data; +} tftp_packet_t; + +typedef struct tftp_state_data { + tftp_state_t state; + tftp_mode_t mode; + tftp_error_t error; + tftp_event_t event; + struct connectdata *conn; + curl_socket_t sockfd; + int retries; + int retry_time; + int retry_max; + time_t start_time; + time_t max_time; + time_t rx_time; + unsigned short block; + struct Curl_sockaddr_storage local_addr; + struct Curl_sockaddr_storage remote_addr; + curl_socklen_t remote_addrlen; + int rbytes; + int sbytes; + int blksize; + int requested_blksize; + tftp_packet_t rpacket; + tftp_packet_t spacket; +} tftp_state_data_t; + + +/* Forward declarations */ +static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event); +static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event); +static CURLcode tftp_connect(struct connectdata *conn, bool *done); +static CURLcode tftp_disconnect(struct connectdata *conn, + bool dead_connection); +static CURLcode tftp_do(struct connectdata *conn, bool *done); +static CURLcode tftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode tftp_setup_connection(struct connectdata * conn); +static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done); +static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done); +static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode tftp_translate_code(tftp_error_t error); + + +/* + * TFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_tftp = { + "TFTP", /* scheme */ + tftp_setup_connection, /* setup_connection */ + tftp_do, /* do_it */ + tftp_done, /* done */ + ZERO_NULL, /* do_more */ + tftp_connect, /* connect_it */ + tftp_multi_statemach, /* connecting */ + tftp_doing, /* doing */ + tftp_getsock, /* proto_getsock */ + tftp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + tftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_TFTP, /* defport */ + CURLPROTO_TFTP, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + +/********************************************************** + * + * tftp_set_timeouts - + * + * Set timeouts based on state machine state. + * Use user provided connect timeouts until DATA or ACK + * packet is received, then use user-provided transfer timeouts + * + * + **********************************************************/ +static CURLcode tftp_set_timeouts(tftp_state_data_t *state) +{ + time_t maxtime, timeout; + long timeout_ms; + bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; + + time(&state->start_time); + + /* Compute drop-dead time */ + timeout_ms = Curl_timeleft(state->conn->data, NULL, start); + + if(timeout_ms < 0) { + /* time-out, bail out, go home */ + failf(state->conn->data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(start) { + + maxtime = (time_t)(timeout_ms + 500) / 1000; + state->max_time = state->start_time+maxtime; + + /* Set per-block timeout to total */ + timeout = maxtime; + + /* Average restart after 5 seconds */ + state->retry_max = (int)timeout/5; + + if(state->retry_max < 1) + /* avoid division by zero below */ + state->retry_max = 1; + + /* Compute the re-start interval to suit the timeout */ + state->retry_time = (int)timeout/state->retry_max; + if(state->retry_time<1) + state->retry_time=1; + + } + else { + if(timeout_ms > 0) + maxtime = (time_t)(timeout_ms + 500) / 1000; + else + maxtime = 3600; + + state->max_time = state->start_time+maxtime; + + /* Set per-block timeout to total */ + timeout = maxtime; + + /* Average reposting an ACK after 5 seconds */ + state->retry_max = (int)timeout/5; + } + /* But bound the total number */ + if(state->retry_max<3) + state->retry_max=3; + + if(state->retry_max>50) + state->retry_max=50; + + /* Compute the re-ACK interval to suit the timeout */ + state->retry_time = (int)(timeout/state->retry_max); + if(state->retry_time<1) + state->retry_time=1; + + infof(state->conn->data, + "set timeouts for state %d; Total %ld, retry %d maxtry %d\n", + (int)state->state, (long)(state->max_time-state->start_time), + state->retry_time, state->retry_max); + + /* init RX time */ + time(&state->rx_time); + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_set_send_first + * + * Event handler for the START state + * + **********************************************************/ + +static void setpacketevent(tftp_packet_t *packet, unsigned short num) +{ + packet->data[0] = (unsigned char)(num >> 8); + packet->data[1] = (unsigned char)(num & 0xff); +} + + +static void setpacketblock(tftp_packet_t *packet, unsigned short num) +{ + packet->data[2] = (unsigned char)(num >> 8); + packet->data[3] = (unsigned char)(num & 0xff); +} + +static unsigned short getrpacketevent(const tftp_packet_t *packet) +{ + return (unsigned short)((packet->data[0] << 8) | packet->data[1]); +} + +static unsigned short getrpacketblock(const tftp_packet_t *packet) +{ + return (unsigned short)((packet->data[2] << 8) | packet->data[3]); +} + +static size_t Curl_strnlen(const char *string, size_t maxlen) +{ + const char *end = memchr (string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} + +static const char *tftp_option_get(const char *buf, size_t len, + const char **option, const char **value) +{ + size_t loc; + + loc = Curl_strnlen( buf, len ); + loc++; /* NULL term */ + + if(loc >= len) + return NULL; + *option = buf; + + loc += Curl_strnlen( buf+loc, len-loc ); + loc++; /* NULL term */ + + if(loc > len) + return NULL; + *value = &buf[strlen(*option) + 1]; + + return &buf[loc]; +} + +static CURLcode tftp_parse_option_ack(tftp_state_data_t *state, + const char *ptr, int len) +{ + const char *tmp = ptr; + struct SessionHandle *data = state->conn->data; + + /* if OACK doesn't contain blksize option, the default (512) must be used */ + state->blksize = TFTP_BLKSIZE_DEFAULT; + + while(tmp < ptr + len) { + const char *option, *value; + + tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); + if(tmp == NULL) { + failf(data, "Malformed ACK packet, rejecting"); + return CURLE_TFTP_ILLEGAL; + } + + infof(data, "got option=(%s) value=(%s)\n", option, value); + + if(checkprefix(option, TFTP_OPTION_BLKSIZE)) { + long blksize; + + blksize = strtol( value, NULL, 10 ); + + if(!blksize) { + failf(data, "invalid blocksize value in OACK packet"); + return CURLE_TFTP_ILLEGAL; + } + else if(blksize > TFTP_BLKSIZE_MAX) { + failf(data, "%s (%d)", "blksize is larger than max supported", + TFTP_BLKSIZE_MAX); + return CURLE_TFTP_ILLEGAL; + } + else if(blksize < TFTP_BLKSIZE_MIN) { + failf(data, "%s (%d)", "blksize is smaller than min supported", + TFTP_BLKSIZE_MIN); + return CURLE_TFTP_ILLEGAL; + } + else if(blksize > state->requested_blksize) { + /* could realloc pkt buffers here, but the spec doesn't call out + * support for the server requesting a bigger blksize than the client + * requests */ + failf(data, "%s (%ld)", + "server requested blksize larger than allocated", blksize); + return CURLE_TFTP_ILLEGAL; + } + + state->blksize = (int)blksize; + infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK", + state->blksize, "requested", state->requested_blksize); + } + else if(checkprefix(option, TFTP_OPTION_TSIZE)) { + long tsize = 0; + + tsize = strtol( value, NULL, 10 ); + infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize); + + /* tsize should be ignored on upload: Who cares about the size of the + remote file? */ + if(!data->set.upload) { + if(!tsize) { + failf(data, "invalid tsize -:%s:- value in OACK packet", value); + return CURLE_TFTP_ILLEGAL; + } + Curl_pgrsSetDownloadSize(data, tsize); + } + } + } + + return CURLE_OK; +} + +static size_t tftp_option_add(tftp_state_data_t *state, size_t csize, + char *buf, const char *option) +{ + if(( strlen(option) + csize + 1 ) > (size_t)state->blksize) + return 0; + strcpy(buf, option); + return strlen(option) + 1; +} + +static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + struct SessionHandle *data = state->conn->data; + + infof(data, "%s\n", "Connected for transmit"); +#endif + state->state = TFTP_STATE_TX; + result = tftp_set_timeouts(state); + if(result) + return result; + return tftp_tx(state, event); +} + +static CURLcode tftp_connect_for_rx(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + struct SessionHandle *data = state->conn->data; + + infof(data, "%s\n", "Connected for receive"); +#endif + state->state = TFTP_STATE_RX; + result = tftp_set_timeouts(state); + if(result) + return result; + return tftp_rx(state, event); +} + +static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) +{ + size_t sbytes; + ssize_t senddata; + const char *mode = "octet"; + char *filename; + char buf[64]; + struct SessionHandle *data = state->conn->data; + CURLcode result = CURLE_OK; + + /* Set ascii mode if -B flag was used */ + if(data->set.prefer_ascii) + mode = "netascii"; + + switch(event) { + + case TFTP_EVENT_INIT: /* Send the first packet out */ + case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */ + /* Increment the retry counter, quit if over the limit */ + state->retries++; + if(state->retries>state->retry_max) { + state->error = TFTP_ERR_NORESPONSE; + state->state = TFTP_STATE_FIN; + return result; + } + + if(data->set.upload) { + /* If we are uploading, send an WRQ */ + setpacketevent(&state->spacket, TFTP_EVENT_WRQ); + state->conn->data->req.upload_fromhere = + (char *)state->spacket.data+4; + if(data->state.infilesize != -1) + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + else { + /* If we are downloading, send an RRQ */ + setpacketevent(&state->spacket, TFTP_EVENT_RRQ); + } + /* As RFC3617 describes the separator slash is not actually part of the + file name so we skip the always-present first letter of the path + string. */ + filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0, + NULL); + if(!filename) + return CURLE_OUT_OF_MEMORY; + + snprintf((char *)state->spacket.data+2, + state->blksize, + "%s%c%s%c", filename, '\0', mode, '\0'); + sbytes = 4 + strlen(filename) + strlen(mode); + + /* add tsize option */ + if(data->set.upload && (data->state.infilesize != -1)) + snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, + data->state.infilesize); + else + strcpy(buf, "0"); /* the destination is large enough */ + + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data+sbytes, + TFTP_OPTION_TSIZE); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data+sbytes, buf); + /* add blksize option */ + snprintf( buf, sizeof(buf), "%d", state->requested_blksize ); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data+sbytes, + TFTP_OPTION_BLKSIZE); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data+sbytes, buf ); + + /* add timeout option */ + snprintf( buf, sizeof(buf), "%d", state->retry_time); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data+sbytes, + TFTP_OPTION_INTERVAL); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data+sbytes, buf ); + + /* the typecase for the 3rd argument is mostly for systems that do + not have a size_t argument, like older unixes that want an 'int' */ + senddata = sendto(state->sockfd, (void *)state->spacket.data, + (SEND_TYPE_ARG3)sbytes, 0, + state->conn->ip_addr->ai_addr, + state->conn->ip_addr->ai_addrlen); + if(senddata != (ssize_t)sbytes) { + failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + } + free(filename); + break; + + case TFTP_EVENT_OACK: + if(data->set.upload) { + result = tftp_connect_for_tx(state, event); + } + else { + result = tftp_connect_for_rx(state, event); + } + break; + + case TFTP_EVENT_ACK: /* Connected for transmit */ + result = tftp_connect_for_tx(state, event); + break; + + case TFTP_EVENT_DATA: /* Connected for receive */ + result = tftp_connect_for_rx(state, event); + break; + + case TFTP_EVENT_ERROR: + state->state = TFTP_STATE_FIN; + break; + + default: + failf(state->conn->data, "tftp_send_first: internal error"); + break; + } + + return result; +} + +/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit + boundary */ +#define NEXT_BLOCKNUM(x) (((x)+1)&0xffff) + +/********************************************************** + * + * tftp_rx + * + * Event handler for the RX state + * + **********************************************************/ +static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) +{ + ssize_t sbytes; + int rblock; + struct SessionHandle *data = state->conn->data; + + switch(event) { + + case TFTP_EVENT_DATA: + /* Is this the block we expect? */ + rblock = getrpacketblock(&state->rpacket); + if(NEXT_BLOCKNUM(state->block) == rblock) { + /* This is the expected block. Reset counters and ACK it. */ + state->retries = 0; + } + else if(state->block == rblock) { + /* This is the last recently received block again. Log it and ACK it + again. */ + infof(data, "Received last DATA packet block %d again.\n", rblock); + } + else { + /* totally unexpected, just log it */ + infof(data, + "Received unexpected DATA packet block %d, expecting block %d\n", + rblock, NEXT_BLOCKNUM(state->block)); + break; + } + + /* ACK this block. */ + state->block = (unsigned short)rblock; + setpacketevent(&state->spacket, TFTP_EVENT_ACK); + setpacketblock(&state->spacket, state->block); + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes < 0) { + failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + return CURLE_SEND_ERROR; + } + + /* Check if completed (That is, a less than full packet is received) */ + if(state->rbytes < (ssize_t)state->blksize+4) { + state->state = TFTP_STATE_FIN; + } + else { + state->state = TFTP_STATE_RX; + } + time(&state->rx_time); + break; + + case TFTP_EVENT_OACK: + /* ACK option acknowledgement so we can move on to data */ + state->block = 0; + state->retries = 0; + setpacketevent(&state->spacket, TFTP_EVENT_ACK); + setpacketblock(&state->spacket, state->block); + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes < 0) { + failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + return CURLE_SEND_ERROR; + } + + /* we're ready to RX data */ + state->state = TFTP_STATE_RX; + time(&state->rx_time); + break; + + case TFTP_EVENT_TIMEOUT: + /* Increment the retry count and fail if over the limit */ + state->retries++; + infof(data, + "Timeout waiting for block %d ACK. Retries = %d\n", + NEXT_BLOCKNUM(state->block), state->retries); + if(state->retries > state->retry_max) { + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + } + else { + /* Resend the previous ACK */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes<0) { + failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + return CURLE_SEND_ERROR; + } + } + break; + + case TFTP_EVENT_ERROR: + setpacketevent(&state->spacket, TFTP_EVENT_ERROR); + setpacketblock(&state->spacket, state->block); + (void)sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* don't bother with the return code, but if the socket is still up we + * should be a good TFTP client and let the server know we're done */ + state->state = TFTP_STATE_FIN; + break; + + default: + failf(data, "%s", "tftp_rx: internal error"); + return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for + this */ + } + return CURLE_OK; +} + +/********************************************************** + * + * tftp_tx + * + * Event handler for the TX state + * + **********************************************************/ +static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) +{ + struct SessionHandle *data = state->conn->data; + ssize_t sbytes; + int rblock; + CURLcode result = CURLE_OK; + struct SingleRequest *k = &data->req; + + switch(event) { + + case TFTP_EVENT_ACK: + case TFTP_EVENT_OACK: + if(event == TFTP_EVENT_ACK) { + /* Ack the packet */ + rblock = getrpacketblock(&state->rpacket); + + if(rblock != state->block && + /* There's a bug in tftpd-hpa that causes it to send us an ack for + * 65535 when the block number wraps to 0. So when we're expecting + * 0, also accept 65535. See + * http://syslinux.zytor.com/archives/2010-September/015253.html + * */ + !(state->block == 0 && rblock == 65535)) { + /* This isn't the expected block. Log it and up the retry counter */ + infof(data, "Received ACK for block %d, expecting %d\n", + rblock, state->block); + state->retries++; + /* Bail out if over the maximum */ + if(state->retries>state->retry_max) { + failf(data, "tftp_tx: giving up waiting for block %d ack", + state->block); + result = CURLE_SEND_ERROR; + } + else { + /* Re-send the data packet */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4+state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + result = CURLE_SEND_ERROR; + } + } + + return result; + } + /* This is the expected packet. Reset the counters and send the next + block */ + time(&state->rx_time); + state->block++; + } + else + state->block = 1; /* first data block is 1 when using OACK */ + + state->retries = 0; + setpacketevent(&state->spacket, TFTP_EVENT_DATA); + setpacketblock(&state->spacket, state->block); + if(state->block > 1 && state->sbytes < (int)state->blksize) { + state->state = TFTP_STATE_FIN; + return CURLE_OK; + } + + result = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes); + if(result) + return result; + + sbytes = sendto(state->sockfd, (void *) state->spacket.data, + 4 + state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + return CURLE_SEND_ERROR; + } + /* Update the progress meter */ + k->writebytecount += state->sbytes; + Curl_pgrsSetUploadCounter(data, k->writebytecount); + break; + + case TFTP_EVENT_TIMEOUT: + /* Increment the retry counter and log the timeout */ + state->retries++; + infof(data, "Timeout waiting for block %d ACK. " + " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries); + /* Decide if we've had enough */ + if(state->retries > state->retry_max) { + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + } + else { + /* Re-send the data packet */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4+state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + return CURLE_SEND_ERROR; + } + /* since this was a re-send, we remain at the still byte position */ + Curl_pgrsSetUploadCounter(data, k->writebytecount); + } + break; + + case TFTP_EVENT_ERROR: + state->state = TFTP_STATE_FIN; + setpacketevent(&state->spacket, TFTP_EVENT_ERROR); + setpacketblock(&state->spacket, state->block); + (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* don't bother with the return code, but if the socket is still up we + * should be a good TFTP client and let the server know we're done */ + state->state = TFTP_STATE_FIN; + break; + + default: + failf(data, "tftp_tx: internal error, event: %i", (int)(event)); + break; + } + + return result; +} + +/********************************************************** + * + * tftp_translate_code + * + * Translate internal error codes to CURL error codes + * + **********************************************************/ +static CURLcode tftp_translate_code(tftp_error_t error) +{ + CURLcode result = CURLE_OK; + + if(error != TFTP_ERR_NONE) { + switch(error) { + case TFTP_ERR_NOTFOUND: + result = CURLE_TFTP_NOTFOUND; + break; + case TFTP_ERR_PERM: + result = CURLE_TFTP_PERM; + break; + case TFTP_ERR_DISKFULL: + result = CURLE_REMOTE_DISK_FULL; + break; + case TFTP_ERR_UNDEF: + case TFTP_ERR_ILLEGAL: + result = CURLE_TFTP_ILLEGAL; + break; + case TFTP_ERR_UNKNOWNID: + result = CURLE_TFTP_UNKNOWNID; + break; + case TFTP_ERR_EXISTS: + result = CURLE_REMOTE_FILE_EXISTS; + break; + case TFTP_ERR_NOSUCHUSER: + result = CURLE_TFTP_NOSUCHUSER; + break; + case TFTP_ERR_TIMEOUT: + result = CURLE_OPERATION_TIMEDOUT; + break; + case TFTP_ERR_NORESPONSE: + result = CURLE_COULDNT_CONNECT; + break; + default: + result = CURLE_ABORTED_BY_CALLBACK; + break; + } + } + else + result = CURLE_OK; + + return result; +} + +/********************************************************** + * + * tftp_state_machine + * + * The tftp state machine event dispatcher + * + **********************************************************/ +static CURLcode tftp_state_machine(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = state->conn->data; + + switch(state->state) { + case TFTP_STATE_START: + DEBUGF(infof(data, "TFTP_STATE_START\n")); + result = tftp_send_first(state, event); + break; + case TFTP_STATE_RX: + DEBUGF(infof(data, "TFTP_STATE_RX\n")); + result = tftp_rx(state, event); + break; + case TFTP_STATE_TX: + DEBUGF(infof(data, "TFTP_STATE_TX\n")); + result = tftp_tx(state, event); + break; + case TFTP_STATE_FIN: + infof(data, "%s\n", "TFTP finished"); + break; + default: + DEBUGF(infof(data, "STATE: %d\n", state->state)); + failf(data, "%s", "Internal state machine error"); + result = CURLE_TFTP_ILLEGAL; + break; + } + + return result; +} + +/********************************************************** + * + * tftp_disconnect + * + * The disconnect callback + * + **********************************************************/ +static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + tftp_state_data_t *state = conn->proto.tftpc; + (void) dead_connection; + + /* done, free dynamically allocated pkt buffers */ + if(state) { + Curl_safefree(state->rpacket.data); + Curl_safefree(state->spacket.data); + free(state); + } + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_connect + * + * The connect callback + * + **********************************************************/ +static CURLcode tftp_connect(struct connectdata *conn, bool *done) +{ + tftp_state_data_t *state; + int blksize, rc; + + blksize = TFTP_BLKSIZE_DEFAULT; + + state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t)); + if(!state) + return CURLE_OUT_OF_MEMORY; + + /* alloc pkt buffers based on specified blksize */ + if(conn->data->set.tftp_blksize) { + blksize = (int)conn->data->set.tftp_blksize; + if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN ) + return CURLE_TFTP_ILLEGAL; + } + + if(!state->rpacket.data) { + state->rpacket.data = calloc(1, blksize + 2 + 2); + + if(!state->rpacket.data) + return CURLE_OUT_OF_MEMORY; + } + + if(!state->spacket.data) { + state->spacket.data = calloc(1, blksize + 2 + 2); + + if(!state->spacket.data) + return CURLE_OUT_OF_MEMORY; + } + + /* we don't keep TFTP connections up bascially because there's none or very + * little gain for UDP */ + connclose(conn, "TFTP"); + + state->conn = conn; + state->sockfd = state->conn->sock[FIRSTSOCKET]; + state->state = TFTP_STATE_START; + state->error = TFTP_ERR_NONE; + state->blksize = TFTP_BLKSIZE_DEFAULT; + state->requested_blksize = blksize; + + ((struct sockaddr *)&state->local_addr)->sa_family = + (unsigned short)(conn->ip_addr->ai_family); + + tftp_set_timeouts(state); + + if(!conn->bits.bound) { + /* If not already bound, bind to any interface, random UDP port. If it is + * reused or a custom local port was desired, this has already been done! + * + * We once used the size of the local_addr struct as the third argument + * for bind() to better work with IPv6 or whatever size the struct could + * have, but we learned that at least Tru64, AIX and IRIX *requires* the + * size of that argument to match the exact size of a 'sockaddr_in' struct + * when running IPv4-only. + * + * Therefore we use the size from the address we connected to, which we + * assume uses the same IP version and thus hopefully this works for both + * IPv4 and IPv6... + */ + rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, + conn->ip_addr->ai_addrlen); + if(rc) { + failf(conn->data, "bind() failed; %s", + Curl_strerror(conn, SOCKERRNO)); + return CURLE_COULDNT_CONNECT; + } + conn->bits.bound = TRUE; + } + + Curl_pgrsStartNow(conn->data); + + *done = TRUE; + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_done + * + * The done callback + * + **********************************************************/ +static CURLcode tftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + (void)status; /* unused */ + (void)premature; /* not used */ + + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + /* If we have encountered an error */ + if(state) + result = tftp_translate_code(state->error); + + return result; +} + +/********************************************************** + * + * tftp_getsock + * + * The getsock callback + * + **********************************************************/ +static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + + return GETSOCK_READSOCK(0); +} + +/********************************************************** + * + * tftp_receive_packet + * + * Called once select fires and data is ready on the socket + * + **********************************************************/ +static CURLcode tftp_receive_packet(struct connectdata *conn) +{ + struct Curl_sockaddr_storage fromaddr; + curl_socklen_t fromlen; + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + struct SingleRequest *k = &data->req; + + /* Receive the packet */ + fromlen = sizeof(fromaddr); + state->rbytes = (int)recvfrom(state->sockfd, + (void *)state->rpacket.data, + state->blksize+4, + 0, + (struct sockaddr *)&fromaddr, + &fromlen); + if(state->remote_addrlen==0) { + memcpy(&state->remote_addr, &fromaddr, fromlen); + state->remote_addrlen = fromlen; + } + + /* Sanity check packet length */ + if(state->rbytes < 4) { + failf(data, "Received too short packet"); + /* Not a timeout, but how best to handle it? */ + state->event = TFTP_EVENT_TIMEOUT; + } + else { + /* The event is given by the TFTP packet time */ + state->event = (tftp_event_t)getrpacketevent(&state->rpacket); + + switch(state->event) { + case TFTP_EVENT_DATA: + /* Don't pass to the client empty or retransmitted packets */ + if(state->rbytes > 4 && + (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *)state->rpacket.data+4, + state->rbytes-4); + if(result) { + tftp_state_machine(state, TFTP_EVENT_ERROR); + return result; + } + k->bytecount += state->rbytes-4; + Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount); + } + break; + case TFTP_EVENT_ERROR: + state->error = (tftp_error_t)getrpacketblock(&state->rpacket); + infof(data, "%s\n", (const char *)state->rpacket.data+4); + break; + case TFTP_EVENT_ACK: + break; + case TFTP_EVENT_OACK: + result = tftp_parse_option_ack(state, + (const char *)state->rpacket.data+2, + state->rbytes-2); + if(result) + return result; + break; + case TFTP_EVENT_RRQ: + case TFTP_EVENT_WRQ: + default: + failf(data, "%s", "Internal error: Unexpected packet"); + break; + } + + /* Update the progress meter */ + if(Curl_pgrsUpdate(conn)) { + tftp_state_machine(state, TFTP_EVENT_ERROR); + return CURLE_ABORTED_BY_CALLBACK; + } + } + return result; +} + +/********************************************************** + * + * tftp_state_timeout + * + * Check if timeouts have been reached + * + **********************************************************/ +static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) +{ + time_t current; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + if(event) + *event = TFTP_EVENT_NONE; + + time(¤t); + if(current > state->max_time) { + DEBUGF(infof(conn->data, "timeout: %ld > %ld\n", + (long)current, (long)state->max_time)); + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + return 0; + } + else if(current > state->rx_time+state->retry_time) { + if(event) + *event = TFTP_EVENT_TIMEOUT; + time(&state->rx_time); /* update even though we received nothing */ + } + + /* there's a typecast below here since 'time_t' may in fact be larger than + 'long', but we estimate that a 'long' will still be able to hold number + of seconds even if "only" 32 bit */ + return (long)(state->max_time - current); +} + +/********************************************************** + * + * tftp_multi_statemach + * + * Handle single RX socket event and return + * + **********************************************************/ +static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) +{ + int rc; + tftp_event_t event; + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + long timeout_ms = tftp_state_timeout(conn, &event); + + *done = FALSE; + + if(timeout_ms <= 0) { + failf(data, "TFTP response timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + else if(event != TFTP_EVENT_NONE) { + result = tftp_state_machine(state, event); + if(result) + return result; + *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; + if(*done) + /* Tell curl we're done */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + } + else { + /* no timeouts to handle, check our socket */ + rc = Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, 0); + + if(rc == -1) { + /* bail out */ + int error = SOCKERRNO; + failf(data, "%s", Curl_strerror(conn, error)); + state->event = TFTP_EVENT_ERROR; + } + else if(rc != 0) { + result = tftp_receive_packet(conn); + if(result) + return result; + result = tftp_state_machine(state, state->event); + if(result) + return result; + *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; + if(*done) + /* Tell curl we're done */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + } + /* if rc == 0, then select() timed out */ + } + + return result; +} + +/********************************************************** + * + * tftp_doing + * + * Called from multi.c while DOing + * + **********************************************************/ +static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result; + result = tftp_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + else if(!result) { + /* The multi code doesn't have this logic for the DOING state so we + provide it for TFTP since it may do the entire transfer in this + state. */ + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(conn->data, Curl_tvnow()); + } + return result; +} + +/********************************************************** + * + * tftp_peform + * + * Entry point for transfer from tftp_do, sarts state mach + * + **********************************************************/ +static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = CURLE_OK; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + *dophase_done = FALSE; + + result = tftp_state_machine(state, TFTP_EVENT_INIT); + + if((state->state == TFTP_STATE_FIN) || result) + return result; + + tftp_multi_statemach(conn, dophase_done); + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + + +/********************************************************** + * + * tftp_do + * + * The do callback + * + * This callback initiates the TFTP transfer + * + **********************************************************/ + +static CURLcode tftp_do(struct connectdata *conn, bool *done) +{ + tftp_state_data_t *state; + CURLcode result; + + *done = FALSE; + + if(!conn->proto.tftpc) { + result = tftp_connect(conn, done); + if(result) + return result; + } + + state = (tftp_state_data_t *)conn->proto.tftpc; + if(!state) + return CURLE_BAD_CALLING_ORDER; + + result = tftp_perform(conn, done); + + /* If tftp_perform() returned an error, use that for return code. If it + was OK, see if tftp_translate_code() has an error. */ + if(!result) + /* If we have encountered an internal tftp error, translate it. */ + result = tftp_translate_code(state->error); + + return result; +} + +static CURLcode tftp_setup_connection(struct connectdata * conn) +{ + struct SessionHandle *data = conn->data; + char * type; + char command; + + conn->socktype = SOCK_DGRAM; /* UDP datagram based */ + + /* TFTP URLs support an extension like ";mode=" that + * we'll try to get now! */ + type = strstr(data->state.path, ";mode="); + + if(!type) + type = strstr(conn->host.rawalloc, ";mode="); + + if(type) { + *type = 0; /* it was in the middle of the hostname */ + command = Curl_raw_toupper(type[6]); + + switch (command) { + case 'A': /* ASCII mode */ + case 'N': /* NETASCII mode */ + data->set.prefer_ascii = TRUE; + break; + + case 'O': /* octet mode */ + case 'I': /* binary mode */ + default: + /* switch off ASCII */ + data->set.prefer_ascii = FALSE; + break; + } + } + + return CURLE_OK; +} +#endif diff --git a/libcurl/src/lib/tftp.h b/libcurl/src/lib/tftp.h new file mode 100644 index 0000000..117b40f --- /dev/null +++ b/libcurl/src/lib/tftp.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_TFTP_H +#define HEADER_CURL_TFTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TFTP +extern const struct Curl_handler Curl_handler_tftp; +#endif + +#endif /* HEADER_CURL_TFTP_H */ + diff --git a/libcurl/src/lib/timeval.c b/libcurl/src/lib/timeval.c new file mode 100644 index 0000000..b6f398d --- /dev/null +++ b/libcurl/src/lib/timeval.c @@ -0,0 +1,142 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "timeval.h" + +#if defined(WIN32) && !defined(MSDOS) + +CURL_STATIC struct timeval curlx_tvnow(void) +{ + /* + ** GetTickCount() is available on _all_ Windows versions from W95 up + ** to nowadays. Returns milliseconds elapsed since last system boot, + ** increases monotonically and wraps once 49.7 days have elapsed. + */ + struct timeval now; +#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ + (_WIN32_WINNT < _WIN32_WINNT_VISTA) + DWORD milliseconds = GetTickCount(); + now.tv_sec = milliseconds / 1000; + now.tv_usec = (milliseconds % 1000) * 1000; +#else + ULONGLONG milliseconds = GetTickCount64(); + now.tv_sec = (long) (milliseconds / 1000); + now.tv_usec = (long) (milliseconds % 1000) * 1000; +#endif + + return now; +} + +#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) + +CURL_STATIC struct timeval curlx_tvnow(void) +{ + /* + ** clock_gettime() is granted to be increased monotonically when the + ** monotonic clock is queried. Time starting point is unspecified, it + ** could be the system start-up time, the Epoch, or something else, + ** in any case the time starting point does not change once that the + ** system has started up. + */ + struct timeval now; + struct timespec tsnow; + if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) { + now.tv_sec = tsnow.tv_sec; + now.tv_usec = tsnow.tv_nsec / 1000; + } + /* + ** Even when the configure process has truly detected monotonic clock + ** availability, it might happen that it is not actually available at + ** run-time. When this occurs simply fallback to other time source. + */ +#ifdef HAVE_GETTIMEOFDAY + else + (void)gettimeofday(&now, NULL); +#else + else { + now.tv_sec = (long)time(NULL); + now.tv_usec = 0; + } +#endif + return now; +} + +#elif defined(HAVE_GETTIMEOFDAY) + +CURL_STATIC struct timeval curlx_tvnow(void) +{ + /* + ** gettimeofday() is not granted to be increased monotonically, due to + ** clock drifting and external source time synchronization it can jump + ** forward or backward in time. + */ + struct timeval now; + (void)gettimeofday(&now, NULL); + return now; +} + +#else + +CURL_STATIC struct timeval curlx_tvnow(void) +{ + /* + ** time() returns the value of time in seconds since the Epoch. + */ + struct timeval now; + now.tv_sec = (long)time(NULL); + now.tv_usec = 0; + return now; +} + +#endif + +/* + * Make sure that the first argument is the more recent time, as otherwise + * we'll get a weird negative time-diff back... + * + * Returns: the time difference in number of milliseconds. + */ +CURL_STATIC long curlx_tvdiff(struct timeval newer, struct timeval older) +{ + return (newer.tv_sec-older.tv_sec)*1000+ + (long)(newer.tv_usec-older.tv_usec)/1000; +} + +/* + * Same as curlx_tvdiff but with full usec resolution. + * + * Returns: the time difference in seconds with subsecond resolution. + */ +CURL_STATIC double curlx_tvdiff_secs(struct timeval newer, struct timeval older) +{ + if(newer.tv_sec != older.tv_sec) + return (double)(newer.tv_sec-older.tv_sec)+ + (double)(newer.tv_usec-older.tv_usec)/1000000.0; + else + return (double)(newer.tv_usec-older.tv_usec)/1000000.0; +} + +/* return the number of seconds in the given input timeval struct */ +CURL_STATIC long Curl_tvlong(struct timeval t1) +{ + return t1.tv_sec; +} diff --git a/libcurl/src/lib/timeval.h b/libcurl/src/lib/timeval.h new file mode 100644 index 0000000..2562012 --- /dev/null +++ b/libcurl/src/lib/timeval.h @@ -0,0 +1,58 @@ +#ifndef HEADER_CURL_TIMEVAL_H +#define HEADER_CURL_TIMEVAL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * CAUTION: this header is designed to work when included by the app-side + * as well as the library. Do not mix with library internals! + */ + +#include "curl_setup.h" + +CURL_STATIC struct timeval curlx_tvnow(void); + +/* + * Make sure that the first argument (t1) is the more recent time and t2 is + * the older time, as otherwise you get a weird negative time-diff back... + * + * Returns: the time difference in number of milliseconds. + */ +CURL_STATIC long curlx_tvdiff(struct timeval t1, struct timeval t2); + +/* + * Same as curlx_tvdiff but with full usec resolution. + * + * Returns: the time difference in seconds with subsecond resolution. + */ +CURL_STATIC double curlx_tvdiff_secs(struct timeval t1, struct timeval t2); + +CURL_STATIC long Curl_tvlong(struct timeval t1); + +/* These two defines below exist to provide the older API for library + internals only. */ +#define Curl_tvnow() curlx_tvnow() +#define Curl_tvdiff(x,y) curlx_tvdiff(x,y) +#define Curl_tvdiff_secs(x,y) curlx_tvdiff_secs(x,y) + +#endif /* HEADER_CURL_TIMEVAL_H */ + diff --git a/libcurl/src/lib/transfer.c b/libcurl/src/lib/transfer.c new file mode 100644 index 0000000..227dc83 --- /dev/null +++ b/libcurl/src/lib/transfer.c @@ -0,0 +1,2004 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "strtoofft.h" +#include "strequal.h" +#include "rawstr.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#ifndef HAVE_SOCKET +#error "We can't compile without socket() support!" +#endif + +#include "urldata.h" +#include +#include "netrc.h" + +#include "content_encoding.h" +#include "hostip.h" +#include "transfer.h" +#include "sendf.h" +#include "speedcheck.h" +#include "progress.h" +#include "http.h" +#include "url.h" +#include "getinfo.h" +#include "vtls/vtls.h" +#include "http_digest.h" +#include "curl_ntlm.h" +#include "http_negotiate.h" +#include "share.h" +#include "select.h" +#include "multiif.h" +#include "connect.h" +#include "non-ascii.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * This function will call the read callback to fill our buffer with data + * to upload. + */ +CURL_STATIC CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) +{ + struct SessionHandle *data = conn->data; + size_t buffersize = (size_t)bytes; + int nread; +#ifdef CURL_DOES_CONVERSIONS + bool sending_http_headers = FALSE; + + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + const struct HTTP *http = data->req.protop; + + if(http->sending == HTTPSEND_REQUEST) + /* We're sending the HTTP request headers, not the data. + Remember that so we don't re-translate them into garbage. */ + sending_http_headers = TRUE; + } +#endif + + if(data->req.upload_chunky) { + /* if chunked Transfer-Encoding */ + buffersize -= (8 + 2 + 2); /* 32bit hex + CRLF + CRLF */ + data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */ + } + + /* this function returns a size_t, so we typecast to int to prevent warnings + with picky compilers */ + nread = (int)conn->fread_func(data->req.upload_fromhere, 1, + buffersize, conn->fread_in); + + if(nread == CURL_READFUNC_ABORT) { + failf(data, "operation aborted by callback"); + *nreadp = 0; + return CURLE_ABORTED_BY_CALLBACK; + } + else if(nread == CURL_READFUNC_PAUSE) { + + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* protocols that work without network cannot be paused. This is + actually only FILE:// just now, and it can't pause since the transfer + isn't done using the "normal" procedure. */ + failf(data, "Read callback asked for PAUSE when not supported!"); + return CURLE_READ_ERROR; + } + else { + struct SingleRequest *k = &data->req; + /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ + k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */ + if(data->req.upload_chunky) { + /* Back out the preallocation done above */ + data->req.upload_fromhere -= (8 + 2); + } + *nreadp = 0; + } + return CURLE_OK; /* nothing was read */ + } + else if((size_t)nread > buffersize) { + /* the read function returned a too large value */ + *nreadp = 0; + failf(data, "read function returned funny value"); + return CURLE_READ_ERROR; + } + + if(!data->req.forbidchunk && data->req.upload_chunky) { + /* if chunked Transfer-Encoding + * build chunk: + * + * CRLF + * CRLF + */ + /* On non-ASCII platforms the may or may not be + translated based on set.prefer_ascii while the protocol + portion must always be translated to the network encoding. + To further complicate matters, line end conversion might be + done later on, so we need to prevent CRLFs from becoming + CRCRLFs if that's the case. To do this we use bare LFs + here, knowing they'll become CRLFs later on. + */ + + char hexbuffer[11]; + const char *endofline_native; + const char *endofline_network; + int hexlen; + + if( +#ifdef CURL_DO_LINEEND_CONV + (data->set.prefer_ascii) || +#endif + (data->set.crlf)) { + /* \n will become \r\n later on */ + endofline_native = "\n"; + endofline_network = "\x0a"; + } + else { + endofline_native = "\r\n"; + endofline_network = "\x0d\x0a"; + } + hexlen = snprintf(hexbuffer, sizeof(hexbuffer), + "%x%s", nread, endofline_native); + + /* move buffer pointer */ + data->req.upload_fromhere -= hexlen; + nread += hexlen; + + /* copy the prefix to the buffer, leaving out the NUL */ + memcpy(data->req.upload_fromhere, hexbuffer, hexlen); + + /* always append ASCII CRLF to the data */ + memcpy(data->req.upload_fromhere + nread, + endofline_network, + strlen(endofline_network)); + +#ifdef CURL_DOES_CONVERSIONS + CURLcode result; + int length; + if(data->set.prefer_ascii) { + /* translate the protocol and data */ + length = nread; + } + else { + /* just translate the protocol portion */ + length = strlen(hexbuffer); + } + result = Curl_convert_to_network(data, data->req.upload_fromhere, length); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; +#endif /* CURL_DOES_CONVERSIONS */ + + if((nread - hexlen) == 0) + /* mark this as done once this chunk is transferred */ + data->req.upload_done = TRUE; + + nread+=(int)strlen(endofline_native); /* for the added end of line */ + } +#ifdef CURL_DOES_CONVERSIONS + else if((data->set.prefer_ascii) && (!sending_http_headers)) { + CURLcode result; + result = Curl_convert_to_network(data, data->req.upload_fromhere, nread); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + } +#endif /* CURL_DOES_CONVERSIONS */ + + *nreadp = nread; + + return CURLE_OK; +} + + +/* + * Curl_readrewind() rewinds the read stream. This is typically used for HTTP + * POST/PUT with multi-pass authentication when a sending was denied and a + * resend is necessary. + */ +CURL_STATIC CURLcode Curl_readrewind(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + + conn->bits.rewindaftersend = FALSE; /* we rewind now */ + + /* explicitly switch off sending data on this connection now since we are + about to restart a new transfer and thus we want to avoid inadvertently + sending more data on the existing connection until the next transfer + starts */ + data->req.keepon &= ~KEEP_SEND; + + /* We have sent away data. If not using CURLOPT_POSTFIELDS or + CURLOPT_HTTPPOST, call app to rewind + */ + if(data->set.postfields || + (data->set.httpreq == HTTPREQ_POST_FORM)) + ; /* do nothing */ + else { + if(data->set.seek_func) { + int err; + + err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET); + if(err) { + failf(data, "seek callback returned error %d", (int)err); + return CURLE_SEND_FAIL_REWIND; + } + } + else if(data->set.ioctl_func) { + curlioerr err; + + err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD, + data->set.ioctl_client); + infof(data, "the ioctl callback returned %d\n", (int)err); + + if(err) { + /* FIXME: convert to a human readable error message */ + failf(data, "ioctl callback returned error %d", (int)err); + return CURLE_SEND_FAIL_REWIND; + } + } + else { + /* If no CURLOPT_READFUNCTION is used, we know that we operate on a + given FILE * stream and we can actually attempt to rewind that + ourselves with fseek() */ + if(data->set.fread_func == (curl_read_callback)fread) { + if(-1 != fseek(data->set.in, 0, SEEK_SET)) + /* successful rewind */ + return CURLE_OK; + } + + /* no callback set or failure above, makes us fail at once */ + failf(data, "necessary data rewind wasn't possible"); + return CURLE_SEND_FAIL_REWIND; + } + } + return CURLE_OK; +} + +static int data_pending(const struct connectdata *conn) +{ + /* in the case of libssh2, we can never be really sure that we have emptied + its internal buffers so we MUST always try until we get EAGAIN back */ + return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) || +#if defined(USE_NGHTTP2) + Curl_ssl_data_pending(conn, FIRSTSOCKET) || + /* For HTTP/2, we may read up everything including responde body + with header fields in Curl_http_readwrite_headers. If no + content-length is provided, curl waits for the connection + close, which we emulate it using conn->proto.httpc.closed = + TRUE. The thing is if we read everything, then http2_recv won't + be called and we cannot signal the HTTP/2 stream has closed. As + a workaround, we return nonzero here to call http2_recv. */ + ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20 && + conn->proto.httpc.closed); +#else + Curl_ssl_data_pending(conn, FIRSTSOCKET); +#endif +} + +static void read_rewind(struct connectdata *conn, + size_t thismuch) +{ + DEBUGASSERT(conn->read_pos >= thismuch); + + conn->read_pos -= thismuch; + conn->bits.stream_was_rewound = TRUE; + +#ifdef DEBUGBUILD + { + char buf[512 + 1]; + size_t show; + + show = CURLMIN(conn->buf_len - conn->read_pos, sizeof(buf)-1); + if(conn->master_buffer) { + memcpy(buf, conn->master_buffer + conn->read_pos, show); + buf[show] = '\0'; + } + else { + buf[0] = '\0'; + } + + DEBUGF(infof(conn->data, + "Buffer after stream rewind (read_pos = %zu): [%s]\n", + conn->read_pos, buf)); + } +#endif +} + +/* + * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the + * remote document with the time provided by CURLOPT_TIMEVAL + */ +CURL_STATIC bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc) +{ + if((timeofdoc == 0) || (data->set.timevalue == 0)) + return TRUE; + + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + if(timeofdoc <= data->set.timevalue) { + infof(data, + "The requested document is not new enough\n"); + data->info.timecond = TRUE; + return FALSE; + } + break; + case CURL_TIMECOND_IFUNMODSINCE: + if(timeofdoc >= data->set.timevalue) { + infof(data, + "The requested document is not old enough\n"); + data->info.timecond = TRUE; + return FALSE; + } + break; + } + + return TRUE; +} + +/* + * Go ahead and do a read if we have a readable socket or if + * the stream was rewound (in which case we have data in a + * buffer) + */ +static CURLcode readwrite_data(struct SessionHandle *data, + struct connectdata *conn, + struct SingleRequest *k, + int *didwhat, bool *done) +{ + CURLcode result = CURLE_OK; + ssize_t nread; /* number of bytes read */ + size_t excess = 0; /* excess bytes read */ + bool is_empty_data = FALSE; + bool readmore = FALSE; /* used by RTP to signal for more data */ + + *done = FALSE; + + /* This is where we loop until we have read everything there is to + read or we get a CURLE_AGAIN */ + do { + size_t buffersize = data->set.buffer_size? + data->set.buffer_size : BUFSIZE; + size_t bytestoread = buffersize; + + if(k->size != -1 && !k->header) { + /* make sure we don't read "too much" if we can help it since we + might be pipelining and then someone else might want to read what + follows! */ + curl_off_t totalleft = k->size - k->bytecount; + if(totalleft < (curl_off_t)bytestoread) + bytestoread = (size_t)totalleft; + } + + if(bytestoread) { + /* receive data from the network! */ + result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread); + + /* read would've blocked */ + if(CURLE_AGAIN == result) + break; /* get out of loop */ + + if(result>0) + return result; + } + else { + /* read nothing but since we wanted nothing we consider this an OK + situation to proceed from */ + nread = 0; + } + + if((k->bytecount == 0) && (k->writebytecount == 0)) { + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + if(k->exp100 > EXP100_SEND_DATA) + /* set time stamp to compare with when waiting for the 100 */ + k->start100 = Curl_tvnow(); + } + + *didwhat |= KEEP_RECV; + /* indicates data of zero size, i.e. empty file */ + is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE; + + /* NUL terminate, allowing string ops to be used */ + if(0 < nread || is_empty_data) { + k->buf[nread] = 0; + } + else if(0 >= nread) { + /* if we receive 0 or less here, the server closed the connection + and we bail out from this! */ + DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n")); + k->keepon &= ~KEEP_RECV; + break; + } + + /* Default buffer to use when we write the buffer, it may be changed + in the flow below before the actual storing is done. */ + k->str = k->buf; + + if(conn->handler->readwrite) { + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + if(readmore) + break; + } + +#ifndef CURL_DISABLE_HTTP + /* Since this is a two-state thing, we check if we are parsing + headers at the moment or not. */ + if(k->header) { + /* we are in parse-the-header-mode */ + bool stop_reading = FALSE; + result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading); + if(result) + return result; + + if(conn->handler->readwrite && + (k->maxdownload <= 0 && nread > 0)) { + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + if(readmore) + break; + } + + if(stop_reading) { + /* We've stopped dealing with input, get out of the do-while loop */ + + if(nread > 0) { + if(Curl_multi_pipeline_enabled(conn->data->multi)) { + infof(data, + "Rewinding stream by : %zd" + " bytes on url %s (zero-length body)\n", + nread, data->state.path); + read_rewind(conn, (size_t)nread); + } + else { + infof(data, + "Excess found in a non pipelined read:" + " excess = %zd" + " url = %s (zero-length body)\n", + nread, data->state.path); + } + } + + break; + } + } +#endif /* CURL_DISABLE_HTTP */ + + + /* This is not an 'else if' since it may be a rest from the header + parsing, where the beginning of the buffer is headers and the end + is non-headers. */ + if(k->str && !k->header && (nread > 0 || is_empty_data)) { + +#ifndef CURL_DISABLE_HTTP + if(0 == k->bodywrites && !is_empty_data) { + /* These checks are only made the first time we are about to + write a piece of the body */ + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + /* HTTP-only checks */ + + if(data->req.newurl) { + if(conn->bits.close) { + /* Abort after the headers if "follow Location" is set + and we're set to close anyway. */ + k->keepon &= ~KEEP_RECV; + *done = TRUE; + return CURLE_OK; + } + /* We have a new url to load, but since we want to be able + to re-use this connection properly, we read the full + response in "ignore more" */ + k->ignorebody = TRUE; + infof(data, "Ignoring the response-body\n"); + } + if(data->state.resume_from && !k->content_range && + (data->set.httpreq==HTTPREQ_GET) && + !k->ignorebody) { + + if(k->size == data->state.resume_from) { + /* The resume point is at the end of file, consider this fine + even if it doesn't allow resume from here. */ + infof(data, "The entire document is already downloaded"); + connclose(conn, "already downloaded"); + /* Abort download */ + k->keepon &= ~KEEP_RECV; + *done = TRUE; + return CURLE_OK; + } + + /* we wanted to resume a download, although the server doesn't + * seem to support this and we did this with a GET (if it + * wasn't a GET we did a POST or PUT resume) */ + failf(data, "HTTP server doesn't seem to support " + "byte ranges. Cannot resume."); + return CURLE_RANGE_ERROR; + } + + if(data->set.timecondition && !data->state.range) { + /* A time condition has been set AND no ranges have been + requested. This seems to be what chapter 13.3.4 of + RFC 2616 defines to be the correct action for a + HTTP/1.1 client */ + + if(!Curl_meets_timecondition(data, k->timeofdoc)) { + *done = TRUE; + /* We're simulating a http 304 from server so we return + what should have been returned from the server */ + data->info.httpcode = 304; + infof(data, "Simulate a HTTP 304 response!\n"); + /* we abort the transfer before it is completed == we ruin the + re-use ability. Close the connection */ + connclose(conn, "Simulated 304 handling"); + return CURLE_OK; + } + } /* we have a time condition */ + + } /* this is HTTP or RTSP */ + } /* this is the first time we write a body part */ +#endif /* CURL_DISABLE_HTTP */ + + k->bodywrites++; + + /* pass data to the debug function before it gets "dechunked" */ + if(data->set.verbose) { + if(k->badheader) { + Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff, + (size_t)k->hbuflen, conn); + if(k->badheader == HEADER_PARTHEADER) + Curl_debug(data, CURLINFO_DATA_IN, + k->str, (size_t)nread, conn); + } + else + Curl_debug(data, CURLINFO_DATA_IN, + k->str, (size_t)nread, conn); + } + +#ifndef CURL_DISABLE_HTTP + if(k->chunk) { + /* + * Here comes a chunked transfer flying and we need to decode this + * properly. While the name says read, this function both reads + * and writes away the data. The returned 'nread' holds the number + * of actual data it wrote to the client. + */ + + CHUNKcode res = + Curl_httpchunk_read(conn, k->str, nread, &nread); + + if(CHUNKE_OK < res) { + if(CHUNKE_WRITE_ERROR == res) { + failf(data, "Failed writing data"); + return CURLE_WRITE_ERROR; + } + failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res)); + return CURLE_RECV_ERROR; + } + else if(CHUNKE_STOP == res) { + size_t dataleft; + /* we're done reading chunks! */ + k->keepon &= ~KEEP_RECV; /* read no more */ + + /* There are now possibly N number of bytes at the end of the + str buffer that weren't written to the client. + + We DO care about this data if we are pipelining. + Push it back to be read on the next pass. */ + + dataleft = conn->chunk.dataleft; + if(dataleft != 0) { + infof(conn->data, "Leftovers after chunking: %zu bytes\n", + dataleft); + if(Curl_multi_pipeline_enabled(conn->data->multi)) { + /* only attempt the rewind if we truly are pipelining */ + infof(conn->data, "Rewinding %zu bytes\n",dataleft); + read_rewind(conn, dataleft); + } + } + } + /* If it returned OK, we just keep going */ + } +#endif /* CURL_DISABLE_HTTP */ + + /* Account for body content stored in the header buffer */ + if(k->badheader && !k->ignorebody) { + DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n", + k->hbuflen)); + k->bytecount += k->hbuflen; + } + + if((-1 != k->maxdownload) && + (k->bytecount + nread >= k->maxdownload)) { + + excess = (size_t)(k->bytecount + nread - k->maxdownload); + if(excess > 0 && !k->ignorebody) { + if(Curl_multi_pipeline_enabled(conn->data->multi)) { + /* The 'excess' amount below can't be more than BUFSIZE which + always will fit in a size_t */ + infof(data, + "Rewinding stream by : %zu" + " bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T + ", maxdownload = %" CURL_FORMAT_CURL_OFF_T + ", bytecount = %" CURL_FORMAT_CURL_OFF_T ", nread = %zd)\n", + excess, data->state.path, + k->size, k->maxdownload, k->bytecount, nread); + read_rewind(conn, excess); + } + else { + infof(data, + "Excess found in a non pipelined read:" + " excess = %zu" + ", size = %" CURL_FORMAT_CURL_OFF_T + ", maxdownload = %" CURL_FORMAT_CURL_OFF_T + ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n", + excess, k->size, k->maxdownload, k->bytecount); + } + } + + nread = (ssize_t) (k->maxdownload - k->bytecount); + if(nread < 0 ) /* this should be unusual */ + nread = 0; + + k->keepon &= ~KEEP_RECV; /* we're done reading */ + } + + k->bytecount += nread; + + Curl_pgrsSetDownloadCounter(data, k->bytecount); + + if(!k->chunk && (nread || k->badheader || is_empty_data)) { + /* If this is chunky transfer, it was already written */ + + if(k->badheader && !k->ignorebody) { + /* we parsed a piece of data wrongly assuming it was a header + and now we output it as body instead */ + + /* Don't let excess data pollute body writes */ + if(k->maxdownload == -1 || (curl_off_t)k->hbuflen <= k->maxdownload) + result = Curl_client_write(conn, CLIENTWRITE_BODY, + data->state.headerbuff, + k->hbuflen); + else + result = Curl_client_write(conn, CLIENTWRITE_BODY, + data->state.headerbuff, + (size_t)k->maxdownload); + + if(result) + return result; + } + if(k->badheader < HEADER_ALLBAD) { + /* This switch handles various content encodings. If there's an + error here, be sure to check over the almost identical code + in http_chunks.c. + Make sure that ALL_CONTENT_ENCODINGS contains all the + encodings handled here. */ +#ifdef HAVE_LIBZ + switch (conn->data->set.http_ce_skip ? + IDENTITY : k->auto_decoding) { + case IDENTITY: +#endif + /* This is the default when the server sends no + Content-Encoding header. See Curl_readwrite_init; the + memset() call initializes k->auto_decoding to zero. */ + if(!k->ignorebody) { + +#ifndef CURL_DISABLE_POP3 + if(conn->handler->protocol&PROTO_FAMILY_POP3) + result = Curl_pop3_write(conn, k->str, nread); + else +#endif /* CURL_DISABLE_POP3 */ + + result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str, + nread); + } +#ifdef HAVE_LIBZ + break; + + case DEFLATE: + /* Assume CLIENTWRITE_BODY; headers are not encoded. */ + if(!k->ignorebody) + result = Curl_unencode_deflate_write(conn, k, nread); + break; + + case GZIP: + /* Assume CLIENTWRITE_BODY; headers are not encoded. */ + if(!k->ignorebody) + result = Curl_unencode_gzip_write(conn, k, nread); + break; + + case COMPRESS: + default: + failf (data, "Unrecognized content encoding type. " + "libcurl understands `identity', `deflate' and `gzip' " + "content encodings."); + result = CURLE_BAD_CONTENT_ENCODING; + break; + } +#endif + } + k->badheader = HEADER_NORMAL; /* taken care of now */ + + if(result) + return result; + } + + } /* if(! header and data to read ) */ + + if(conn->handler->readwrite && + (excess > 0 && !conn->bits.stream_was_rewound)) { + /* Parse the excess data */ + k->str += nread; + nread = (ssize_t)excess; + + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + + if(readmore) + k->keepon |= KEEP_RECV; /* we're not done reading */ + break; + } + + if(is_empty_data) { + /* if we received nothing, the server closed the connection and we + are done */ + k->keepon &= ~KEEP_RECV; + } + + } while(data_pending(conn)); + + if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) && + conn->bits.close ) { + /* When we've read the entire thing and the close bit is set, the server + may now close the connection. If there's now any kind of sending going + on from our side, we need to stop that immediately. */ + infof(data, "we are done reading and this is set to close, stop send\n"); + k->keepon &= ~KEEP_SEND; /* no writing anymore either */ + } + + return CURLE_OK; +} + +/* + * Send data to upload to the server, when the socket is writable. + */ +static CURLcode readwrite_upload(struct SessionHandle *data, + struct connectdata *conn, + struct SingleRequest *k, + int *didwhat) +{ + ssize_t i, si; + ssize_t bytes_written; + CURLcode result; + ssize_t nread; /* number of bytes read */ + bool sending_http_headers = FALSE; + + if((k->bytecount == 0) && (k->writebytecount == 0)) + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + + *didwhat |= KEEP_SEND; + + /* + * We loop here to do the READ and SEND loop until we run out of + * data to send or until we get EWOULDBLOCK back + * + * FIXME: above comment is misleading. Currently no looping is + * actually done in do-while loop below. + */ + do { + + /* only read more data if there's no upload data already + present in the upload buffer */ + if(0 == data->req.upload_present) { + /* init the "upload from here" pointer */ + data->req.upload_fromhere = k->uploadbuf; + + if(!k->upload_done) { + /* HTTP pollution, this should be written nicer to become more + protocol agnostic. */ + int fillcount; + struct HTTP *http = data->req.protop; + + if((k->exp100 == EXP100_SENDING_REQUEST) && + (http->sending == HTTPSEND_BODY)) { + /* If this call is to send body data, we must take some action: + We have sent off the full HTTP 1.1 request, and we shall now + go into the Expect: 100 state and await such a header */ + k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */ + k->keepon &= ~KEEP_SEND; /* disable writing */ + k->start100 = Curl_tvnow(); /* timeout count starts now */ + *didwhat &= ~KEEP_SEND; /* we didn't write anything actually */ + + /* set a timeout for the multi interface */ + Curl_expire(data, data->set.expect_100_timeout); + break; + } + + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + if(http->sending == HTTPSEND_REQUEST) + /* We're sending the HTTP request headers, not the data. + Remember that so we don't change the line endings. */ + sending_http_headers = TRUE; + else + sending_http_headers = FALSE; + } + + result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount); + if(result) + return result; + + nread = (ssize_t)fillcount; + } + else + nread = 0; /* we're done uploading/reading */ + + if(!nread && (k->keepon & KEEP_SEND_PAUSE)) { + /* this is a paused transfer */ + break; + } + else if(nread<=0) { + /* done */ + k->keepon &= ~KEEP_SEND; /* we're done writing */ + + if(conn->bits.rewindaftersend) { + result = Curl_readrewind(conn); + if(result) + return result; + } + break; + } + + /* store number of bytes available for upload */ + data->req.upload_present = nread; + + /* convert LF to CRLF if so asked */ + if((!sending_http_headers) && ( +#ifdef CURL_DO_LINEEND_CONV + /* always convert if we're FTPing in ASCII mode */ + (data->set.prefer_ascii) || +#endif + (data->set.crlf))) { + /* Do we need to allocate a scratch buffer? */ + if(!data->state.scratch) { + data->state.scratch = malloc(2 * BUFSIZE); + if(!data->state.scratch) { + failf(data, "Failed to alloc scratch buffer!"); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* + * ASCII/EBCDIC Note: This is presumably a text (not binary) + * transfer so the data should already be in ASCII. + * That means the hex values for ASCII CR (0x0d) & LF (0x0a) + * must be used instead of the escape sequences \r & \n. + */ + for(i = 0, si = 0; i < nread; i++, si++) { + if(data->req.upload_fromhere[i] == 0x0a) { + data->state.scratch[si++] = 0x0d; + data->state.scratch[si] = 0x0a; + if(!data->set.crlf) { + /* we're here only because FTP is in ASCII mode... + bump infilesize for the LF we just added */ + data->state.infilesize++; + } + } + else + data->state.scratch[si] = data->req.upload_fromhere[i]; + } + + if(si != nread) { + /* only perform the special operation if we really did replace + anything */ + nread = si; + + /* upload from the new (replaced) buffer instead */ + data->req.upload_fromhere = data->state.scratch; + + /* set the new amount too */ + data->req.upload_present = nread; + } + } + +#ifndef CURL_DISABLE_SMTP + if(conn->handler->protocol & PROTO_FAMILY_SMTP) { + result = Curl_smtp_escape_eob(conn, nread); + if(result) + return result; + } +#endif /* CURL_DISABLE_SMTP */ + } /* if 0 == data->req.upload_present */ + else { + /* We have a partial buffer left from a previous "round". Use + that instead of reading more data */ + } + + /* write to socket (send away data) */ + result = Curl_write(conn, + conn->writesockfd, /* socket to send to */ + data->req.upload_fromhere, /* buffer pointer */ + data->req.upload_present, /* buffer size */ + &bytes_written); /* actually sent */ + + if(result) + return result; + + if(data->set.verbose) + /* show the data before we change the pointer upload_fromhere */ + Curl_debug(data, CURLINFO_DATA_OUT, data->req.upload_fromhere, + (size_t)bytes_written, conn); + + k->writebytecount += bytes_written; + + if(k->writebytecount == data->state.infilesize) { + /* we have sent all data we were supposed to */ + k->upload_done = TRUE; + infof(data, "We are completely uploaded and fine\n"); + } + + if(data->req.upload_present != bytes_written) { + /* we only wrote a part of the buffer (if anything), deal with it! */ + + /* store the amount of bytes left in the buffer to write */ + data->req.upload_present -= bytes_written; + + /* advance the pointer where to find the buffer when the next send + is to happen */ + data->req.upload_fromhere += bytes_written; + } + else { + /* we've uploaded that buffer now */ + data->req.upload_fromhere = k->uploadbuf; + data->req.upload_present = 0; /* no more bytes left */ + + if(k->upload_done) { + /* switch off writing, we're done! */ + k->keepon &= ~KEEP_SEND; /* we're done writing */ + } + } + + Curl_pgrsSetUploadCounter(data, k->writebytecount); + + } WHILE_FALSE; /* just to break out from! */ + + return CURLE_OK; +} + +/* + * Curl_readwrite() is the low-level function to be called when data is to + * be read and written to/from the connection. + */ +CURL_STATIC CURLcode Curl_readwrite(struct connectdata *conn, + bool *done) +{ + struct SessionHandle *data = conn->data; + struct SingleRequest *k = &data->req; + CURLcode result; + int didwhat=0; + + curl_socket_t fd_read; + curl_socket_t fd_write; + int select_res = conn->cselect_bits; + + conn->cselect_bits = 0; + + /* only use the proper socket if the *_HOLD bit is not set simultaneously as + then we are in rate limiting state in that transfer direction */ + + if((k->keepon & KEEP_RECVBITS) == KEEP_RECV) + fd_read = conn->sockfd; + else + fd_read = CURL_SOCKET_BAD; + + if((k->keepon & KEEP_SENDBITS) == KEEP_SEND) + fd_write = conn->writesockfd; + else + fd_write = CURL_SOCKET_BAD; + + if(!select_res) /* Call for select()/poll() only, if read/write/error + status is not known. */ + select_res = Curl_socket_ready(fd_read, fd_write, 0); + + if(select_res == CURL_CSELECT_ERR) { + failf(data, "select/poll returned error"); + return CURLE_SEND_ERROR; + } + + /* We go ahead and do a read if we have a readable socket or if + the stream was rewound (in which case we have data in a + buffer) */ + if((k->keepon & KEEP_RECV) && + ((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) { + + result = readwrite_data(data, conn, k, &didwhat, done); + if(result || *done) + return result; + } + + /* If we still have writing to do, we check if we have a writable socket. */ + if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) { + /* write */ + + result = readwrite_upload(data, conn, k, &didwhat); + if(result) + return result; + } + + k->now = Curl_tvnow(); + if(didwhat) { + /* Update read/write counters */ + if(k->bytecountp) + *k->bytecountp = k->bytecount; /* read count */ + if(k->writebytecountp) + *k->writebytecountp = k->writebytecount; /* write count */ + } + else { + /* no read no write, this is a timeout? */ + if(k->exp100 == EXP100_AWAITING_CONTINUE) { + /* This should allow some time for the header to arrive, but only a + very short time as otherwise it'll be too much wasted time too + often. */ + + /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status": + + Therefore, when a client sends this header field to an origin server + (possibly via a proxy) from which it has never seen a 100 (Continue) + status, the client SHOULD NOT wait for an indefinite period before + sending the request body. + + */ + + long ms = Curl_tvdiff(k->now, k->start100); + if(ms >= data->set.expect_100_timeout) { + /* we've waited long enough, continue anyway */ + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + infof(data, "Done waiting for 100-continue\n"); + } + } + } + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, k->now); + if(result) + return result; + + if(k->keepon) { + if(0 > Curl_timeleft(data, &k->now, FALSE)) { + if(k->size != -1) { + failf(data, "Operation timed out after %ld milliseconds with %" + CURL_FORMAT_CURL_OFF_T " out of %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount, + k->size); + } + else { + failf(data, "Operation timed out after %ld milliseconds with %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount); + } + return CURLE_OPERATION_TIMEDOUT; + } + } + else { + /* + * The transfer has been performed. Just make some general checks before + * returning. + */ + + if(!(data->set.opt_no_body) && (k->size != -1) && + (k->bytecount != k->size) && +#ifdef CURL_DO_LINEEND_CONV + /* Most FTP servers don't adjust their file SIZE response for CRLFs, + so we'll check to see if the discrepancy can be explained + by the number of CRLFs we've changed to LFs. + */ + (k->bytecount != (k->size + data->state.crlf_conversions)) && +#endif /* CURL_DO_LINEEND_CONV */ + !data->req.newurl) { + failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T + " bytes remaining to read", + k->size - k->bytecount); + return CURLE_PARTIAL_FILE; + } + else if(!(data->set.opt_no_body) && + k->chunk && + (conn->chunk.state != CHUNK_STOP)) { + /* + * In chunked mode, return an error if the connection is closed prior to + * the empty (terminating) chunk is read. + * + * The condition above used to check for + * conn->proto.http->chunk.datasize != 0 which is true after reading + * *any* chunk, not just the empty chunk. + * + */ + failf(data, "transfer closed with outstanding read data remaining"); + return CURLE_PARTIAL_FILE; + } + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + } + + /* Now update the "done" boolean we return */ + *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND| + KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE; + + return CURLE_OK; +} + +/* + * Curl_single_getsock() gets called by the multi interface code when the app + * has requested to get the sockets for the current connection. This function + * will then be called once for every connection that the multi interface + * keeps track of. This function will only be called for connections that are + * in the proper state to have this information available. + */ +CURL_STATIC int Curl_single_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks) +{ + const struct SessionHandle *data = conn->data; + int bitmap = GETSOCK_BLANK; + unsigned sockindex = 0; + + if(conn->handler->perform_getsock) + return conn->handler->perform_getsock(conn, sock, numsocks); + + if(numsocks < 2) + /* simple check but we might need two slots */ + return GETSOCK_BLANK; + + /* don't include HOLD and PAUSE connections */ + if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) { + + DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD); + + bitmap |= GETSOCK_READSOCK(sockindex); + sock[sockindex] = conn->sockfd; + } + + /* don't include HOLD and PAUSE connections */ + if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) { + + if((conn->sockfd != conn->writesockfd) || + bitmap == GETSOCK_BLANK) { + /* only if they are not the same socket and we have a readable + one, we increase index */ + if(bitmap != GETSOCK_BLANK) + sockindex++; /* increase index if we need two entries */ + + DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD); + + sock[sockindex] = conn->writesockfd; + } + + bitmap |= GETSOCK_WRITESOCK(sockindex); + } + + return bitmap; +} + +/* + * Determine optimum sleep time based on configured rate, current rate, + * and packet size. + * Returns value in milliseconds. + * + * The basic idea is to adjust the desired rate up/down in this method + * based on whether we are running too slow or too fast. Then, calculate + * how many milliseconds to wait for the next packet to achieve this new + * rate. + */ +CURL_STATIC long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps, + int pkt_size) +{ + curl_off_t min_sleep = 0; + curl_off_t rv = 0; + + if(rate_bps == 0) + return 0; + + /* If running faster than about .1% of the desired speed, slow + * us down a bit. Use shift instead of division as the 0.1% + * cutoff is arbitrary anyway. + */ + if(cur_rate_bps > (rate_bps + (rate_bps >> 10))) { + /* running too fast, decrease target rate by 1/64th of rate */ + rate_bps -= rate_bps >> 6; + min_sleep = 1; + } + else if(cur_rate_bps < (rate_bps - (rate_bps >> 10))) { + /* running too slow, increase target rate by 1/64th of rate */ + rate_bps += rate_bps >> 6; + } + + /* Determine number of milliseconds to wait until we do + * the next packet at the adjusted rate. We should wait + * longer when using larger packets, for instance. + */ + rv = ((curl_off_t)(pkt_size * 1000) / rate_bps); + + /* Catch rounding errors and always slow down at least 1ms if + * we are running too fast. + */ + if(rv < min_sleep) + rv = min_sleep; + + /* Bound value to fit in 'long' on 32-bit platform. That's + * plenty long enough anyway! + */ + if(rv > 0x7fffffff) + rv = 0x7fffffff; + + return (long)rv; +} + +/* + * Curl_pretransfer() is called immediately before a transfer starts. + */ +CURL_STATIC CURLcode Curl_pretransfer(struct SessionHandle *data) +{ + CURLcode result; + if(!data->change.url) { + /* we can't do anything without URL */ + failf(data, "No URL set!"); + return CURLE_URL_MALFORMAT; + } + + /* Init the SSL session ID cache here. We do it here since we want to do it + after the *_setopt() calls (that could specify the size of the cache) but + before any transfer takes place. */ + result = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions); + if(result) + return result; + + data->set.followlocation=0; /* reset the location-follow counter */ + data->state.this_is_a_follow = FALSE; /* reset this */ + data->state.errorbuf = FALSE; /* no error has occurred */ + data->state.httpversion = 0; /* don't assume any particular server version */ + + data->state.authproblem = FALSE; + data->state.authhost.want = data->set.httpauth; + data->state.authproxy.want = data->set.proxyauth; + Curl_safefree(data->info.wouldredirect); + data->info.wouldredirect = NULL; + + /* If there is a list of cookie files to read, do it now! */ + if(data->change.cookielist) + Curl_cookie_loadfiles(data); + + /* If there is a list of host pairs to deal with */ + if(data->change.resolve) + result = Curl_loadhostpairs(data); + + if(!result) { + /* Allow data->set.use_port to set which port to use. This needs to be + * disabled for example when we follow Location: headers to URLs using + * different ports! */ + data->state.allow_port = TRUE; + +#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) + /************************************************************* + * Tell signal handler to ignore SIGPIPE + *************************************************************/ + if(!data->set.no_signal) + data->state.prev_signal = signal(SIGPIPE, SIG_IGN); +#endif + + Curl_initinfo(data); /* reset session-specific information "variables" */ + Curl_pgrsResetTimesSizes(data); + Curl_pgrsStartNow(data); + + if(data->set.timeout) + Curl_expire(data, data->set.timeout); + + if(data->set.connecttimeout) + Curl_expire(data, data->set.connecttimeout); + + /* In case the handle is re-used and an authentication method was picked + in the session we need to make sure we only use the one(s) we now + consider to be fine */ + data->state.authhost.picked &= data->state.authhost.want; + data->state.authproxy.picked &= data->state.authproxy.want; + } + + return result; +} + +/* + * Curl_posttransfer() is called immediately after a transfer ends + */ +CURL_STATIC CURLcode Curl_posttransfer(struct SessionHandle *data) +{ +#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) + /* restore the signal handler for SIGPIPE before we get back */ + if(!data->set.no_signal) + signal(SIGPIPE, data->state.prev_signal); +#else + (void)data; /* unused parameter */ +#endif + + return CURLE_OK; +} + +#ifndef CURL_DISABLE_HTTP +/* + * strlen_url() returns the length of the given URL if the spaces within the + * URL were properly URL encoded. + */ +static size_t strlen_url(const char *url) +{ + const char *ptr; + size_t newlen=0; + bool left=TRUE; /* left side of the ? */ + + for(ptr=url; *ptr; ptr++) { + switch(*ptr) { + case '?': + left=FALSE; + /* fall through */ + default: + newlen++; + break; + case ' ': + if(left) + newlen+=3; + else + newlen++; + break; + } + } + return newlen; +} + +/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in + * the source URL accordingly. + */ +static void strcpy_url(char *output, const char *url) +{ + /* we must add this with whitespace-replacing */ + bool left=TRUE; + const char *iptr; + char *optr = output; + for(iptr = url; /* read from here */ + *iptr; /* until zero byte */ + iptr++) { + switch(*iptr) { + case '?': + left=FALSE; + /* fall through */ + default: + *optr++=*iptr; + break; + case ' ': + if(left) { + *optr++='%'; /* add a '%' */ + *optr++='2'; /* add a '2' */ + *optr++='0'; /* add a '0' */ + } + else + *optr++='+'; /* add a '+' here */ + break; + } + } + *optr=0; /* zero terminate output buffer */ + +} + +/* + * Returns true if the given URL is absolute (as opposed to relative) + */ +static bool is_absolute_url(const char *url) +{ + char prot[16]; /* URL protocol string storage */ + char letter; /* used for a silly sscanf */ + + return (2 == sscanf(url, "%15[^?&/:]://%c", prot, &letter)) ? TRUE : FALSE; +} + +/* + * Concatenate a relative URL to a base URL making it absolute. + * URL-encodes any spaces. + * The returned pointer must be freed by the caller unless NULL + * (returns NULL on out of memory). + */ +static char *concat_url(const char *base, const char *relurl) +{ + /*** + TRY to append this new path to the old URL + to the right of the host part. Oh crap, this is doomed to cause + problems in the future... + */ + char *newest; + char *protsep; + char *pathsep; + size_t newlen; + + const char *useurl = relurl; + size_t urllen; + + /* we must make our own copy of the URL to play with, as it may + point to read-only data */ + char *url_clone=strdup(base); + + if(!url_clone) + return NULL; /* skip out of this NOW */ + + /* protsep points to the start of the host name */ + protsep=strstr(url_clone, "//"); + if(!protsep) + protsep=url_clone; + else + protsep+=2; /* pass the slashes */ + + if('/' != relurl[0]) { + int level=0; + + /* First we need to find out if there's a ?-letter in the URL, + and cut it and the right-side of that off */ + pathsep = strchr(protsep, '?'); + if(pathsep) + *pathsep=0; + + /* we have a relative path to append to the last slash if there's one + available, or if the new URL is just a query string (starts with a + '?') we append the new one at the end of the entire currently worked + out URL */ + if(useurl[0] != '?') { + pathsep = strrchr(protsep, '/'); + if(pathsep) + *pathsep=0; + } + + /* Check if there's any slash after the host name, and if so, remember + that position instead */ + pathsep = strchr(protsep, '/'); + if(pathsep) + protsep = pathsep+1; + else + protsep = NULL; + + /* now deal with one "./" or any amount of "../" in the newurl + and act accordingly */ + + if((useurl[0] == '.') && (useurl[1] == '/')) + useurl+=2; /* just skip the "./" */ + + while((useurl[0] == '.') && + (useurl[1] == '.') && + (useurl[2] == '/')) { + level++; + useurl+=3; /* pass the "../" */ + } + + if(protsep) { + while(level--) { + /* cut off one more level from the right of the original URL */ + pathsep = strrchr(protsep, '/'); + if(pathsep) + *pathsep=0; + else { + *protsep=0; + break; + } + } + } + } + else { + /* We got a new absolute path for this server */ + + if((relurl[0] == '/') && (relurl[1] == '/')) { + /* the new URL starts with //, just keep the protocol part from the + original one */ + *protsep=0; + useurl = &relurl[2]; /* we keep the slashes from the original, so we + skip the new ones */ + } + else { + /* cut off the original URL from the first slash, or deal with URLs + without slash */ + pathsep = strchr(protsep, '/'); + if(pathsep) { + /* When people use badly formatted URLs, such as + "http://www.url.com?dir=/home/daniel" we must not use the first + slash, if there's a ?-letter before it! */ + char *sep = strchr(protsep, '?'); + if(sep && (sep < pathsep)) + pathsep = sep; + *pathsep=0; + } + else { + /* There was no slash. Now, since we might be operating on a badly + formatted URL, such as "http://www.url.com?id=2380" which doesn't + use a slash separator as it is supposed to, we need to check for a + ?-letter as well! */ + pathsep = strchr(protsep, '?'); + if(pathsep) + *pathsep=0; + } + } + } + + /* If the new part contains a space, this is a mighty stupid redirect + but we still make an effort to do "right". To the left of a '?' + letter we replace each space with %20 while it is replaced with '+' + on the right side of the '?' letter. + */ + newlen = strlen_url(useurl); + + urllen = strlen(url_clone); + + newest = malloc(urllen + 1 + /* possible slash */ + newlen + 1 /* zero byte */); + + if(!newest) { + free(url_clone); /* don't leak this */ + return NULL; + } + + /* copy over the root url part */ + memcpy(newest, url_clone, urllen); + + /* check if we need to append a slash */ + if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0])) + ; + else + newest[urllen++]='/'; + + /* then append the new piece on the right side */ + strcpy_url(&newest[urllen], useurl); + + free(url_clone); + + return newest; +} +#endif /* CURL_DISABLE_HTTP */ + +/* + * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string + * as given by the remote server and set up the new URL to request. + */ +CURLcode Curl_follow(struct SessionHandle *data, + char *newurl, /* this 'newurl' is the Location: string, + and it must be malloc()ed before passed + here */ + followtype type) /* see transfer.h */ +{ +#ifdef CURL_DISABLE_HTTP + (void)data; + (void)newurl; + (void)type; + /* Location: following will not happen when HTTP is disabled */ + return CURLE_TOO_MANY_REDIRECTS; +#else + + /* Location: redirect */ + bool disallowport = FALSE; + + if(type == FOLLOW_REDIR) { + if((data->set.maxredirs != -1) && + (data->set.followlocation >= data->set.maxredirs)) { + failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs); + return CURLE_TOO_MANY_REDIRECTS; + } + + /* mark the next request as a followed location: */ + data->state.this_is_a_follow = TRUE; + + data->set.followlocation++; /* count location-followers */ + + if(data->set.http_auto_referer) { + /* We are asked to automatically set the previous URL as the referer + when we get the next URL. We pick the ->url field, which may or may + not be 100% correct */ + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + + data->change.referer = strdup(data->change.url); + if(!data->change.referer) + return CURLE_OUT_OF_MEMORY; + data->change.referer_alloc = TRUE; /* yes, free this later */ + } + } + + if(!is_absolute_url(newurl)) { + /*** + *DANG* this is an RFC 2068 violation. The URL is supposed + to be absolute and this doesn't seem to be that! + */ + char *absolute = concat_url(data->change.url, newurl); + if(!absolute) + return CURLE_OUT_OF_MEMORY; + free(newurl); + newurl = absolute; + } + else { + /* This is an absolute URL, don't allow the custom port number */ + disallowport = TRUE; + + if(strchr(newurl, ' ')) { + /* This new URL contains at least one space, this is a mighty stupid + redirect but we still make an effort to do "right". */ + char *newest; + size_t newlen = strlen_url(newurl); + + newest = malloc(newlen+1); /* get memory for this */ + if(!newest) + return CURLE_OUT_OF_MEMORY; + strcpy_url(newest, newurl); /* create a space-free URL */ + + free(newurl); /* that was no good */ + newurl = newest; /* use this instead now */ + } + + } + + if(type == FOLLOW_FAKE) { + /* we're only figuring out the new url if we would've followed locations + but now we're done so we can get out! */ + data->info.wouldredirect = newurl; + return CURLE_OK; + } + + if(disallowport) + data->state.allow_port = FALSE; + + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + + data->change.url = newurl; + data->change.url_alloc = TRUE; + newurl = NULL; /* don't free! */ + + infof(data, "Issue another request to this URL: '%s'\n", data->change.url); + + /* + * We get here when the HTTP code is 300-399 (and 401). We need to perform + * differently based on exactly what return code there was. + * + * News from 7.10.6: we can also get here on a 401 or 407, in case we act on + * a HTTP (proxy-) authentication scheme other than Basic. + */ + switch(data->info.httpcode) { + /* 401 - Act on a WWW-Authenticate, we keep on moving and do the + Authorization: XXXX header in the HTTP request code snippet */ + /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the + Proxy-Authorization: XXXX header in the HTTP request code snippet */ + /* 300 - Multiple Choices */ + /* 306 - Not used */ + /* 307 - Temporary Redirect */ + default: /* for all above (and the unknown ones) */ + /* Some codes are explicitly mentioned since I've checked RFC2616 and they + * seem to be OK to POST to. + */ + break; + case 301: /* Moved Permanently */ + /* (quote from RFC7231, section 6.4.2) + * + * Note: For historical reasons, a user agent MAY change the request + * method from POST to GET for the subsequent request. If this + * behavior is undesired, the 307 (Temporary Redirect) status code + * can be used instead. + * + * ---- + * + * Many webservers expect this, so these servers often answers to a POST + * request with an error page. To be sure that libcurl gets the page that + * most user agents would get, libcurl has to force GET. + * + * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and + * can be overridden with CURLOPT_POSTREDIR. + */ + if((data->set.httpreq == HTTPREQ_POST + || data->set.httpreq == HTTPREQ_POST_FORM) + && !(data->set.keep_post & CURL_REDIR_POST_301)) { + infof(data, "Switch from POST to GET\n"); + data->set.httpreq = HTTPREQ_GET; + } + break; + case 302: /* Found */ + /* (quote from RFC7231, section 6.4.3) + * + * Note: For historical reasons, a user agent MAY change the request + * method from POST to GET for the subsequent request. If this + * behavior is undesired, the 307 (Temporary Redirect) status code + * can be used instead. + * + * ---- + * + * Many webservers expect this, so these servers often answers to a POST + * request with an error page. To be sure that libcurl gets the page that + * most user agents would get, libcurl has to force GET. + * + * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and + * can be overridden with CURLOPT_POSTREDIR. + */ + if((data->set.httpreq == HTTPREQ_POST + || data->set.httpreq == HTTPREQ_POST_FORM) + && !(data->set.keep_post & CURL_REDIR_POST_302)) { + infof(data, "Switch from POST to GET\n"); + data->set.httpreq = HTTPREQ_GET; + } + break; + + case 303: /* See Other */ + /* Disable both types of POSTs, unless the user explicitely + asks for POST after POST */ + if(data->set.httpreq != HTTPREQ_GET + && !(data->set.keep_post & CURL_REDIR_POST_303)) { + data->set.httpreq = HTTPREQ_GET; /* enforce GET request */ + infof(data, "Disables POST, goes with %s\n", + data->set.opt_no_body?"HEAD":"GET"); + } + break; + case 304: /* Not Modified */ + /* 304 means we did a conditional request and it was "Not modified". + * We shouldn't get any Location: header in this response! + */ + break; + case 305: /* Use Proxy */ + /* (quote from RFC2616, section 10.3.6): + * "The requested resource MUST be accessed through the proxy given + * by the Location field. The Location field gives the URI of the + * proxy. The recipient is expected to repeat this single request + * via the proxy. 305 responses MUST only be generated by origin + * servers." + */ + break; + } + Curl_pgrsTime(data, TIMER_REDIRECT); + Curl_pgrsResetTimesSizes(data); + + return CURLE_OK; +#endif /* CURL_DISABLE_HTTP */ +} + +CURL_STATIC CURLcode +Curl_reconnect_request(struct connectdata **connp) +{ + CURLcode result = CURLE_OK; + struct connectdata *conn = *connp; + struct SessionHandle *data = conn->data; + + /* This was a re-use of a connection and we got a write error in the + * DO-phase. Then we DISCONNECT this connection and have another attempt to + * CONNECT and then DO again! The retry cannot possibly find another + * connection to re-use, since we only keep one possible connection for + * each. */ + + infof(data, "Re-used connection seems dead, get a new one\n"); + + connclose(conn, "Reconnect dead connection"); /* enforce close */ + result = Curl_done(&conn, result, FALSE); /* we are so done with this */ + + /* conn may no longer be a good pointer, clear it to avoid mistakes by + parent functions */ + *connp = NULL; + + /* + * According to bug report #1330310. We need to check for CURLE_SEND_ERROR + * here as well. I figure this could happen when the request failed on a FTP + * connection and thus Curl_done() itself tried to use the connection + * (again). Slight Lack of feedback in the report, but I don't think this + * extra check can do much harm. + */ + if(!result || (CURLE_SEND_ERROR == result)) { + bool async; + bool protocol_done = TRUE; + + /* Now, redo the connect and get a new connection */ + result = Curl_connect(data, connp, &async, &protocol_done); + if(!result) { + /* We have connected or sent away a name resolve query fine */ + + conn = *connp; /* setup conn to again point to something nice */ + if(async) { + /* Now, if async is TRUE here, we need to wait for the name + to resolve */ + result = Curl_resolver_wait_resolv(conn, NULL); + if(result) + return result; + + /* Resolved, continue with the connection */ + result = Curl_async_resolved(conn, &protocol_done); + if(result) + return result; + } + } + } + + return result; +} + +/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted. + + NOTE: that the *url is malloc()ed. */ +CURL_STATIC CURLcode Curl_retry_request(struct connectdata *conn, + char **url) +{ + struct SessionHandle *data = conn->data; + + *url = NULL; + + /* if we're talking upload, we can't do the checks below, unless the protocol + is HTTP as when uploading over HTTP we will still get a response */ + if(data->set.upload && + !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP))) + return CURLE_OK; + + if((data->req.bytecount + data->req.headerbytecount == 0) && + conn->bits.reuse && + !data->set.opt_no_body && + (data->set.rtspreq != RTSPREQ_RECEIVE)) { + /* We got no data, we attempted to re-use a connection and yet we want a + "body". This might happen if the connection was left alive when we were + done using it before, but that was closed when we wanted to read from + it again. Bad luck. Retry the same request on a fresh connect! */ + infof(conn->data, "Connection died, retrying a fresh connect\n"); + *url = strdup(conn->data->change.url); + if(!*url) + return CURLE_OUT_OF_MEMORY; + + connclose(conn, "retry"); /* close this connection */ + conn->bits.retry = TRUE; /* mark this as a connection we're about + to retry. Marking it this way should + prevent i.e HTTP transfers to return + error just because nothing has been + transferred! */ + + + if(conn->handler->protocol&PROTO_FAMILY_HTTP) { + struct HTTP *http = data->req.protop; + if(http->writebytecount) + return Curl_readrewind(conn); + } + } + return CURLE_OK; +} + +/* + * Curl_setup_transfer() is called to setup some basic properties for the + * upcoming transfer. + */ +CURL_STATIC void +Curl_setup_transfer( + struct connectdata *conn, /* connection data */ + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + curl_off_t *bytecountp, /* return number of bytes read or NULL */ + int writesockindex, /* socket index to write to, it may very well be + the same we read from. -1 disables */ + curl_off_t *writecountp /* return number of bytes written or NULL */ + ) +{ + struct SessionHandle *data; + struct SingleRequest *k; + + DEBUGASSERT(conn != NULL); + + data = conn->data; + k = &data->req; + + DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); + + /* now copy all input parameters */ + conn->sockfd = sockindex == -1 ? + CURL_SOCKET_BAD : conn->sock[sockindex]; + conn->writesockfd = writesockindex == -1 ? + CURL_SOCKET_BAD:conn->sock[writesockindex]; + k->getheader = getheader; + + k->size = size; + k->bytecountp = bytecountp; + k->writebytecountp = writecountp; + + /* The code sequence below is placed in this function just because all + necessary input is not always known in do_complete() as this function may + be called after that */ + + if(!k->getheader) { + k->header = FALSE; + if(size > 0) + Curl_pgrsSetDownloadSize(data, size); + } + /* we want header and/or body, if neither then don't do this! */ + if(k->getheader || !data->set.opt_no_body) { + + if(conn->sockfd != CURL_SOCKET_BAD) + k->keepon |= KEEP_RECV; + + if(conn->writesockfd != CURL_SOCKET_BAD) { + struct HTTP *http = data->req.protop; + /* HTTP 1.1 magic: + + Even if we require a 100-return code before uploading data, we might + need to write data before that since the REQUEST may not have been + finished sent off just yet. + + Thus, we must check if the request has been sent before we set the + state info where we wait for the 100-return code + */ + if((data->state.expect100header) && + (conn->handler->protocol&PROTO_FAMILY_HTTP) && + (http->sending == HTTPSEND_BODY)) { + /* wait with write until we either got 100-continue or a timeout */ + k->exp100 = EXP100_AWAITING_CONTINUE; + k->start100 = Curl_tvnow(); + + /* Set a timeout for the multi interface. Add the inaccuracy margin so + that we don't fire slightly too early and get denied to run. */ + Curl_expire(data, data->set.expect_100_timeout); + } + else { + if(data->state.expect100header) + /* when we've sent off the rest of the headers, we must await a + 100-continue but first finish sending the request */ + k->exp100 = EXP100_SENDING_REQUEST; + + /* enable the write bit when we're not waiting for continue */ + k->keepon |= KEEP_SEND; + } + } /* if(conn->writesockfd != CURL_SOCKET_BAD) */ + } /* if(k->getheader || !data->set.opt_no_body) */ + +} diff --git a/libcurl/src/lib/transfer.h b/libcurl/src/lib/transfer.h new file mode 100644 index 0000000..6b0d9f9 --- /dev/null +++ b/libcurl/src/lib/transfer.h @@ -0,0 +1,70 @@ +#ifndef HEADER_CURL_TRANSFER_H +#define HEADER_CURL_TRANSFER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURL_STATIC CURLcode Curl_pretransfer(struct SessionHandle *data); +CURL_STATIC CURLcode Curl_second_connect(struct connectdata *conn); +CURL_STATIC CURLcode Curl_posttransfer(struct SessionHandle *data); + +typedef enum { + FOLLOW_NONE, /* not used within the function, just a placeholder to + allow initing to this */ + FOLLOW_FAKE, /* only records stuff, not actually following */ + FOLLOW_RETRY, /* set if this is a request retry as opposed to a real + redirect following */ + FOLLOW_REDIR, /* a full true redirect */ + FOLLOW_LAST /* never used */ +} followtype; + +CURL_STATIC CURLcode Curl_follow(struct SessionHandle *data, char *newurl, + followtype type); + + +CURL_STATIC CURLcode Curl_readwrite(struct connectdata *conn, bool *done); +CURL_STATIC int Curl_single_getsock(const struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +CURL_STATIC CURLcode Curl_readrewind(struct connectdata *conn); +CURL_STATIC CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp); +CURL_STATIC CURLcode Curl_reconnect_request(struct connectdata **connp); +CURL_STATIC CURLcode Curl_retry_request(struct connectdata *conn, char **url); +CURL_STATIC bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc); + +/* This sets up a forthcoming transfer */ +CURL_STATIC void +Curl_setup_transfer (struct connectdata *data, + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + curl_off_t *bytecountp, /* return number of bytes read */ + int writesockindex, /* socket index to write to, it may + very well be the same we read from. + -1 disables */ + curl_off_t *writecountp /* return number of bytes written */ +); + +CURL_STATIC long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps, + int pkt_size); + +#endif /* HEADER_CURL_TRANSFER_H */ + diff --git a/libcurl/src/lib/url.c b/libcurl/src/lib/url.c new file mode 100644 index 0000000..9c3c59c --- /dev/null +++ b/libcurl/src/lib/url.c @@ -0,0 +1,6164 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + +#ifndef HAVE_SOCKET +#error "We can't compile without socket() support!" +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + +#ifdef USE_LIBIDN +#include +#include +#include +#ifdef HAVE_IDN_FREE_H +#include +#else +/* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */ +void idn_free (void *ptr); +#endif +#ifndef HAVE_IDN_FREE +/* if idn_free() was not found in this version of libidn use free() instead */ +#define idn_free(x) (free)(x) +#endif +#elif defined(USE_WIN32_IDN) +/* prototype for curl_win32_idn_to_ascii() */ +int curl_win32_idn_to_ascii(const char *in, char **out); +#endif /* USE_LIBIDN */ + +#include "urldata.h" +#include "netrc.h" + +#include "formdata.h" +#include "vtls/vtls.h" +#include "hostip.h" +#include "transfer.h" +#include "sendf.h" +#include "progress.h" +#include "cookie.h" +#include "strequal.h" +#include "strerror.h" +#include "escape.h" +#include "strtok.h" +#include "share.h" +#include "content_encoding.h" +#include "http_digest.h" +#include "http_negotiate.h" +#include "select.h" +#include "multiif.h" +#include "easyif.h" +#include "speedcheck.h" +#include "rawstr.h" +#include "warnless.h" +#include "non-ascii.h" +#include "inet_pton.h" + +/* And now for the protocols */ +#include "ftp.h" +#include "dict.h" +#include "telnet.h" +#include "tftp.h" +#include "http.h" +#include "file.h" +#include "curl_ldap.h" +#include "ssh.h" +#include "imap.h" +#include "url.h" +#include "connect.h" +#include "inet_ntop.h" +#include "curl_ntlm.h" +#include "curl_ntlm_wb.h" +#include "socks.h" +#include "curl_rtmp.h" +#include "gopher.h" +#include "http_proxy.h" +#include "bundles.h" +#include "conncache.h" +#include "multihandle.h" +#include "pipeline.h" +#include "dotdot.h" +#include "strdup.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* Local static prototypes */ +static struct connectdata * +find_oldest_idle_connection(struct SessionHandle *data); +static struct connectdata * +find_oldest_idle_connection_in_bundle(struct SessionHandle *data, + struct connectbundle *bundle); +static void conn_free(struct connectdata *conn); +static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke); +static CURLcode do_init(struct connectdata *conn); +static CURLcode parse_url_login(struct SessionHandle *data, + struct connectdata *conn, + char **userptr, char **passwdptr, + char **optionsptr); +static CURLcode parse_login_details(const char *login, const size_t len, + char **userptr, char **passwdptr, + char **optionsptr); +/* + * Protocol table. + */ + +static const struct Curl_handler * const protocols[] = { + +#ifndef CURL_DISABLE_HTTP + &Curl_handler_http, +#endif + +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_https, +#endif + +#ifndef CURL_DISABLE_FTP + &Curl_handler_ftp, +#endif + +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + &Curl_handler_ftps, +#endif + +#ifndef CURL_DISABLE_TELNET + &Curl_handler_telnet, +#endif + +#ifndef CURL_DISABLE_DICT + &Curl_handler_dict, +#endif + +#ifndef CURL_DISABLE_LDAP + &Curl_handler_ldap, +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + &Curl_handler_ldaps, +#endif +#endif + +#ifndef CURL_DISABLE_FILE + &Curl_handler_file, +#endif + +#ifndef CURL_DISABLE_TFTP + &Curl_handler_tftp, +#endif + +#ifdef USE_LIBSSH2 + &Curl_handler_scp, + &Curl_handler_sftp, +#endif + +#ifndef CURL_DISABLE_IMAP + &Curl_handler_imap, +#ifdef USE_SSL + &Curl_handler_imaps, +#endif +#endif + +#ifndef CURL_DISABLE_POP3 + &Curl_handler_pop3, +#ifdef USE_SSL + &Curl_handler_pop3s, +#endif +#endif + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) && \ + (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)) + &Curl_handler_smb, +#ifdef USE_SSL + &Curl_handler_smbs, +#endif +#endif + +#ifndef CURL_DISABLE_SMTP + &Curl_handler_smtp, +#ifdef USE_SSL + &Curl_handler_smtps, +#endif +#endif + +#ifndef CURL_DISABLE_RTSP + &Curl_handler_rtsp, +#endif + +#ifndef CURL_DISABLE_GOPHER + &Curl_handler_gopher, +#endif + +#ifdef USE_LIBRTMP + &Curl_handler_rtmp, + &Curl_handler_rtmpt, + &Curl_handler_rtmpe, + &Curl_handler_rtmpte, + &Curl_handler_rtmps, + &Curl_handler_rtmpts, +#endif + + (struct Curl_handler *) NULL +}; + +/* + * Dummy handler for undefined protocol schemes. + */ + +static const struct Curl_handler Curl_handler_dummy = { + "", /* scheme */ + ZERO_NULL, /* setup_connection */ + ZERO_NULL, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + 0, /* defport */ + 0, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +CURL_STATIC void Curl_freeset(struct SessionHandle *data) +{ + /* Free all dynamic strings stored in the data->set substructure. */ + enum dupstring i; + for(i=(enum dupstring)0; i < STRING_LAST; i++) { + Curl_safefree(data->set.str[i]); + } + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + data->change.referer = NULL; + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + data->change.url = NULL; +} + +static CURLcode setstropt(char **charp, char *s) +{ + /* Release the previous storage at `charp' and replace by a dynamic storage + copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */ + + Curl_safefree(*charp); + + if(s) { + s = strdup(s); + + if(!s) + return CURLE_OUT_OF_MEMORY; + + *charp = s; + } + + return CURLE_OK; +} + +static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) +{ + CURLcode result = CURLE_OK; + char *user = NULL; + char *passwd = NULL; + + /* Parse the login details if specified. It not then we treat NULL as a hint + to clear the existing data */ + if(option) { + result = parse_login_details(option, strlen(option), + (userp ? &user : NULL), + (passwdp ? &passwd : NULL), + NULL); + } + + if(!result) { + /* Store the username part of option if required */ + if(userp) { + if(!user && option && option[0] == ':') { + /* Allocate an empty string instead of returning NULL as user name */ + user = strdup(""); + if(!user) + result = CURLE_OUT_OF_MEMORY; + } + + Curl_safefree(*userp); + *userp = user; + } + + /* Store the password part of option if required */ + if(passwdp) { + Curl_safefree(*passwdp); + *passwdp = passwd; + } + } + + return result; +} + +CURL_STATIC CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src) +{ + CURLcode result = CURLE_OK; + enum dupstring i; + + /* Copy src->set into dst->set first, then deal with the strings + afterwards */ + dst->set = src->set; + + /* clear all string pointers first */ + memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); + + /* duplicate all strings */ + for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { + result = setstropt(&dst->set.str[i], src->set.str[i]); + if(result) + return result; + } + + /* duplicate memory areas pointed to */ + i = STRING_COPYPOSTFIELDS; + if(src->set.postfieldsize && src->set.str[i]) { + /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ + dst->set.str[i] = Curl_memdup(src->set.str[i], + curlx_sotouz(src->set.postfieldsize)); + if(!dst->set.str[i]) + return CURLE_OUT_OF_MEMORY; + /* point to the new copy */ + dst->set.postfields = dst->set.str[i]; + } + + return CURLE_OK; +} + +/* + * This is the internal function curl_easy_cleanup() calls. This should + * cleanup and free all resources associated with this sessionhandle. + * + * NOTE: if we ever add something that attempts to write to a socket or + * similar here, we must ignore SIGPIPE first. It is currently only done + * when curl_easy_perform() is invoked. + */ + +CURL_STATIC CURLcode Curl_close(struct SessionHandle *data) +{ + struct Curl_multi *m; + + if(!data) + return CURLE_OK; + + Curl_expire(data, 0); /* shut off timers */ + + m = data->multi; + + if(m) + /* This handle is still part of a multi handle, take care of this first + and detach this handle from there. */ + curl_multi_remove_handle(data->multi, data); + + if(data->multi_easy) + /* when curl_easy_perform() is used, it creates its own multi handle to + use and this is the one */ + curl_multi_cleanup(data->multi_easy); + + /* Destroy the timeout list that is held in the easy handle. It is + /normally/ done by curl_multi_remove_handle() but this is "just in + case" */ + if(data->state.timeoutlist) { + Curl_llist_destroy(data->state.timeoutlist, NULL); + data->state.timeoutlist = NULL; + } + + data->magic = 0; /* force a clear AFTER the possibly enforced removal from + the multi handle, since that function uses the magic + field! */ + + if(data->state.rangestringalloc) + free(data->state.range); + + /* Free the pathbuffer */ + Curl_safefree(data->state.pathbuffer); + data->state.path = NULL; + + /* freed here just in case DONE wasn't called */ + Curl_free_request_state(data); + + /* Close down all open SSL info and sessions */ + Curl_ssl_close_all(data); + Curl_safefree(data->state.first_host); + Curl_safefree(data->state.scratch); + Curl_ssl_free_certinfo(data); + + /* Cleanup possible redirect junk */ + free(data->req.newurl); + data->req.newurl = NULL; + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + data->change.referer = NULL; + + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + data->change.url = NULL; + + Curl_safefree(data->state.headerbuff); + + Curl_flush_cookies(data, 1); + + Curl_digest_cleanup(data); + + Curl_safefree(data->info.contenttype); + Curl_safefree(data->info.wouldredirect); + + /* this destroys the channel and we cannot use it anymore after this */ + Curl_resolver_cleanup(data->state.resolver); + + Curl_convert_close(data); + + /* No longer a dirty share, if it exists */ + if(data->share) { + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + data->share->dirty--; + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + } + + Curl_freeset(data); + free(data); + return CURLE_OK; +} + +/* + * Initialize the UserDefined fields within a SessionHandle. + * This may be safely called on a new or existing SessionHandle. + */ +CURL_STATIC CURLcode Curl_init_userdefined(struct UserDefined *set) +{ + CURLcode result = CURLE_OK; + + set->out = stdout; /* default output to stdout */ + set->in = stdin; /* default input from stdin */ + set->err = stderr; /* default stderr to stderr */ + + /* use fwrite as default function to store output */ + set->fwrite_func = (curl_write_callback)fwrite; + + /* use fread as default function to read input */ + set->fread_func = (curl_read_callback)fread; + set->is_fread_set = 0; + set->is_fwrite_set = 0; + + set->seek_func = ZERO_NULL; + set->seek_client = ZERO_NULL; + + /* conversion callbacks for non-ASCII hosts */ + set->convfromnetwork = ZERO_NULL; + set->convtonetwork = ZERO_NULL; + set->convfromutf8 = ZERO_NULL; + + set->filesize = -1; /* we don't know the size */ + set->postfieldsize = -1; /* unknown size */ + set->maxredirs = -1; /* allow any amount by default */ + + set->httpreq = HTTPREQ_GET; /* Default HTTP request */ + set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */ + set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ + set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */ + set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */ + set->ftp_filemethod = FTPFILE_MULTICWD; + + set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ + + /* Set the default size of the SSL session ID cache */ + set->ssl.max_ssl_sessions = 5; + + set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */ + set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ + set->httpauth = CURLAUTH_BASIC; /* defaults to basic */ + set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */ + + /* make libcurl quiet by default: */ + set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */ + + /* + * libcurl 7.10 introduced SSL verification *by default*! This needs to be + * switched off unless wanted. + */ + set->ssl.verifypeer = TRUE; + set->ssl.verifyhost = TRUE; +#ifdef USE_TLS_SRP + set->ssl.authtype = CURL_TLSAUTH_NONE; +#endif + set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth + type */ + set->ssl.sessionid = TRUE; /* session ID caching enabled by default */ + + set->new_file_perms = 0644; /* Default permissions */ + set->new_directory_perms = 0755; /* Default permissions */ + + /* for the *protocols fields we don't use the CURLPROTO_ALL convenience + define since we internally only use the lower 16 bits for the passed + in bitmask to not conflict with the private bits */ + set->allowed_protocols = CURLPROTO_ALL; + set->redir_protocols = CURLPROTO_ALL & /* All except FILE, SCP and SMB */ + ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB | + CURLPROTO_SMBS); + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + /* + * disallow unprotected protection negotiation NEC reference implementation + * seem not to follow rfc1961 section 4.3/4.4 + */ + set->socks5_gssapi_nec = FALSE; + /* set default GSS-API service name */ + result = setstropt(&set->str[STRING_SOCKS5_GSSAPI_SERVICE], + (char *) CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE); + if(result) + return result; +#endif + + /* This is our preferred CA cert bundle/path since install time */ +#if defined(CURL_CA_BUNDLE) + result = setstropt(&set->str[STRING_SSL_CAFILE], (char *) CURL_CA_BUNDLE); + if(result) + return result; +#endif +#if defined(CURL_CA_PATH) + result = setstropt(&set->str[STRING_SSL_CAPATH], (char *) CURL_CA_PATH); + if(result) + return result; +#endif + + set->wildcardmatch = FALSE; + set->chunk_bgn = ZERO_NULL; + set->chunk_end = ZERO_NULL; + + /* tcp keepalives are disabled by default, but provide reasonable values for + * the interval and idle times. + */ + set->tcp_keepalive = FALSE; + set->tcp_keepintvl = 60; + set->tcp_keepidle = 60; + + set->ssl_enable_npn = TRUE; + set->ssl_enable_alpn = TRUE; + + set->expect_100_timeout = 1000L; /* Wait for a second by default. */ + set->sep_headers = TRUE; /* separated header lists by default */ + return result; +} + +/** + * Curl_open() + * + * @param curl is a pointer to a sessionhandle pointer that gets set by this + * function. + * @return CURLcode + */ + +CURL_STATIC CURLcode Curl_open(struct SessionHandle **curl) +{ + CURLcode result; + struct SessionHandle *data; + + /* Very simple start-up: alloc the struct, init it with zeroes and return */ + data = calloc(1, sizeof(struct SessionHandle)); + if(!data) { + /* this is a very serious error */ + DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n")); + return CURLE_OUT_OF_MEMORY; + } + + data->magic = CURLEASY_MAGIC_NUMBER; + + result = Curl_resolver_init(&data->state.resolver); + if(result) { + DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); + free(data); + return result; + } + + /* We do some initial setup here, all those fields that can't be just 0 */ + + data->state.headerbuff = malloc(HEADERSIZE); + if(!data->state.headerbuff) { + DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + else { + result = Curl_init_userdefined(&data->set); + + data->state.headersize=HEADERSIZE; + + Curl_convert_init(data); + + /* most recent connection is not yet defined */ + data->state.lastconnect = NULL; + + data->progress.flags |= PGRS_HIDE; + data->state.current_speed = -1; /* init to negative == impossible */ + + data->wildcard.state = CURLWC_INIT; + data->wildcard.filelist = NULL; + data->set.fnmatch = ZERO_NULL; + data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */ + } + + if(result) { + Curl_resolver_cleanup(data->state.resolver); + free(data->state.headerbuff); + Curl_freeset(data); + free(data); + data = NULL; + } + else + *curl = data; + + return result; +} + +CURL_STATIC CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, + va_list param) +{ + char *argptr; + CURLcode result = CURLE_OK; + long arg; +#ifndef CURL_DISABLE_HTTP + curl_off_t bigsize; +#endif + + switch(option) { + case CURLOPT_DNS_CACHE_TIMEOUT: + data->set.dns_cache_timeout = va_arg(param, long); + break; + case CURLOPT_DNS_USE_GLOBAL_CACHE: + /* remember we want this enabled */ + arg = va_arg(param, long); + data->set.global_dns_cache = (0 != arg)?TRUE:FALSE; + break; + case CURLOPT_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection */ + result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST], + va_arg(param, char *)); + break; + + case CURLOPT_RANDOM_FILE: + /* + * This is the path name to a file that contains random data to seed + * the random SSL stuff with. The file is only used for reading. + */ + result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE], + va_arg(param, char *)); + break; + case CURLOPT_EGDSOCKET: + /* + * The Entropy Gathering Daemon socket pathname + */ + result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET], + va_arg(param, char *)); + break; + case CURLOPT_MAXCONNECTS: + /* + * Set the absolute number of maximum simultaneous alive connection that + * libcurl is allowed to have. + */ + data->set.maxconnects = va_arg(param, long); + break; + case CURLOPT_FORBID_REUSE: + /* + * When this transfer is done, it must not be left to be reused by a + * subsequent transfer but shall be closed immediately. + */ + data->set.reuse_forbid = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_FRESH_CONNECT: + /* + * This transfer shall not use a previously cached connection but + * should be made with a fresh new connect! + */ + data->set.reuse_fresh = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_VERBOSE: + /* + * Verbose means infof() calls that give a lot of information about + * the connection and transfer procedures as well as internal choices. + */ + data->set.verbose = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_HEADER: + /* + * Set to include the header in the general data output stream. + */ + data->set.include_header = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_NOPROGRESS: + /* + * Shut off the internal supported progress meter + */ + data->set.hide_progress = (0 != va_arg(param, long))?TRUE:FALSE; + if(data->set.hide_progress) + data->progress.flags |= PGRS_HIDE; + else + data->progress.flags &= ~PGRS_HIDE; + break; + case CURLOPT_NOBODY: + /* + * Do not include the body part in the output data stream. + */ + data->set.opt_no_body = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_FAILONERROR: + /* + * Don't output the >=400 error code HTML-page, but instead only + * return error. + */ + data->set.http_fail_on_error = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_UPLOAD: + case CURLOPT_PUT: + /* + * We want to sent data to the remote host. If this is HTTP, that equals + * using the PUT request. + */ + data->set.upload = (0 != va_arg(param, long))?TRUE:FALSE; + if(data->set.upload) { + /* If this is HTTP, PUT is what's needed to "upload" */ + data->set.httpreq = HTTPREQ_PUT; + data->set.opt_no_body = FALSE; /* this is implied */ + } + else + /* In HTTP, the opposite of upload is GET (unless NOBODY is true as + then this can be changed to HEAD later on) */ + data->set.httpreq = HTTPREQ_GET; + break; + case CURLOPT_FILETIME: + /* + * Try to get the file time of the remote document. The time will + * later (possibly) become available using curl_easy_getinfo(). + */ + data->set.get_filetime = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_FTP_CREATE_MISSING_DIRS: + /* + * An FTP option that modifies an upload to create missing directories on + * the server. + */ + switch(va_arg(param, long)) { + case 0: + data->set.ftp_create_missing_dirs = 0; + break; + case 1: + data->set.ftp_create_missing_dirs = 1; + break; + case 2: + data->set.ftp_create_missing_dirs = 2; + break; + default: + /* reserve other values for future use */ + result = CURLE_UNKNOWN_OPTION; + break; + } + break; + case CURLOPT_SERVER_RESPONSE_TIMEOUT: + /* + * Option that specifies how quickly an server response must be obtained + * before it is considered failure. For pingpong protocols. + */ + data->set.server_response_timeout = va_arg( param , long ) * 1000; + break; + case CURLOPT_TFTP_BLKSIZE: + /* + * TFTP option that specifies the block size to use for data transmission + */ + data->set.tftp_blksize = va_arg(param, long); + break; + case CURLOPT_DIRLISTONLY: + /* + * An option that changes the command to one that asks for a list + * only, no file info details. + */ + data->set.ftp_list_only = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_APPEND: + /* + * We want to upload and append to an existing file. + */ + data->set.ftp_append = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_FTP_FILEMETHOD: + /* + * How do access files over FTP. + */ + data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long); + break; + case CURLOPT_NETRC: + /* + * Parse the $HOME/.netrc file + */ + data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long); + break; + case CURLOPT_NETRC_FILE: + /* + * Use this file instead of the $HOME/.netrc file + */ + result = setstropt(&data->set.str[STRING_NETRC_FILE], + va_arg(param, char *)); + break; + case CURLOPT_TRANSFERTEXT: + /* + * This option was previously named 'FTPASCII'. Renamed to work with + * more protocols than merely FTP. + * + * Transfer using ASCII (instead of BINARY). + */ + data->set.prefer_ascii = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_TIMECONDITION: + /* + * Set HTTP time condition. This must be one of the defines in the + * curl/curl.h header file. + */ + data->set.timecondition = (curl_TimeCond)va_arg(param, long); + break; + case CURLOPT_TIMEVALUE: + /* + * This is the value to compare with the remote document with the + * method set with CURLOPT_TIMECONDITION + */ + data->set.timevalue = (time_t)va_arg(param, long); + break; + case CURLOPT_SSLVERSION: + /* + * Set explicit SSL version to try to connect with, as some SSL + * implementations are lame. + */ +#ifdef USE_SSL + data->set.ssl.version = va_arg(param, long); +#else + result = CURLE_UNKNOWN_OPTION; +#endif + break; + +#ifndef CURL_DISABLE_HTTP + case CURLOPT_AUTOREFERER: + /* + * Switch on automatic referer that gets set if curl follows locations. + */ + data->set.http_auto_referer = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_ACCEPT_ENCODING: + /* + * String to use at the value of Accept-Encoding header. + * + * If the encoding is set to "" we use an Accept-Encoding header that + * encompasses all the encodings we support. + * If the encoding is set to NULL we don't send an Accept-Encoding header + * and ignore an received Content-Encoding header. + * + */ + argptr = va_arg(param, char *); + result = setstropt(&data->set.str[STRING_ENCODING], + (argptr && !*argptr)? + (char *) ALL_CONTENT_ENCODINGS: argptr); + break; + + case CURLOPT_TRANSFER_ENCODING: + data->set.http_transfer_encoding = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_FOLLOWLOCATION: + /* + * Follow Location: header hints on a HTTP-server. + */ + data->set.http_follow_location = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_UNRESTRICTED_AUTH: + /* + * Send authentication (user+password) when following locations, even when + * hostname changed. + */ + data->set.http_disable_hostname_check_before_authentication = + (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_MAXREDIRS: + /* + * The maximum amount of hops you allow curl to follow Location: + * headers. This should mostly be used to detect never-ending loops. + */ + data->set.maxredirs = va_arg(param, long); + break; + + case CURLOPT_POSTREDIR: + { + /* + * Set the behaviour of POST when redirecting + * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302 + * CURL_REDIR_POST_301 - POST is kept as POST after 301 + * CURL_REDIR_POST_302 - POST is kept as POST after 302 + * CURL_REDIR_POST_303 - POST is kept as POST after 303 + * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303 + * other - POST is kept as POST after 301 and 302 + */ + int postRedir = curlx_sltosi(va_arg(param, long)); + data->set.keep_post = postRedir & CURL_REDIR_POST_ALL; + } + break; + + case CURLOPT_POST: + /* Does this option serve a purpose anymore? Yes it does, when + CURLOPT_POSTFIELDS isn't used and the POST data is read off the + callback! */ + if(va_arg(param, long)) { + data->set.httpreq = HTTPREQ_POST; + data->set.opt_no_body = FALSE; /* this is implied */ + } + else + data->set.httpreq = HTTPREQ_GET; + break; + + case CURLOPT_COPYPOSTFIELDS: + /* + * A string with POST data. Makes curl HTTP POST. Even if it is NULL. + * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to + * CURLOPT_COPYPOSTFIELDS and not altered later. + */ + argptr = va_arg(param, char *); + + if(!argptr || data->set.postfieldsize == -1) + result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr); + else { + /* + * Check that requested length does not overflow the size_t type. + */ + + if((data->set.postfieldsize < 0) || + ((sizeof(curl_off_t) != sizeof(size_t)) && + (data->set.postfieldsize > (curl_off_t)((size_t)-1)))) + result = CURLE_OUT_OF_MEMORY; + else { + char * p; + + (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + + /* Allocate even when size == 0. This satisfies the need of possible + later address compare to detect the COPYPOSTFIELDS mode, and + to mark that postfields is used rather than read function or + form data. + */ + p = malloc((size_t)(data->set.postfieldsize? + data->set.postfieldsize:1)); + + if(!p) + result = CURLE_OUT_OF_MEMORY; + else { + if(data->set.postfieldsize) + memcpy(p, argptr, (size_t)data->set.postfieldsize); + + data->set.str[STRING_COPYPOSTFIELDS] = p; + } + } + } + + data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS]; + data->set.httpreq = HTTPREQ_POST; + break; + + case CURLOPT_POSTFIELDS: + /* + * Like above, but use static data instead of copying it. + */ + data->set.postfields = va_arg(param, void *); + /* Release old copied data. */ + (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.httpreq = HTTPREQ_POST; + break; + + case CURLOPT_POSTFIELDSIZE: + /* + * The size of the POSTFIELD data to prevent libcurl to do strlen() to + * figure it out. Enables binary posts. + */ + bigsize = va_arg(param, long); + + if(data->set.postfieldsize < bigsize && + data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { + /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ + (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.postfields = NULL; + } + + data->set.postfieldsize = bigsize; + break; + + case CURLOPT_POSTFIELDSIZE_LARGE: + /* + * The size of the POSTFIELD data to prevent libcurl to do strlen() to + * figure it out. Enables binary posts. + */ + bigsize = va_arg(param, curl_off_t); + + if(data->set.postfieldsize < bigsize && + data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { + /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ + (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.postfields = NULL; + } + + data->set.postfieldsize = bigsize; + break; + + case CURLOPT_HTTPPOST: + /* + * Set to make us do HTTP POST + */ + data->set.httppost = va_arg(param, struct curl_httppost *); + data->set.httpreq = HTTPREQ_POST_FORM; + data->set.opt_no_body = FALSE; /* this is implied */ + break; + + case CURLOPT_REFERER: + /* + * String to set in the HTTP Referer: field. + */ + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + result = setstropt(&data->set.str[STRING_SET_REFERER], + va_arg(param, char *)); + data->change.referer = data->set.str[STRING_SET_REFERER]; + break; + + case CURLOPT_USERAGENT: + /* + * String to use in the HTTP User-Agent field + */ + result = setstropt(&data->set.str[STRING_USERAGENT], + va_arg(param, char *)); + break; + + case CURLOPT_HTTPHEADER: + /* + * Set a list with HTTP headers to use (or replace internals with) + */ + data->set.headers = va_arg(param, struct curl_slist *); + break; + + case CURLOPT_PROXYHEADER: + /* + * Set a list with proxy headers to use (or replace internals with) + * + * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a + * long time we remain doing it this way until CURLOPT_PROXYHEADER is + * used. As soon as this option has been used, if set to anything but + * NULL, custom headers for proxies are only picked from this list. + * + * Set this option to NULL to restore the previous behavior. + */ + data->set.proxyheaders = va_arg(param, struct curl_slist *); + break; + + case CURLOPT_HEADEROPT: + /* + * Set header option. + */ + arg = va_arg(param, long); + data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE; + break; + + case CURLOPT_HTTP200ALIASES: + /* + * Set a list of aliases for HTTP 200 in response header + */ + data->set.http200aliases = va_arg(param, struct curl_slist *); + break; + +#if !defined(CURL_DISABLE_COOKIES) + case CURLOPT_COOKIE: + /* + * Cookie string to send to the remote server in the request. + */ + result = setstropt(&data->set.str[STRING_COOKIE], + va_arg(param, char *)); + break; + + case CURLOPT_COOKIEFILE: + /* + * Set cookie file to read and parse. Can be used multiple times. + */ + argptr = (char *)va_arg(param, void *); + if(argptr) { + struct curl_slist *cl; + /* append the cookie file name to the list of file names, and deal with + them later */ + cl = curl_slist_append(data->change.cookielist, argptr); + if(!cl) { + curl_slist_free_all(data->change.cookielist); + data->change.cookielist = NULL; + return CURLE_OUT_OF_MEMORY; + } + data->change.cookielist = cl; /* store the list for later use */ + } + break; + + case CURLOPT_COOKIEJAR: + /* + * Set cookie file name to dump all cookies to when we're done. + */ + { + struct CookieInfo *newcookies; + result = setstropt(&data->set.str[STRING_COOKIEJAR], + va_arg(param, char *)); + + /* + * Activate the cookie parser. This may or may not already + * have been made. + */ + newcookies = Curl_cookie_init(data, NULL, data->cookies, + data->set.cookiesession); + if(!newcookies) + result = CURLE_OUT_OF_MEMORY; + data->cookies = newcookies; + } + break; + + case CURLOPT_COOKIESESSION: + /* + * Set this option to TRUE to start a new "cookie session". It will + * prevent the forthcoming read-cookies-from-file actions to accept + * cookies that are marked as being session cookies, as they belong to a + * previous session. + * + * In the original Netscape cookie spec, "session cookies" are cookies + * with no expire date set. RFC2109 describes the same action if no + * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds + * a 'Discard' action that can enforce the discard even for cookies that + * have a Max-Age. + * + * We run mostly with the original cookie spec, as hardly anyone implements + * anything else. + */ + data->set.cookiesession = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_COOKIELIST: + argptr = va_arg(param, char *); + + if(argptr == NULL) + break; + + if(Curl_raw_equal(argptr, "ALL")) { + /* clear all cookies */ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_clearall(data->cookies); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + else if(Curl_raw_equal(argptr, "SESS")) { + /* clear session cookies */ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_clearsess(data->cookies); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + else if(Curl_raw_equal(argptr, "FLUSH")) { + /* flush cookies to file, takes care of the locking */ + Curl_flush_cookies(data, 0); + } + else if(Curl_raw_equal(argptr, "RELOAD")) { + /* reload cookies from file */ + Curl_cookie_loadfiles(data); + break; + } + else { + if(!data->cookies) + /* if cookie engine was not running, activate it */ + data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); + + argptr = strdup(argptr); + if(!argptr || !data->cookies) { + result = CURLE_OUT_OF_MEMORY; + free(argptr); + } + else { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + + if(checkprefix("Set-Cookie:", argptr)) + /* HTTP Header format line */ + Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL); + + else + /* Netscape format line */ + Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL); + + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + free(argptr); + } + } + + break; +#endif /* CURL_DISABLE_COOKIES */ + + case CURLOPT_HTTPGET: + /* + * Set to force us do HTTP GET + */ + if(va_arg(param, long)) { + data->set.httpreq = HTTPREQ_GET; + data->set.upload = FALSE; /* switch off upload */ + data->set.opt_no_body = FALSE; /* this is implied */ + } + break; + + case CURLOPT_HTTP_VERSION: + /* + * This sets a requested HTTP version to be used. The value is one of + * the listed enums in curl/curl.h. + */ + arg = va_arg(param, long); +#ifndef USE_NGHTTP2 + if(arg == CURL_HTTP_VERSION_2_0) + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + data->set.httpversion = arg; + break; + + case CURLOPT_HTTPAUTH: + /* + * Set HTTP Authentication type BITMASK. + */ + { + int bitcheck; + bool authbits; + unsigned long auth = va_arg(param, unsigned long); + + if(auth == CURLAUTH_NONE) { + data->set.httpauth = auth; + break; + } + + /* the DIGEST_IE bit is only used to set a special marker, for all the + rest we need to handle it as normal DIGEST */ + data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE; + + if(auth & CURLAUTH_DIGEST_IE) { + auth |= CURLAUTH_DIGEST; /* set standard digest bit */ + auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ + } + + /* switch off bits we can't support */ +#ifndef USE_NTLM + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#elif !defined(NTLM_WB_ENABLED) + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#endif +#ifndef USE_SPNEGO + auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without + GSS-API or SSPI */ +#endif + + /* check if any auth bit lower than CURLAUTH_ONLY is still set */ + bitcheck = 0; + authbits = FALSE; + while(bitcheck < 31) { + if(auth & (1UL << bitcheck++)) { + authbits = TRUE; + break; + } + } + if(!authbits) + return CURLE_NOT_BUILT_IN; /* no supported types left! */ + + data->set.httpauth = auth; + } + break; + + case CURLOPT_EXPECT_100_TIMEOUT_MS: + /* + * Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. + */ + data->set.expect_100_timeout = va_arg(param, long); + break; + +#endif /* CURL_DISABLE_HTTP */ + + case CURLOPT_CUSTOMREQUEST: + /* + * Set a custom string to use as request + */ + result = setstropt(&data->set.str[STRING_CUSTOMREQUEST], + va_arg(param, char *)); + + /* we don't set + data->set.httpreq = HTTPREQ_CUSTOM; + here, we continue as if we were using the already set type + and this just changes the actual request keyword */ + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_HTTPPROXYTUNNEL: + /* + * Tunnel operations through the proxy instead of normal proxy use + */ + data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_PROXYPORT: + /* + * Explicitly set HTTP proxy port number. + */ + data->set.proxyport = va_arg(param, long); + break; + + case CURLOPT_PROXYAUTH: + /* + * Set HTTP Authentication type BITMASK. + */ + { + int bitcheck; + bool authbits; + unsigned long auth = va_arg(param, unsigned long); + + if(auth == CURLAUTH_NONE) { + data->set.proxyauth = auth; + break; + } + + /* the DIGEST_IE bit is only used to set a special marker, for all the + rest we need to handle it as normal DIGEST */ + data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE; + + if(auth & CURLAUTH_DIGEST_IE) { + auth |= CURLAUTH_DIGEST; /* set standard digest bit */ + auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ + } + /* switch off bits we can't support */ +#ifndef USE_NTLM + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#elif !defined(NTLM_WB_ENABLED) + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#endif +#ifndef USE_SPNEGO + auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without + GSS-API or SSPI */ +#endif + + /* check if any auth bit lower than CURLAUTH_ONLY is still set */ + bitcheck = 0; + authbits = FALSE; + while(bitcheck < 31) { + if(auth & (1UL << bitcheck++)) { + authbits = TRUE; + break; + } + } + if(!authbits) + return CURLE_NOT_BUILT_IN; /* no supported types left! */ + + data->set.proxyauth = auth; + } + break; + + case CURLOPT_PROXY: + /* + * Set proxy server:port to use as HTTP proxy. + * + * If the proxy is set to "" we explicitly say that we don't want to use a + * proxy (even though there might be environment variables saying so). + * + * Setting it to NULL, means no proxy but allows the environment variables + * to decide for us. + */ + result = setstropt(&data->set.str[STRING_PROXY], + va_arg(param, char *)); + break; + + case CURLOPT_PROXYTYPE: + /* + * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME + */ + data->set.proxytype = (curl_proxytype)va_arg(param, long); + break; + + case CURLOPT_PROXY_TRANSFER_MODE: + /* + * set transfer mode (;type=) when doing FTP via an HTTP proxy + */ + switch (va_arg(param, long)) { + case 0: + data->set.proxy_transfer_mode = FALSE; + break; + case 1: + data->set.proxy_transfer_mode = TRUE; + break; + default: + /* reserve other values for future use */ + result = CURLE_UNKNOWN_OPTION; + break; + } + break; +#endif /* CURL_DISABLE_PROXY */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + case CURLOPT_SOCKS5_GSSAPI_SERVICE: + /* + * Set GSS-API service name + */ + result = setstropt(&data->set.str[STRING_SOCKS5_GSSAPI_SERVICE], + va_arg(param, char *)); + break; + + case CURLOPT_SOCKS5_GSSAPI_NEC: + /* + * set flag for nec socks5 support + */ + data->set.socks5_gssapi_nec = (0 != va_arg(param, long))?TRUE:FALSE; + break; +#endif + + case CURLOPT_HEADERDATA: + /* + * Custom pointer to pass the header write callback function + */ + data->set.writeheader = (void *)va_arg(param, void *); + break; + case CURLOPT_ERRORBUFFER: + /* + * Error buffer provided by the caller to get the human readable + * error string in. + */ + data->set.errorbuffer = va_arg(param, char *); + break; + case CURLOPT_WRITEDATA: + /* + * FILE pointer to write to. Or possibly + * used as argument to the write callback. + */ + data->set.out = va_arg(param, void *); + break; + case CURLOPT_FTPPORT: + /* + * Use FTP PORT, this also specifies which IP address to use + */ + result = setstropt(&data->set.str[STRING_FTPPORT], + va_arg(param, char *)); + data->set.ftp_use_port = (NULL != data->set.str[STRING_FTPPORT]) ? + TRUE:FALSE; + break; + + case CURLOPT_FTP_USE_EPRT: + data->set.ftp_use_eprt = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_FTP_USE_EPSV: + data->set.ftp_use_epsv = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_FTP_USE_PRET: + data->set.ftp_use_pret = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_FTP_SSL_CCC: + data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long); + break; + + case CURLOPT_FTP_SKIP_PASV_IP: + /* + * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the + * bypass of the IP address in PASV responses. + */ + data->set.ftp_skip_ip = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_READDATA: + /* + * FILE pointer to read the file to be uploaded from. Or possibly + * used as argument to the read callback. + */ + data->set.in = va_arg(param, void *); + break; + case CURLOPT_INFILESIZE: + /* + * If known, this should inform curl about the file size of the + * to-be-uploaded file. + */ + data->set.filesize = va_arg(param, long); + break; + case CURLOPT_INFILESIZE_LARGE: + /* + * If known, this should inform curl about the file size of the + * to-be-uploaded file. + */ + data->set.filesize = va_arg(param, curl_off_t); + break; + case CURLOPT_LOW_SPEED_LIMIT: + /* + * The low speed limit that if transfers are below this for + * CURLOPT_LOW_SPEED_TIME, the transfer is aborted. + */ + data->set.low_speed_limit=va_arg(param, long); + break; + case CURLOPT_MAX_SEND_SPEED_LARGE: + /* + * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE + * bytes per second the transfer is throttled.. + */ + data->set.max_send_speed=va_arg(param, curl_off_t); + break; + case CURLOPT_MAX_RECV_SPEED_LARGE: + /* + * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per + * second the transfer is throttled.. + */ + data->set.max_recv_speed=va_arg(param, curl_off_t); + break; + case CURLOPT_LOW_SPEED_TIME: + /* + * The low speed time that if transfers are below the set + * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted. + */ + data->set.low_speed_time=va_arg(param, long); + break; + case CURLOPT_URL: + /* + * The URL to fetch. + */ + if(data->change.url_alloc) { + /* the already set URL is allocated, free it first! */ + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + result = setstropt(&data->set.str[STRING_SET_URL], + va_arg(param, char *)); + data->change.url = data->set.str[STRING_SET_URL]; + break; + case CURLOPT_PORT: + /* + * The port number to use when getting the URL + */ + data->set.use_port = va_arg(param, long); + break; + case CURLOPT_TIMEOUT: + /* + * The maximum time you allow curl to use for a single transfer + * operation. + */ + data->set.timeout = va_arg(param, long) * 1000L; + break; + + case CURLOPT_TIMEOUT_MS: + data->set.timeout = va_arg(param, long); + break; + + case CURLOPT_CONNECTTIMEOUT: + /* + * The maximum time you allow curl to use to connect. + */ + data->set.connecttimeout = va_arg(param, long) * 1000L; + break; + + case CURLOPT_CONNECTTIMEOUT_MS: + data->set.connecttimeout = va_arg(param, long); + break; + + case CURLOPT_ACCEPTTIMEOUT_MS: + /* + * The maximum time you allow curl to wait for server connect + */ + data->set.accepttimeout = va_arg(param, long); + break; + + case CURLOPT_USERPWD: + /* + * user:password to use in the operation + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_USERNAME], + &data->set.str[STRING_PASSWORD]); + break; + + case CURLOPT_USERNAME: + /* + * authentication user name to use in the operation + */ + result = setstropt(&data->set.str[STRING_USERNAME], + va_arg(param, char *)); + break; + + case CURLOPT_PASSWORD: + /* + * authentication password to use in the operation + */ + result = setstropt(&data->set.str[STRING_PASSWORD], + va_arg(param, char *)); + break; + + case CURLOPT_LOGIN_OPTIONS: + /* + * authentication options to use in the operation + */ + result = setstropt(&data->set.str[STRING_OPTIONS], + va_arg(param, char *)); + break; + + case CURLOPT_XOAUTH2_BEARER: + /* + * XOAUTH2 bearer token to use in the operation + */ + result = setstropt(&data->set.str[STRING_BEARER], + va_arg(param, char *)); + break; + + case CURLOPT_POSTQUOTE: + /* + * List of RAW FTP commands to use after a transfer + */ + data->set.postquote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_PREQUOTE: + /* + * List of RAW FTP commands to use prior to RETR (Wesley Laxton) + */ + data->set.prequote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_QUOTE: + /* + * List of RAW FTP commands to use before a transfer + */ + data->set.quote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_RESOLVE: + /* + * List of NAME:[address] names to populate the DNS cache with + * Prefix the NAME with dash (-) to _remove_ the name from the cache. + * + * Names added with this API will remain in the cache until explicitly + * removed or the handle is cleaned up. + * + * This API can remove any name from the DNS cache, but only entries + * that aren't actually in use right now will be pruned immediately. + */ + data->set.resolve = va_arg(param, struct curl_slist *); + data->change.resolve = data->set.resolve; + break; + case CURLOPT_PROGRESSFUNCTION: + /* + * Progress callback function + */ + data->set.fprogress = va_arg(param, curl_progress_callback); + if(data->set.fprogress) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + break; + + case CURLOPT_XFERINFOFUNCTION: + /* + * Transfer info callback function + */ + data->set.fxferinfo = va_arg(param, curl_xferinfo_callback); + if(data->set.fxferinfo) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + + break; + + case CURLOPT_PROGRESSDATA: + /* + * Custom client data to pass to the progress callback + */ + data->set.progress_client = va_arg(param, void *); + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXYUSERPWD: + /* + * user:password needed to use the proxy + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_PROXYUSERNAME], + &data->set.str[STRING_PROXYPASSWORD]); + break; + case CURLOPT_PROXYUSERNAME: + /* + * authentication user name to use in the operation + */ + result = setstropt(&data->set.str[STRING_PROXYUSERNAME], + va_arg(param, char *)); + break; + case CURLOPT_PROXYPASSWORD: + /* + * authentication password to use in the operation + */ + result = setstropt(&data->set.str[STRING_PROXYPASSWORD], + va_arg(param, char *)); + break; + case CURLOPT_NOPROXY: + /* + * proxy exception list + */ + result = setstropt(&data->set.str[STRING_NOPROXY], + va_arg(param, char *)); + break; +#endif + + case CURLOPT_RANGE: + /* + * What range of the file you want to transfer + */ + result = setstropt(&data->set.str[STRING_SET_RANGE], + va_arg(param, char *)); + break; + case CURLOPT_RESUME_FROM: + /* + * Resume transfer at the give file position + */ + data->set.set_resume_from = va_arg(param, long); + break; + case CURLOPT_RESUME_FROM_LARGE: + /* + * Resume transfer at the give file position + */ + data->set.set_resume_from = va_arg(param, curl_off_t); + break; + case CURLOPT_DEBUGFUNCTION: + /* + * stderr write callback. + */ + data->set.fdebug = va_arg(param, curl_debug_callback); + /* + * if the callback provided is NULL, it'll use the default callback + */ + break; + case CURLOPT_DEBUGDATA: + /* + * Set to a void * that should receive all error writes. This + * defaults to CURLOPT_STDERR for normal operations. + */ + data->set.debugdata = va_arg(param, void *); + break; + case CURLOPT_STDERR: + /* + * Set to a FILE * that should receive all error writes. This + * defaults to stderr for normal operations. + */ + data->set.err = va_arg(param, FILE *); + if(!data->set.err) + data->set.err = stderr; + break; + case CURLOPT_HEADERFUNCTION: + /* + * Set header write callback + */ + data->set.fwrite_header = va_arg(param, curl_write_callback); + break; + case CURLOPT_WRITEFUNCTION: + /* + * Set data write callback + */ + data->set.fwrite_func = va_arg(param, curl_write_callback); + if(!data->set.fwrite_func) { + data->set.is_fwrite_set = 0; + /* When set to NULL, reset to our internal default function */ + data->set.fwrite_func = (curl_write_callback)fwrite; + } + else + data->set.is_fwrite_set = 1; + break; + case CURLOPT_READFUNCTION: + /* + * Read data callback + */ + data->set.fread_func = va_arg(param, curl_read_callback); + if(!data->set.fread_func) { + data->set.is_fread_set = 0; + /* When set to NULL, reset to our internal default function */ + data->set.fread_func = (curl_read_callback)fread; + } + else + data->set.is_fread_set = 1; + break; + case CURLOPT_SEEKFUNCTION: + /* + * Seek callback. Might be NULL. + */ + data->set.seek_func = va_arg(param, curl_seek_callback); + break; + case CURLOPT_SEEKDATA: + /* + * Seek control callback. Might be NULL. + */ + data->set.seek_client = va_arg(param, void *); + break; + case CURLOPT_CONV_FROM_NETWORK_FUNCTION: + /* + * "Convert from network encoding" callback + */ + data->set.convfromnetwork = va_arg(param, curl_conv_callback); + break; + case CURLOPT_CONV_TO_NETWORK_FUNCTION: + /* + * "Convert to network encoding" callback + */ + data->set.convtonetwork = va_arg(param, curl_conv_callback); + break; + case CURLOPT_CONV_FROM_UTF8_FUNCTION: + /* + * "Convert from UTF-8 encoding" callback + */ + data->set.convfromutf8 = va_arg(param, curl_conv_callback); + break; + case CURLOPT_IOCTLFUNCTION: + /* + * I/O control callback. Might be NULL. + */ + data->set.ioctl_func = va_arg(param, curl_ioctl_callback); + break; + case CURLOPT_IOCTLDATA: + /* + * I/O control data pointer. Might be NULL. + */ + data->set.ioctl_client = va_arg(param, void *); + break; + case CURLOPT_SSLCERT: + /* + * String that holds file name of the SSL certificate to use + */ + result = setstropt(&data->set.str[STRING_CERT], + va_arg(param, char *)); + break; + case CURLOPT_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use + */ + result = setstropt(&data->set.str[STRING_CERT_TYPE], + va_arg(param, char *)); + break; + case CURLOPT_SSLKEY: + /* + * String that holds file name of the SSL key to use + */ + result = setstropt(&data->set.str[STRING_KEY], + va_arg(param, char *)); + break; + case CURLOPT_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use + */ + result = setstropt(&data->set.str[STRING_KEY_TYPE], + va_arg(param, char *)); + break; + case CURLOPT_KEYPASSWD: + /* + * String that holds the SSL or SSH private key password. + */ + result = setstropt(&data->set.str[STRING_KEY_PASSWD], + va_arg(param, char *)); + break; + case CURLOPT_SSLENGINE: + /* + * String that holds the SSL crypto engine. + */ + argptr = va_arg(param, char *); + if(argptr && argptr[0]) + result = Curl_ssl_set_engine(data, argptr); + break; + + case CURLOPT_SSLENGINE_DEFAULT: + /* + * flag to set engine as default. + */ + result = Curl_ssl_set_engine_default(data); + break; + case CURLOPT_CRLF: + /* + * Kludgy option to enable CRLF conversions. Subject for removal. + */ + data->set.crlf = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_INTERFACE: + /* + * Set what interface or address/hostname to bind the socket to when + * performing an operation and thus what from-IP your connection will use. + */ + result = setstropt(&data->set.str[STRING_DEVICE], + va_arg(param, char *)); + break; + case CURLOPT_LOCALPORT: + /* + * Set what local port to bind the socket to when performing an operation. + */ + data->set.localport = curlx_sltous(va_arg(param, long)); + break; + case CURLOPT_LOCALPORTRANGE: + /* + * Set number of local ports to try, starting with CURLOPT_LOCALPORT. + */ + data->set.localportrange = curlx_sltosi(va_arg(param, long)); + break; + case CURLOPT_KRBLEVEL: + /* + * A string that defines the kerberos security level. + */ + result = setstropt(&data->set.str[STRING_KRB_LEVEL], + va_arg(param, char *)); + data->set.krb = (NULL != data->set.str[STRING_KRB_LEVEL])?TRUE:FALSE; + break; + case CURLOPT_GSSAPI_DELEGATION: + /* + * GSS-API credential delegation + */ + data->set.gssapi_delegation = va_arg(param, long); + break; + case CURLOPT_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying. + */ + data->set.ssl.verifypeer = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.ssl.verifyhost = (0 != arg)?TRUE:FALSE; + break; + case CURLOPT_SSL_VERIFYSTATUS: + /* + * Enable certificate status verifying. + */ + if(!Curl_ssl_cert_status_request()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.verifystatus = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_SSL_CTX_FUNCTION: +#ifdef have_curlssl_ssl_ctx + /* + * Set a SSL_CTX callback + */ + data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback); +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; + case CURLOPT_SSL_CTX_DATA: +#ifdef have_curlssl_ssl_ctx + /* + * Set a SSL_CTX callback parameter pointer + */ + data->set.ssl.fsslctxp = va_arg(param, void *); +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; + case CURLOPT_SSL_FALSESTART: + /* + * Enable TLS false start. + */ + if(!Curl_ssl_false_start()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.falsestart = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_CERTINFO: +#ifdef have_curlssl_certinfo + data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE; +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; + case CURLOPT_PINNEDPUBLICKEY: + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ + result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY], + va_arg(param, char *)); + break; + case CURLOPT_CAINFO: + /* + * Set CA info for SSL connection. Specify file name of the CA certificate + */ + result = setstropt(&data->set.str[STRING_SSL_CAFILE], + va_arg(param, char *)); + break; + case CURLOPT_CAPATH: +#ifdef have_curlssl_ca_path /* not supported by all backends */ + /* + * Set CA path info for SSL connection. Specify directory name of the CA + * certificates which have been prepared using openssl c_rehash utility. + */ + /* This does not work on windows. */ + result = setstropt(&data->set.str[STRING_SSL_CAPATH], + va_arg(param, char *)); +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; + case CURLOPT_CRLFILE: + /* + * Set CRL file info for SSL connection. Specify file name of the CRL + * to check certificates revocation + */ + result = setstropt(&data->set.str[STRING_SSL_CRLFILE], + va_arg(param, char *)); + break; + case CURLOPT_ISSUERCERT: + /* + * Set Issuer certificate file + * to check certificates issuer + */ + result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT], + va_arg(param, char *)); + break; + case CURLOPT_TELNETOPTIONS: + /* + * Set a linked list of telnet options + */ + data->set.telnet_options = va_arg(param, struct curl_slist *); + break; + + case CURLOPT_BUFFERSIZE: + /* + * The application kindly asks for a differently sized receive buffer. + * If it seems reasonable, we'll use it. + */ + data->set.buffer_size = va_arg(param, long); + + if((data->set.buffer_size> (BUFSIZE -1 )) || + (data->set.buffer_size < 1)) + data->set.buffer_size = 0; /* huge internal default */ + + break; + + case CURLOPT_NOSIGNAL: + /* + * The application asks not to set any signal() or alarm() handlers, + * even when using a timeout. + */ + data->set.no_signal = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_SHARE: + { + struct Curl_share *set; + set = va_arg(param, struct Curl_share *); + + /* disconnect from old share, if any */ + if(data->share) { + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + + if(data->dns.hostcachetype == HCACHE_SHARED) { + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(data->share->cookies == data->cookies) + data->cookies = NULL; +#endif + + if(data->share->sslsession == data->state.session) + data->state.session = NULL; + + data->share->dirty--; + + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + data->share = NULL; + } + + /* use new share if it set */ + data->share = set; + if(data->share) { + + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + + data->share->dirty++; + + if(data->share->hostcache) { + /* use shared host cache */ + data->dns.hostcache = data->share->hostcache; + data->dns.hostcachetype = HCACHE_SHARED; + } +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(data->share->cookies) { + /* use shared cookie list, first free own one if any */ + Curl_cookie_cleanup(data->cookies); + /* enable cookies since we now use a share that uses cookies! */ + data->cookies = data->share->cookies; + } +#endif /* CURL_DISABLE_HTTP */ + if(data->share->sslsession) { + data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions; + data->state.session = data->share->sslsession; + } + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + + } + /* check for host cache not needed, + * it will be done by curl_easy_perform */ + } + break; + + case CURLOPT_PRIVATE: + /* + * Set private data pointer. + */ + data->set.private_data = va_arg(param, void *); + break; + + case CURLOPT_MAXFILESIZE: + /* + * Set the maximum size of a file to download. + */ + data->set.max_filesize = va_arg(param, long); + break; + +#ifdef USE_SSL + case CURLOPT_USE_SSL: + /* + * Make transfers attempt to use SSL/TLS. + */ + data->set.use_ssl = (curl_usessl)va_arg(param, long); + break; + + case CURLOPT_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.ssl_enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + break; + +#endif + case CURLOPT_FTPSSLAUTH: + /* + * Set a specific auth for FTP-SSL transfers. + */ + data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long); + break; + + case CURLOPT_IPRESOLVE: + data->set.ipver = va_arg(param, long); + break; + + case CURLOPT_MAXFILESIZE_LARGE: + /* + * Set the maximum size of a file to download. + */ + data->set.max_filesize = va_arg(param, curl_off_t); + break; + + case CURLOPT_TCP_NODELAY: + /* + * Enable or disable TCP_NODELAY, which will disable/enable the Nagle + * algorithm + */ + data->set.tcp_nodelay = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_FTP_ACCOUNT: + result = setstropt(&data->set.str[STRING_FTP_ACCOUNT], + va_arg(param, char *)); + break; + + case CURLOPT_IGNORE_CONTENT_LENGTH: + data->set.ignorecl = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_CONNECT_ONLY: + /* + * No data transfer, set up connection and let application use the socket + */ + data->set.connect_only = (0 != va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_FTP_ALTERNATIVE_TO_USER: + result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER], + va_arg(param, char *)); + break; + + case CURLOPT_SOCKOPTFUNCTION: + /* + * socket callback function: called after socket() but before connect() + */ + data->set.fsockopt = va_arg(param, curl_sockopt_callback); + break; + + case CURLOPT_SOCKOPTDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.sockopt_client = va_arg(param, void *); + break; + + case CURLOPT_OPENSOCKETFUNCTION: + /* + * open/create socket callback function: called instead of socket(), + * before connect() + */ + data->set.fopensocket = va_arg(param, curl_opensocket_callback); + break; + + case CURLOPT_OPENSOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.opensocket_client = va_arg(param, void *); + break; + + case CURLOPT_CLOSESOCKETFUNCTION: + /* + * close socket callback function: called instead of close() + * when shutting down a connection + */ + data->set.fclosesocket = va_arg(param, curl_closesocket_callback); + break; + + case CURLOPT_CLOSESOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.closesocket_client = va_arg(param, void *); + break; + + case CURLOPT_SSL_SESSIONID_CACHE: + data->set.ssl.sessionid = (0 != va_arg(param, long))?TRUE:FALSE; + break; + +#ifdef USE_LIBSSH2 + /* we only include SSH options if explicitly built to support SSH */ + case CURLOPT_SSH_AUTH_TYPES: + data->set.ssh_auth_types = va_arg(param, long); + break; + + case CURLOPT_SSH_PUBLIC_KEYFILE: + /* + * Use this file instead of the $HOME/.ssh/id_dsa.pub file + */ + result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_PRIVATE_KEYFILE: + /* + * Use this file instead of the $HOME/.ssh/id_dsa file + */ + result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], + va_arg(param, char *)); + break; + case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: + /* + * Option to allow for the MD5 of the host public key to be checked + * for validation purposes. + */ + result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], + va_arg(param, char *)); + break; +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + case CURLOPT_SSH_KNOWNHOSTS: + /* + * Store the file name to read known hosts from. + */ + result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_KEYFUNCTION: + /* setting to NULL is fine since the ssh.c functions themselves will + then rever to use the internal default */ + data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback); + break; + + case CURLOPT_SSH_KEYDATA: + /* + * Custom client data to pass to the SSH keyfunc callback + */ + data->set.ssh_keyfunc_userp = va_arg(param, void *); + break; +#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ + +#endif /* USE_LIBSSH2 */ + + case CURLOPT_HTTP_TRANSFER_DECODING: + /* + * disable libcurl transfer encoding is used + */ + data->set.http_te_skip = (0 == va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_HTTP_CONTENT_DECODING: + /* + * raw data passed to the application when content encoding is used + */ + data->set.http_ce_skip = (0 == va_arg(param, long))?TRUE:FALSE; + break; + + case CURLOPT_NEW_FILE_PERMS: + /* + * Uses these permissions instead of 0644 + */ + data->set.new_file_perms = va_arg(param, long); + break; + + case CURLOPT_NEW_DIRECTORY_PERMS: + /* + * Uses these permissions instead of 0755 + */ + data->set.new_directory_perms = va_arg(param, long); + break; + + case CURLOPT_ADDRESS_SCOPE: + /* + * We always get longs when passed plain numericals, but for this value we + * know that an unsigned int will always hold the value so we blindly + * typecast to this type + */ + data->set.scope_id = curlx_sltoui(va_arg(param, long)); + break; + + case CURLOPT_PROTOCOLS: + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + data->set.allowed_protocols = va_arg(param, long); + break; + + case CURLOPT_REDIR_PROTOCOLS: + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to all protocols except FILE and SCP. */ + data->set.redir_protocols = va_arg(param, long); + break; + + case CURLOPT_MAIL_FROM: + /* Set the SMTP mail originator */ + result = setstropt(&data->set.str[STRING_MAIL_FROM], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_AUTH: + /* Set the SMTP auth originator */ + result = setstropt(&data->set.str[STRING_MAIL_AUTH], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_RCPT: + /* Set the list of mail recipients */ + data->set.mail_rcpt = va_arg(param, struct curl_slist *); + break; + + case CURLOPT_SASL_IR: + /* Enable/disable SASL initial response */ + data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_RTSP_REQUEST: + { + /* + * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...) + * Would this be better if the RTSPREQ_* were just moved into here? + */ + long curl_rtspreq = va_arg(param, long); + Curl_RtspReq rtspreq = RTSPREQ_NONE; + switch(curl_rtspreq) { + case CURL_RTSPREQ_OPTIONS: + rtspreq = RTSPREQ_OPTIONS; + break; + + case CURL_RTSPREQ_DESCRIBE: + rtspreq = RTSPREQ_DESCRIBE; + break; + + case CURL_RTSPREQ_ANNOUNCE: + rtspreq = RTSPREQ_ANNOUNCE; + break; + + case CURL_RTSPREQ_SETUP: + rtspreq = RTSPREQ_SETUP; + break; + + case CURL_RTSPREQ_PLAY: + rtspreq = RTSPREQ_PLAY; + break; + + case CURL_RTSPREQ_PAUSE: + rtspreq = RTSPREQ_PAUSE; + break; + + case CURL_RTSPREQ_TEARDOWN: + rtspreq = RTSPREQ_TEARDOWN; + break; + + case CURL_RTSPREQ_GET_PARAMETER: + rtspreq = RTSPREQ_GET_PARAMETER; + break; + + case CURL_RTSPREQ_SET_PARAMETER: + rtspreq = RTSPREQ_SET_PARAMETER; + break; + + case CURL_RTSPREQ_RECORD: + rtspreq = RTSPREQ_RECORD; + break; + + case CURL_RTSPREQ_RECEIVE: + rtspreq = RTSPREQ_RECEIVE; + break; + default: + rtspreq = RTSPREQ_NONE; + } + + data->set.rtspreq = rtspreq; + break; + } + + + case CURLOPT_RTSP_SESSION_ID: + /* + * Set the RTSP Session ID manually. Useful if the application is + * resuming a previously established RTSP session + */ + result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_STREAM_URI: + /* + * Set the Stream URI for the RTSP request. Unless the request is + * for generic server options, the application will need to set this. + */ + result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_TRANSPORT: + /* + * The content of the Transport: header for the RTSP request + */ + result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_CLIENT_CSEQ: + /* + * Set the CSEQ number to issue for the next RTSP request. Useful if the + * application is resuming a previously broken connection. The CSEQ + * will increment from this new number henceforth. + */ + data->state.rtsp_next_client_CSeq = va_arg(param, long); + break; + + case CURLOPT_RTSP_SERVER_CSEQ: + /* Same as the above, but for server-initiated requests */ + data->state.rtsp_next_client_CSeq = va_arg(param, long); + break; + + case CURLOPT_INTERLEAVEDATA: + data->set.rtp_out = va_arg(param, void *); + break; + case CURLOPT_INTERLEAVEFUNCTION: + /* Set the user defined RTP write function */ + data->set.fwrite_rtp = va_arg(param, curl_write_callback); + break; + + case CURLOPT_WILDCARDMATCH: + data->set.wildcardmatch = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_CHUNK_BGN_FUNCTION: + data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback); + break; + case CURLOPT_CHUNK_END_FUNCTION: + data->set.chunk_end = va_arg(param, curl_chunk_end_callback); + break; + case CURLOPT_FNMATCH_FUNCTION: + data->set.fnmatch = va_arg(param, curl_fnmatch_callback); + break; + case CURLOPT_CHUNK_DATA: + data->wildcard.customptr = va_arg(param, void *); + break; + case CURLOPT_FNMATCH_DATA: + data->set.fnmatch_data = va_arg(param, void *); + break; +#ifdef USE_TLS_SRP + case CURLOPT_TLSAUTH_USERNAME: + result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_PASSWORD: + result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_TYPE: + if(strnequal((char *)va_arg(param, char *), "SRP", strlen("SRP"))) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.ssl.authtype = CURL_TLSAUTH_NONE; + break; +#endif + case CURLOPT_DNS_SERVERS: + result = Curl_set_dns_servers(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_INTERFACE: + result = Curl_set_dns_interface(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_LOCAL_IP4: + result = Curl_set_dns_local_ip4(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_LOCAL_IP6: + result = Curl_set_dns_local_ip6(data, va_arg(param, char *)); + break; + + case CURLOPT_TCP_KEEPALIVE: + data->set.tcp_keepalive = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_TCP_KEEPIDLE: + data->set.tcp_keepidle = va_arg(param, long); + break; + case CURLOPT_TCP_KEEPINTVL: + data->set.tcp_keepintvl = va_arg(param, long); + break; + case CURLOPT_SSL_ENABLE_NPN: + data->set.ssl_enable_npn = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_SSL_ENABLE_ALPN: + data->set.ssl_enable_alpn = (0 != va_arg(param, long))?TRUE:FALSE; + break; + +#ifdef USE_UNIX_SOCKETS + case CURLOPT_UNIX_SOCKET_PATH: + result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], + va_arg(param, char *)); + break; +#endif + + case CURLOPT_PATH_AS_IS: + data->set.path_as_is = (0 != va_arg(param, long))?TRUE:FALSE; + break; + default: + /* unknown tag and its companion, just ignore: */ + result = CURLE_UNKNOWN_OPTION; + break; + } + + return result; +} + +static void conn_free(struct connectdata *conn) +{ + if(!conn) + return; + + /* possible left-overs from the async name resolvers */ + Curl_resolver_cancel(conn); + + /* close the SSL stuff before we close any sockets since they will/may + write to the sockets */ + Curl_ssl_close(conn, FIRSTSOCKET); + Curl_ssl_close(conn, SECONDARYSOCKET); + + /* close possibly still open sockets */ + if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) + Curl_closesocket(conn, conn->sock[FIRSTSOCKET]); + if(CURL_SOCKET_BAD != conn->tempsock[0]) + Curl_closesocket(conn, conn->tempsock[0]); + if(CURL_SOCKET_BAD != conn->tempsock[1]) + Curl_closesocket(conn, conn->tempsock[1]); + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + Curl_ntlm_wb_cleanup(conn); +#endif + + Curl_safefree(conn->user); + Curl_safefree(conn->passwd); + Curl_safefree(conn->xoauth2_bearer); + Curl_safefree(conn->options); + Curl_safefree(conn->proxyuser); + Curl_safefree(conn->proxypasswd); + Curl_safefree(conn->allocptr.proxyuserpwd); + Curl_safefree(conn->allocptr.uagent); + Curl_safefree(conn->allocptr.userpwd); + Curl_safefree(conn->allocptr.accept_encoding); + Curl_safefree(conn->allocptr.te); + Curl_safefree(conn->allocptr.rangeline); + Curl_safefree(conn->allocptr.ref); + Curl_safefree(conn->allocptr.host); + Curl_safefree(conn->allocptr.cookiehost); + Curl_safefree(conn->allocptr.rtsp_transport); + Curl_safefree(conn->trailer); + Curl_safefree(conn->host.rawalloc); /* host name buffer */ + Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */ + Curl_safefree(conn->master_buffer); + + Curl_llist_destroy(conn->send_pipe, NULL); + Curl_llist_destroy(conn->recv_pipe, NULL); + + conn->send_pipe = NULL; + conn->recv_pipe = NULL; + + Curl_safefree(conn->localdev); + Curl_free_ssl_config(&conn->ssl_config); + + free(conn); /* free all the connection oriented data */ +} + +/* + * Disconnects the given connection. Note the connection may not be the + * primary connection, like when freeing room in the connection cache or + * killing of a dead old connection. + * + * This function MUST NOT reset state in the SessionHandle struct if that + * isn't strictly bound to the life-time of *this* particular connection. + * + */ + +CURL_STATIC CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct SessionHandle *data; + if(!conn) + return CURLE_OK; /* this is closed and fine already */ + data = conn->data; + + if(!data) { + DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n")); + return CURLE_OK; + } + + if(conn->dns_entry != NULL) { + Curl_resolv_unlock(data, conn->dns_entry); + conn->dns_entry = NULL; + } + + Curl_hostcache_prune(data); /* kill old DNS cache entries */ + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + /* Cleanup NTLM connection-related data */ + Curl_http_ntlm_cleanup(conn); +#endif + + if(conn->handler->disconnect) + /* This is set if protocol-specific cleanups should be made */ + conn->handler->disconnect(conn, dead_connection); + + /* unlink ourselves! */ + infof(data, "Closing connection %ld\n", conn->connection_id); + Curl_conncache_remove_conn(data->state.conn_cache, conn); + +#if defined(USE_LIBIDN) + if(conn->host.encalloc) + idn_free(conn->host.encalloc); /* encoded host name buffer, must be freed + with idn_free() since this was allocated + by libidn */ + if(conn->proxy.encalloc) + idn_free(conn->proxy.encalloc); /* encoded proxy name buffer, must be + freed with idn_free() since this was + allocated by libidn */ +#elif defined(USE_WIN32_IDN) + free(conn->host.encalloc); /* encoded host name buffer, must be freed with + idn_free() since this was allocated by + curl_win32_idn_to_ascii */ + free(conn->proxy.encalloc); /* encoded proxy name buffer, must be freed + with idn_free() since this was allocated by + curl_win32_idn_to_ascii */ +#endif + + Curl_ssl_close(conn, FIRSTSOCKET); + + /* Indicate to all handles on the pipe that we're dead */ + if(Curl_multi_pipeline_enabled(data->multi)) { + signalPipeClose(conn->send_pipe, TRUE); + signalPipeClose(conn->recv_pipe, TRUE); + } + + conn_free(conn); + + return CURLE_OK; +} + +/* + * This function should return TRUE if the socket is to be assumed to + * be dead. Most commonly this happens when the server has closed the + * connection due to inactivity. + */ +static bool SocketIsDead(curl_socket_t sock) +{ + int sval; + bool ret_val = TRUE; + + sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0); + if(sval == 0) + /* timeout */ + ret_val = FALSE; + + return ret_val; +} + +static bool IsPipeliningPossible(const struct SessionHandle *handle, + const struct connectdata *conn) +{ + if((conn->handler->protocol & PROTO_FAMILY_HTTP) && + Curl_multi_pipeline_enabled(handle->multi) && + (handle->set.httpreq == HTTPREQ_GET || + handle->set.httpreq == HTTPREQ_HEAD) && + handle->set.httpversion != CURL_HTTP_VERSION_1_0) + return TRUE; + + return FALSE; +} + +CURL_STATIC bool Curl_isPipeliningEnabled(const struct SessionHandle *handle) +{ + return Curl_multi_pipeline_enabled(handle->multi); +} + +CURL_STATIC CURLcode Curl_addHandleToPipeline(struct SessionHandle *data, + struct curl_llist *pipeline) +{ + if(!Curl_llist_insert_next(pipeline, pipeline->tail, data)) + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +} + +CURL_STATIC int Curl_removeHandleFromPipeline(struct SessionHandle *handle, + struct curl_llist *pipeline) +{ + struct curl_llist_element *curr; + + curr = pipeline->head; + while(curr) { + if(curr->ptr == handle) { + Curl_llist_remove(pipeline, curr, NULL); + return 1; /* we removed a handle */ + } + curr = curr->next; + } + + return 0; +} + +#if 0 /* this code is saved here as it is useful for debugging purposes */ +static void Curl_printPipeline(struct curl_llist *pipeline) +{ + struct curl_llist_element *curr; + + curr = pipeline->head; + while(curr) { + struct SessionHandle *data = (struct SessionHandle *) curr->ptr; + infof(data, "Handle in pipeline: %s\n", data->state.path); + curr = curr->next; + } +} +#endif + +static struct SessionHandle* gethandleathead(struct curl_llist *pipeline) +{ + struct curl_llist_element *curr = pipeline->head; + if(curr) { + return (struct SessionHandle *) curr->ptr; + } + + return NULL; +} + +/* remove the specified connection from all (possible) pipelines and related + queues */ +CURL_STATIC void Curl_getoff_all_pipelines(struct SessionHandle *data, + struct connectdata *conn) +{ + bool recv_head = (conn->readchannel_inuse && + (gethandleathead(conn->recv_pipe) == data)) ? TRUE : FALSE; + + bool send_head = (conn->writechannel_inuse && + (gethandleathead(conn->send_pipe) == data)) ? TRUE : FALSE; + + if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head) + conn->readchannel_inuse = FALSE; + if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head) + conn->writechannel_inuse = FALSE; +} + +static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke) +{ + struct curl_llist_element *curr; + + if(!pipeline) + return; + + curr = pipeline->head; + while(curr) { + struct curl_llist_element *next = curr->next; + struct SessionHandle *data = (struct SessionHandle *) curr->ptr; + +#ifdef DEBUGBUILD /* debug-only code */ + if(data->magic != CURLEASY_MAGIC_NUMBER) { + /* MAJOR BADNESS */ + infof(data, "signalPipeClose() found BAAD easy handle\n"); + } +#endif + + if(pipe_broke) + data->state.pipe_broke = TRUE; + Curl_multi_handlePipeBreak(data); + Curl_llist_remove(pipeline, curr, NULL); + curr = next; + } +} + +/* + * This function finds the connection in the connection + * cache that has been unused for the longest time. + * + * Returns the pointer to the oldest idle connection, or NULL if none was + * found. + */ +static struct connectdata * +find_oldest_idle_connection(struct SessionHandle *data) +{ + struct conncache *bc = data->state.conn_cache; + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + long highscore=-1; + long score; + struct timeval now; + struct connectdata *conn_candidate = NULL; + struct connectbundle *bundle; + + now = Curl_tvnow(); + + Curl_hash_start_iterate(bc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectdata *conn; + + bundle = he->ptr; + + curr = bundle->conn_list->head; + while(curr) { + conn = curr->ptr; + + if(!conn->inuse) { + /* Set higher score for the age passed since the connection was used */ + score = Curl_tvdiff(now, conn->now); + + if(score > highscore) { + highscore = score; + conn_candidate = conn; + } + } + curr = curr->next; + } + + he = Curl_hash_next_element(&iter); + } + + return conn_candidate; +} + +/* + * This function finds the connection in the connection + * bundle that has been unused for the longest time. + * + * Returns the pointer to the oldest idle connection, or NULL if none was + * found. + */ +static struct connectdata * +find_oldest_idle_connection_in_bundle(struct SessionHandle *data, + struct connectbundle *bundle) +{ + struct curl_llist_element *curr; + long highscore=-1; + long score; + struct timeval now; + struct connectdata *conn_candidate = NULL; + struct connectdata *conn; + + (void)data; + + now = Curl_tvnow(); + + curr = bundle->conn_list->head; + while(curr) { + conn = curr->ptr; + + if(!conn->inuse) { + /* Set higher score for the age passed since the connection was used */ + score = Curl_tvdiff(now, conn->now); + + if(score > highscore) { + highscore = score; + conn_candidate = conn; + } + } + curr = curr->next; + } + + return conn_candidate; +} + +/* + * This function checks if given connection is dead and disconnects if so. + * (That also removes it from the connection cache.) + * + * Returns TRUE if the connection actually was dead and disconnected. + */ +static bool disconnect_if_dead(struct connectdata *conn, + struct SessionHandle *data) +{ + size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size; + if(!pipeLen && !conn->inuse) { + /* The check for a dead socket makes sense only if there are no + handles in pipeline and the connection isn't already marked in + use */ + bool dead; + if(conn->handler->protocol & CURLPROTO_RTSP) + /* RTSP is a special case due to RTP interleaving */ + dead = Curl_rtsp_connisdead(conn); + else + dead = SocketIsDead(conn->sock[FIRSTSOCKET]); + + if(dead) { + conn->data = data; + infof(data, "Connection %ld seems to be dead!\n", conn->connection_id); + + /* disconnect resources */ + Curl_disconnect(conn, /* dead_connection */TRUE); + return TRUE; + } + } + return FALSE; +} + +/* + * Wrapper to use disconnect_if_dead() function in Curl_conncache_foreach() + * + * Returns always 0. + */ +static int call_disconnect_if_dead(struct connectdata *conn, + void *param) +{ + struct SessionHandle* data = (struct SessionHandle*)param; + disconnect_if_dead(conn, data); + return 0; /* continue iteration */ +} + +/* + * This function scans the connection cache for half-open/dead connections, + * closes and removes them. + * The cleanup is done at most once per second. + */ +static void prune_dead_connections(struct SessionHandle *data) +{ + struct timeval now = Curl_tvnow(); + long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup); + + if(elapsed >= 1000L) { + Curl_conncache_foreach(data->state.conn_cache, data, + call_disconnect_if_dead); + data->state.conn_cache->last_cleanup = now; + } +} + +/* + * Given one filled in connection struct (named needle), this function should + * detect if there already is one that has all the significant details + * exactly the same and thus should be used instead. + * + * If there is a match, this function returns TRUE - and has marked the + * connection as 'in-use'. It must later be called with ConnectionDone() to + * return back to 'idle' (unused) state. + * + * The force_reuse flag is set if the connection must be used, even if + * the pipelining strategy wants to open a new connection instead of reusing. + */ +static bool +ConnectionExists(struct SessionHandle *data, + struct connectdata *needle, + struct connectdata **usethis, + bool *force_reuse) +{ + struct connectdata *check; + struct connectdata *chosen = 0; + bool canPipeline = IsPipeliningPossible(data, needle); +#ifdef USE_NTLM + bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) || + (data->state.authhost.want & CURLAUTH_NTLM_WB)) && + (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE; +#endif + struct connectbundle *bundle; + + *force_reuse = FALSE; + + /* We can't pipe if the site is blacklisted */ + if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) { + canPipeline = FALSE; + } + + /* Look up the bundle with all the connections to this + particular host */ + bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache); + if(bundle) { + size_t max_pipe_len = Curl_multi_max_pipeline_length(data->multi); + size_t best_pipe_len = max_pipe_len; + struct curl_llist_element *curr; + + infof(data, "Found bundle for host %s: %p\n", + needle->host.name, (void *)bundle); + + /* We can't pipe if we don't know anything about the server */ + if(canPipeline && !bundle->server_supports_pipelining) { + infof(data, "Server doesn't support pipelining\n"); + canPipeline = FALSE; + } + + curr = bundle->conn_list->head; + while(curr) { + bool match = FALSE; +#if defined(USE_NTLM) + bool credentialsMatch = FALSE; +#endif + size_t pipeLen; + + /* + * Note that if we use a HTTP proxy, we check connections to that + * proxy and not to the actual remote server. + */ + check = curr->ptr; + curr = curr->next; + + if(disconnect_if_dead(check, data)) + continue; + + pipeLen = check->send_pipe->size + check->recv_pipe->size; + + if(canPipeline) { + /* Make sure the pipe has only GET requests */ + struct SessionHandle* sh = gethandleathead(check->send_pipe); + struct SessionHandle* rh = gethandleathead(check->recv_pipe); + if(sh) { + if(!IsPipeliningPossible(sh, check)) + continue; + } + else if(rh) { + if(!IsPipeliningPossible(rh, check)) + continue; + } + } + else { + if(pipeLen > 0) { + /* can only happen within multi handles, and means that another easy + handle is using this connection */ + continue; + } + + if(Curl_resolver_asynch()) { + /* ip_addr_str[0] is NUL only if the resolving of the name hasn't + completed yet and until then we don't re-use this connection */ + if(!check->ip_addr_str[0]) { + infof(data, + "Connection #%ld is still name resolving, can't reuse\n", + check->connection_id); + continue; + } + } + + if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) || + check->bits.close) { + /* Don't pick a connection that hasn't connected yet or that is going + to get closed. */ + infof(data, "Connection #%ld isn't open enough, can't reuse\n", + check->connection_id); +#ifdef DEBUGBUILD + if(check->recv_pipe->size > 0) { + infof(data, + "BAD! Unconnected #%ld has a non-empty recv pipeline!\n", + check->connection_id); + } +#endif + continue; + } + } + + if((needle->handler->flags&PROTOPT_SSL) != + (check->handler->flags&PROTOPT_SSL)) + /* don't do mixed SSL and non-SSL connections */ + if(!(needle->handler->protocol & check->handler->protocol)) + /* except protocols that have been upgraded via TLS */ + continue; + + if(needle->handler->flags&PROTOPT_SSL) { + if((data->set.ssl.verifypeer != check->verifypeer) || + (data->set.ssl.verifyhost != check->verifyhost)) + continue; + } + + if(needle->bits.proxy != check->bits.proxy) + /* don't do mixed proxy and non-proxy connections */ + continue; + + if(!canPipeline && check->inuse) + /* this request can't be pipelined but the checked connection is + already in use so we skip it */ + continue; + + if(needle->localdev || needle->localport) { + /* If we are bound to a specific local end (IP+port), we must not + re-use a random other one, although if we didn't ask for a + particular one we can reuse one that was bound. + + This comparison is a bit rough and too strict. Since the input + parameters can be specified in numerous ways and still end up the + same it would take a lot of processing to make it really accurate. + Instead, this matching will assume that re-uses of bound connections + will most likely also re-use the exact same binding parameters and + missing out a few edge cases shouldn't hurt anyone very much. + */ + if((check->localport != needle->localport) || + (check->localportrange != needle->localportrange) || + !check->localdev || + !needle->localdev || + strcmp(check->localdev, needle->localdev)) + continue; + } + + if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) +#ifdef USE_NTLM + || (wantNTLMhttp || check->ntlm.state != NTLMSTATE_NONE) +#endif + ) { + /* This protocol requires credentials per connection or is HTTP+NTLM, + so verify that we're using the same name and password as well */ + if(!strequal(needle->user, check->user) || + !strequal(needle->passwd, check->passwd)) { + /* one of them was different */ + continue; + } +#if defined(USE_NTLM) + credentialsMatch = TRUE; +#endif + } + + if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL || + (needle->bits.httpproxy && check->bits.httpproxy && + needle->bits.tunnel_proxy && check->bits.tunnel_proxy && + Curl_raw_equal(needle->proxy.name, check->proxy.name) && + (needle->port == check->port))) { + /* The requested connection does not use a HTTP proxy or it uses SSL or + it is a non-SSL protocol tunneled over the same http proxy name and + port number or it is a non-SSL protocol which is allowed to be + upgraded via TLS */ + + if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) || + needle->handler->protocol & check->handler->protocol) && + Curl_raw_equal(needle->host.name, check->host.name) && + needle->remote_port == check->remote_port) { + if(needle->handler->flags & PROTOPT_SSL) { + /* This is a SSL connection so verify that we're using the same + SSL options as well */ + if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) { + DEBUGF(infof(data, + "Connection #%ld has different SSL parameters, " + "can't reuse\n", + check->connection_id)); + continue; + } + else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) { + DEBUGF(infof(data, + "Connection #%ld has not started SSL connect, " + "can't reuse\n", + check->connection_id)); + continue; + } + } + match = TRUE; + } + } + else { /* The requested needle connection is using a proxy, + is the checked one using the same host, port and type? */ + if(check->bits.proxy && + (needle->proxytype == check->proxytype) && + (needle->bits.tunnel_proxy == check->bits.tunnel_proxy) && + Curl_raw_equal(needle->proxy.name, check->proxy.name) && + needle->port == check->port) { + /* This is the same proxy connection, use it! */ + match = TRUE; + } + } + + if(match) { +#if defined(USE_NTLM) + /* If we are looking for an HTTP+NTLM connection, check if this is + already authenticating with the right credentials. If not, keep + looking so that we can reuse NTLM connections if + possible. (Especially we must not reuse the same connection if + partway through a handshake!) */ + if(wantNTLMhttp) { + if(credentialsMatch && check->ntlm.state != NTLMSTATE_NONE) { + chosen = check; + + /* We must use this connection, no other */ + *force_reuse = TRUE; + break; + } + else if(credentialsMatch) + /* this is a backup choice */ + chosen = check; + continue; + } +#endif + + if(canPipeline) { + /* We can pipeline if we want to. Let's continue looking for + the optimal connection to use, i.e the shortest pipe that is not + blacklisted. */ + + if(pipeLen == 0) { + /* We have the optimal connection. Let's stop looking. */ + chosen = check; + break; + } + + /* We can't use the connection if the pipe is full */ + if(pipeLen >= max_pipe_len) + continue; + + /* We can't use the connection if the pipe is penalized */ + if(Curl_pipeline_penalized(data, check)) + continue; + + if(pipeLen < best_pipe_len) { + /* This connection has a shorter pipe so far. We'll pick this + and continue searching */ + chosen = check; + best_pipe_len = pipeLen; + continue; + } + } + else { + /* We have found a connection. Let's stop searching. */ + chosen = check; + break; + } + } + } + } + + if(chosen) { + *usethis = chosen; + return TRUE; /* yes, we found one to use! */ + } + + return FALSE; /* no matching connecting exists */ +} + +/* Mark the connection as 'idle', or close it if the cache is full. + Returns TRUE if the connection is kept, or FALSE if it was closed. */ +static bool +ConnectionDone(struct SessionHandle *data, struct connectdata *conn) +{ + /* data->multi->maxconnects can be negative, deal with it. */ + size_t maxconnects = + (data->multi->maxconnects < 0) ? data->multi->num_easy * 4: + data->multi->maxconnects; + struct connectdata *conn_candidate = NULL; + + /* Mark the current connection as 'unused' */ + conn->inuse = FALSE; + + if(maxconnects > 0 && + data->state.conn_cache->num_connections > maxconnects) { + infof(data, "Connection cache is full, closing the oldest one.\n"); + + conn_candidate = find_oldest_idle_connection(data); + + if(conn_candidate) { + /* Set the connection's owner correctly */ + conn_candidate->data = data; + + /* the winner gets the honour of being disconnected */ + (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE); + } + } + + return (conn_candidate == conn) ? FALSE : TRUE; +} + +/* + * The given input connection struct pointer is to be stored in the connection + * cache. If the cache is already full, least interesting existing connection + * (if any) gets closed. + * + * The given connection should be unique. That must've been checked prior to + * this call. + */ +static CURLcode ConnectionStore(struct SessionHandle *data, + struct connectdata *conn) +{ + return Curl_conncache_add_conn(data->state.conn_cache, conn); +} + +/* after a TCP connection to the proxy has been verified, this function does + the next magic step. + + Note: this function's sub-functions call failf() + +*/ +CURL_STATIC CURLcode Curl_connected_proxy(struct connectdata *conn, + int sockindex) +{ + if(!conn->bits.proxy || sockindex) + /* this magic only works for the primary socket as the secondary is used + for FTP only and it has FTP specific magic in ftp.c */ + return CURLE_OK; + + switch(conn->proxytype) { +#ifndef CURL_DISABLE_PROXY + case CURLPROXY_SOCKS5: + case CURLPROXY_SOCKS5_HOSTNAME: + return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, + conn->host.name, conn->remote_port, + FIRSTSOCKET, conn); + + case CURLPROXY_SOCKS4: + return Curl_SOCKS4(conn->proxyuser, conn->host.name, + conn->remote_port, FIRSTSOCKET, conn, FALSE); + + case CURLPROXY_SOCKS4A: + return Curl_SOCKS4(conn->proxyuser, conn->host.name, + conn->remote_port, FIRSTSOCKET, conn, TRUE); + +#endif /* CURL_DISABLE_PROXY */ + case CURLPROXY_HTTP: + case CURLPROXY_HTTP_1_0: + /* do nothing here. handled later. */ + break; + default: + break; + } /* switch proxytype */ + + return CURLE_OK; +} + +/* + * verboseconnect() displays verbose information after a connect + */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS +CURL_STATIC void Curl_verboseconnect(struct connectdata *conn) +{ + if(conn->data->set.verbose) + infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", + conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname, + conn->ip_addr_str, conn->port, conn->connection_id); +} +#endif + +CURL_STATIC int Curl_protocol_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn->handler->proto_getsock) + return conn->handler->proto_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} + +CURL_STATIC int Curl_doing_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn && conn->handler->doing_getsock) + return conn->handler->doing_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} + +/* + * We are doing protocol-specific connecting and this is being called over and + * over from the multi interface until the connection phase is done on + * protocol layer. + */ + +CURL_STATIC CURLcode Curl_protocol_connecting(struct connectdata *conn, + bool *done) +{ + CURLcode result=CURLE_OK; + + if(conn && conn->handler->connecting) { + *done = FALSE; + result = conn->handler->connecting(conn, done); + } + else + *done = TRUE; + + return result; +} + +/* + * We are DOING this is being called over and over from the multi interface + * until the DOING phase is done on protocol layer. + */ + +CURL_STATIC CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done) +{ + CURLcode result=CURLE_OK; + + if(conn && conn->handler->doing) { + *done = FALSE; + result = conn->handler->doing(conn, done); + } + else + *done = TRUE; + + return result; +} + +/* + * We have discovered that the TCP connection has been successful, we can now + * proceed with some action. + * + */ +CURL_STATIC CURLcode Curl_protocol_connect(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result=CURLE_OK; + + *protocol_done = FALSE; + + if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) { + /* We already are connected, get back. This may happen when the connect + worked fine in the first call, like when we connect to a local server + or proxy. Note that we don't know if the protocol is actually done. + + Unless this protocol doesn't have any protocol-connect callback, as + then we know we're done. */ + if(!conn->handler->connecting) + *protocol_done = TRUE; + + return CURLE_OK; + } + + if(!conn->bits.protoconnstart) { + + result = Curl_proxy_connect(conn); + if(result) + return result; + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && + (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE)) + /* when using an HTTP tunnel proxy, await complete tunnel establishment + before proceeding further. Return CURLE_OK so we'll be called again */ + return CURLE_OK; + + if(conn->handler->connect_it) { + /* is there a protocol-specific connect() procedure? */ + + /* Call the protocol-specific connect function */ + result = conn->handler->connect_it(conn, protocol_done); + } + else + *protocol_done = TRUE; + + /* it has started, possibly even completed but that knowledge isn't stored + in this bit! */ + if(!result) + conn->bits.protoconnstart = TRUE; + } + + return result; /* pass back status */ +} + +/* + * Helpers for IDNA convertions. + */ +static bool is_ASCII_name(const char *hostname) +{ + const unsigned char *ch = (const unsigned char*)hostname; + + while(*ch) { + if(*ch++ & 0x80) + return FALSE; + } + return TRUE; +} + +#ifdef USE_LIBIDN +/* + * Check if characters in hostname is allowed in Top Level Domain. + */ +static bool tld_check_name(struct SessionHandle *data, + const char *ace_hostname) +{ + size_t err_pos; + char *uc_name = NULL; + int rc; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + const char *tld_errmsg = ""; +#else + (void)data; +#endif + + /* Convert (and downcase) ACE-name back into locale's character set */ + rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0); + if(rc != IDNA_SUCCESS) + return FALSE; + + rc = tld_check_lz(uc_name, &err_pos, NULL); +#ifndef CURL_DISABLE_VERBOSE_STRINGS +#ifdef HAVE_TLD_STRERROR + if(rc != TLD_SUCCESS) + tld_errmsg = tld_strerror((Tld_rc)rc); +#endif + if(rc == TLD_INVALID) + infof(data, "WARNING: %s; pos %u = `%c'/0x%02X\n", + tld_errmsg, err_pos, uc_name[err_pos], + uc_name[err_pos] & 255); + else if(rc != TLD_SUCCESS) + infof(data, "WARNING: TLD check for %s failed; %s\n", + uc_name, tld_errmsg); +#endif /* CURL_DISABLE_VERBOSE_STRINGS */ + if(uc_name) + idn_free(uc_name); + if(rc != TLD_SUCCESS) + return FALSE; + + return TRUE; +} +#endif + +/* + * Perform any necessary IDN conversion of hostname + */ +static void fix_hostname(struct SessionHandle *data, + struct connectdata *conn, struct hostname *host) +{ + size_t len; + +#ifndef USE_LIBIDN + (void)data; + (void)conn; +#elif defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)conn; +#endif + + /* set the name we use to display the host name */ + host->dispname = host->name; + + len = strlen(host->name); + if(len && (host->name[len-1] == '.')) + /* strip off a single trailing dot if present, primarily for SNI but + there's no use for it */ + host->name[len-1]=0; + + if(!is_ASCII_name(host->name)) { +#ifdef USE_LIBIDN + /************************************************************* + * Check name for non-ASCII and convert hostname to ACE form. + *************************************************************/ + if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) { + char *ace_hostname = NULL; + int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0); + infof (data, "Input domain encoded as `%s'\n", + stringprep_locale_charset ()); + if(rc != IDNA_SUCCESS) + infof(data, "Failed to convert %s to ACE; %s\n", + host->name, Curl_idn_strerror(conn, rc)); + else { + /* tld_check_name() displays a warning if the host name contains + "illegal" characters for this TLD */ + (void)tld_check_name(data, ace_hostname); + + host->encalloc = ace_hostname; + /* change the name pointer to point to the encoded hostname */ + host->name = host->encalloc; + } + } +#elif defined(USE_WIN32_IDN) + /************************************************************* + * Check name for non-ASCII and convert hostname to ACE form. + *************************************************************/ + char *ace_hostname = NULL; + int rc = curl_win32_idn_to_ascii(host->name, &ace_hostname); + if(rc == 0) + infof(data, "Failed to convert %s to ACE;\n", + host->name); + else { + host->encalloc = ace_hostname; + /* change the name pointer to point to the encoded hostname */ + host->name = host->encalloc; + } +#else + infof(data, "IDN support not present, can't parse Unicode domains\n"); +#endif + } +} + +static void llist_dtor(void *user, void *element) +{ + (void)user; + (void)element; + /* Do nothing */ +} + +/* + * Allocate and initialize a new connectdata object. + */ +static struct connectdata *allocate_conn(struct SessionHandle *data) +{ + struct connectdata *conn = calloc(1, sizeof(struct connectdata)); + if(!conn) + return NULL; + + conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined + already from start to avoid NULL + situations and checks */ + + /* and we setup a few fields in case we end up actually using this struct */ + + conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->connection_id = -1; /* no ID */ + conn->port = -1; /* unknown at this point */ + conn->remote_port = -1; /* unknown */ + + /* Default protocol-independent behavior doesn't support persistent + connections, so we set this to force-close. Protocols that support + this need to set this to FALSE in their "curl_do" functions. */ + connclose(conn, "Default to force-close"); + + /* Store creation time to help future close decision making */ + conn->created = Curl_tvnow(); + + conn->data = data; /* Setup the association between this connection + and the SessionHandle */ + + conn->proxytype = data->set.proxytype; /* type */ + +#ifdef CURL_DISABLE_PROXY + + conn->bits.proxy = FALSE; + conn->bits.httpproxy = FALSE; + conn->bits.proxy_user_passwd = FALSE; + conn->bits.tunnel_proxy = FALSE; + +#else /* CURL_DISABLE_PROXY */ + + /* note that these two proxy bits are now just on what looks to be + requested, they may be altered down the road */ + conn->bits.proxy = (data->set.str[STRING_PROXY] && + *data->set.str[STRING_PROXY])?TRUE:FALSE; + conn->bits.httpproxy = (conn->bits.proxy && + (conn->proxytype == CURLPROXY_HTTP || + conn->proxytype == CURLPROXY_HTTP_1_0))?TRUE:FALSE; + conn->bits.proxy_user_passwd = + (NULL != data->set.str[STRING_PROXYUSERNAME])?TRUE:FALSE; + conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; + +#endif /* CURL_DISABLE_PROXY */ + + conn->bits.user_passwd = (NULL != data->set.str[STRING_USERNAME])?TRUE:FALSE; + conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; + conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; + + conn->verifypeer = data->set.ssl.verifypeer; + conn->verifyhost = data->set.ssl.verifyhost; + + conn->ip_version = data->set.ipver; + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; + conn->ntlm_auth_hlpr_pid = 0; + conn->challenge_header = NULL; + conn->response_header = NULL; +#endif + + if(Curl_multi_pipeline_enabled(data->multi) && + !conn->master_buffer) { + /* Allocate master_buffer to be used for pipelining */ + conn->master_buffer = calloc(BUFSIZE, sizeof (char)); + if(!conn->master_buffer) + goto error; + } + + /* Initialize the pipeline lists */ + conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); + conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); + if(!conn->send_pipe || !conn->recv_pipe) + goto error; + +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CLEAR; +#endif + + /* Store the local bind parameters that will be used for this connection */ + if(data->set.str[STRING_DEVICE]) { + conn->localdev = strdup(data->set.str[STRING_DEVICE]); + if(!conn->localdev) + goto error; + } + conn->localportrange = data->set.localportrange; + conn->localport = data->set.localport; + + /* the close socket stuff needs to be copied to the connection struct as + it may live on without (this specific) SessionHandle */ + conn->fclosesocket = data->set.fclosesocket; + conn->closesocket_client = data->set.closesocket_client; + + return conn; + error: + + Curl_llist_destroy(conn->send_pipe, NULL); + Curl_llist_destroy(conn->recv_pipe, NULL); + + conn->send_pipe = NULL; + conn->recv_pipe = NULL; + + free(conn->master_buffer); + free(conn->localdev); + free(conn); + return NULL; +} + +static CURLcode findprotocol(struct SessionHandle *data, + struct connectdata *conn, + const char *protostr) +{ + const struct Curl_handler * const *pp; + const struct Curl_handler *p; + + /* Scan protocol handler table and match against 'protostr' to set a few + variables based on the URL. Now that the handler may be changed later + when the protocol specific setup function is called. */ + for(pp = protocols; (p = *pp) != NULL; pp++) { + if(Curl_raw_equal(p->scheme, protostr)) { + /* Protocol found in table. Check if allowed */ + if(!(data->set.allowed_protocols & p->protocol)) + /* nope, get out */ + break; + + /* it is allowed for "normal" request, now do an extra check if this is + the result of a redirect */ + if(data->state.this_is_a_follow && + !(data->set.redir_protocols & p->protocol)) + /* nope, get out */ + break; + + /* Perform setup complement if some. */ + conn->handler = conn->given = p; + + /* 'port' and 'remote_port' are set in setup_connection_internals() */ + return CURLE_OK; + } + } + + + /* The protocol was not found in the table, but we don't have to assign it + to anything since it is already assigned to a dummy-struct in the + create_conn() function when the connectdata struct is allocated. */ + failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME, + protostr); + + return CURLE_UNSUPPORTED_PROTOCOL; +} + +/* + * Parse URL and fill in the relevant members of the connection struct. + */ +static CURLcode parseurlandfillconn(struct SessionHandle *data, + struct connectdata *conn, + bool *prot_missing, + char **userp, char **passwdp, + char **optionsp) +{ + char *at; + char *fragment; + char *path = data->state.path; + char *query; + int rc; + char protobuf[16] = ""; + const char *protop = ""; + CURLcode result; + bool rebuild_url = FALSE; + + *prot_missing = FALSE; + + /* We might pass the entire URL into the request so we need to make sure + * there are no bad characters in there.*/ + if(strpbrk(data->change.url, "\r\n")) { + failf(data, "Illegal characters found in URL"); + return CURLE_URL_MALFORMAT; + } + + /************************************************************* + * Parse the URL. + * + * We need to parse the url even when using the proxy, because we will need + * the hostname and port in case we are trying to SSL connect through the + * proxy -- and we don't know if we will need to use SSL until we parse the + * url ... + ************************************************************/ + if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]", + protobuf, path)) && + Curl_raw_equal(protobuf, "file")) { + if(path[0] == '/' && path[1] == '/') { + /* Allow omitted hostname (e.g. file:/). This is not strictly + * speaking a valid file: URL by RFC 1738, but treating file:/ as + * file://localhost/ is similar to how other schemes treat missing + * hostnames. See RFC 1808. */ + + /* This cannot be done with strcpy() in a portable manner, since the + memory areas overlap! */ + memmove(path, path + 2, strlen(path + 2)+1); + } + /* + * we deal with file:/// differently since it supports no + * hostname other than "localhost" and "127.0.0.1", which is unique among + * the URL protocols specified in RFC 1738 + */ + if(path[0] != '/') { + /* the URL included a host name, we ignore host names in file:// URLs + as the standards don't define what to do with them */ + char *ptr=strchr(path, '/'); + if(ptr) { + /* there was a slash present + + RFC1738 (section 3.1, page 5) says: + + The rest of the locator consists of data specific to the scheme, + and is known as the "url-path". It supplies the details of how the + specified resource can be accessed. Note that the "/" between the + host (or port) and the url-path is NOT part of the url-path. + + As most agents use file://localhost/foo to get '/foo' although the + slash preceding foo is a separator and not a slash for the path, + a URL as file://localhost//foo must be valid as well, to refer to + the same file with an absolute path. + */ + + if(ptr[1] && ('/' == ptr[1])) + /* if there was two slashes, we skip the first one as that is then + used truly as a separator */ + ptr++; + + /* This cannot be made with strcpy, as the memory chunks overlap! */ + memmove(path, ptr, strlen(ptr)+1); + } + } + + protop = "file"; /* protocol string */ + } + else { + /* clear path */ + path[0]=0; + + if(2 > sscanf(data->change.url, + "%15[^\n:]://%[^\n/?]%[^\n]", + protobuf, + conn->host.name, path)) { + + /* + * The URL was badly formatted, let's try the browser-style _without_ + * protocol specified like 'http://'. + */ + rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path); + if(1 > rc) { + /* + * We couldn't even get this format. + * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is + * assigned, but the return value is EOF! + */ +#if defined(__DJGPP__) && (DJGPP_MINOR == 4) + if(!(rc == -1 && *conn->host.name)) +#endif + { + failf(data, " malformed"); + return CURLE_URL_MALFORMAT; + } + } + + /* + * Since there was no protocol part specified, we guess what protocol it + * is based on the first letters of the server name. + */ + + /* Note: if you add a new protocol, please update the list in + * lib/version.c too! */ + + if(checkprefix("FTP.", conn->host.name)) + protop = "ftp"; + else if(checkprefix("DICT.", conn->host.name)) + protop = "DICT"; + else if(checkprefix("LDAP.", conn->host.name)) + protop = "LDAP"; + else if(checkprefix("IMAP.", conn->host.name)) + protop = "IMAP"; + else if(checkprefix("SMTP.", conn->host.name)) + protop = "smtp"; + else if(checkprefix("POP3.", conn->host.name)) + protop = "pop3"; + else { + protop = "http"; + } + + *prot_missing = TRUE; /* not given in URL */ + } + else + protop = protobuf; + } + + /* We search for '?' in the host name (but only on the right side of a + * @-letter to allow ?-letters in username and password) to handle things + * like http://example.com?param= (notice the missing '/'). + */ + at = strchr(conn->host.name, '@'); + if(at) + query = strchr(at+1, '?'); + else + query = strchr(conn->host.name, '?'); + + if(query) { + /* We must insert a slash before the '?'-letter in the URL. If the URL had + a slash after the '?', that is where the path currently begins and the + '?string' is still part of the host name. + + We must move the trailing part from the host name and put it first in + the path. And have it all prefixed with a slash. + */ + + size_t hostlen = strlen(query); + size_t pathlen = strlen(path); + + /* move the existing path plus the zero byte forward, to make room for + the host-name part */ + memmove(path+hostlen+1, path, pathlen+1); + + /* now copy the trailing host part in front of the existing path */ + memcpy(path+1, query, hostlen); + + path[0]='/'; /* prepend the missing slash */ + rebuild_url = TRUE; + + *query=0; /* now cut off the hostname at the ? */ + } + else if(!path[0]) { + /* if there's no path set, use a single slash */ + strcpy(path, "/"); + rebuild_url = TRUE; + } + + /* If the URL is malformatted (missing a '/' after hostname before path) we + * insert a slash here. The only letter except '/' we accept to start a path + * is '?'. + */ + if(path[0] == '?') { + /* We need this function to deal with overlapping memory areas. We know + that the memory area 'path' points to is 'urllen' bytes big and that + is bigger than the path. Use +1 to move the zero byte too. */ + memmove(&path[1], path, strlen(path)+1); + path[0] = '/'; + rebuild_url = TRUE; + } + else if(!data->set.path_as_is) { + /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */ + char *newp = Curl_dedotdotify(path); + if(!newp) + return CURLE_OUT_OF_MEMORY; + + if(strcmp(newp, path)) { + rebuild_url = TRUE; + free(data->state.pathbuffer); + data->state.pathbuffer = newp; + data->state.path = newp; + path = newp; + } + else + free(newp); + } + + /* + * "rebuild_url" means that one or more URL components have been modified so + * we need to generate an updated full version. We need the corrected URL + * when communicating over HTTP proxy and we don't know at this point if + * we're using a proxy or not. + */ + if(rebuild_url) { + char *reurl; + + size_t plen = strlen(path); /* new path, should be 1 byte longer than + the original */ + size_t urllen = strlen(data->change.url); /* original URL length */ + + size_t prefixlen = strlen(conn->host.name); + + if(!*prot_missing) + prefixlen += strlen(protop) + strlen("://"); + + reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */ + if(!reurl) + return CURLE_OUT_OF_MEMORY; + + /* copy the prefix */ + memcpy(reurl, data->change.url, prefixlen); + + /* append the trailing piece + zerobyte */ + memcpy(&reurl[prefixlen], path, plen + 1); + + /* possible free the old one */ + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + + infof(data, "Rebuilt URL to: %s\n", reurl); + + data->change.url = reurl; + data->change.url_alloc = TRUE; /* free this later */ + } + + /* + * Parse the login details from the URL and strip them out of + * the host name + */ + result = parse_url_login(data, conn, userp, passwdp, optionsp); + if(result) + return result; + + if(conn->host.name[0] == '[') { + /* This looks like an IPv6 address literal. See if there is an address + scope if there is no location header */ + char *percent = strchr(conn->host.name, '%'); + if(percent) { + unsigned int identifier_offset = 3; + char *endp; + unsigned long scope; + if(strncmp("%25", percent, 3) != 0) { + infof(data, + "Please URL encode %% as %%25, see RFC 6874.\n"); + identifier_offset = 1; + } + scope = strtoul(percent + identifier_offset, &endp, 10); + if(*endp == ']') { + /* The address scope was well formed. Knock it out of the + hostname. */ + memmove(percent, endp, strlen(endp)+1); + conn->scope_id = (unsigned int)scope; + } + else { + /* Zone identifier is not numeric */ +#if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX) + char ifname[IFNAMSIZ + 2]; + char *square_bracket; + unsigned int scopeidx = 0; + strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2); + /* Ensure nullbyte termination */ + ifname[IFNAMSIZ + 1] = '\0'; + square_bracket = strchr(ifname, ']'); + if(square_bracket) { + /* Remove ']' */ + *square_bracket = '\0'; + scopeidx = if_nametoindex(ifname); + if(scopeidx == 0) { + infof(data, "Invalid network interface: %s; %s\n", ifname, + strerror(errno)); + } + } + if(scopeidx > 0) { + char *p = percent + identifier_offset + strlen(ifname); + + /* Remove zone identifier from hostname */ + memmove(percent, p, strlen(p) + 1); + conn->scope_id = scopeidx; + } + else +#endif /* HAVE_NET_IF_H && IFNAMSIZ */ + infof(data, "Invalid IPv6 address format\n"); + } + } + } + + if(data->set.scope_id) + /* Override any scope that was set above. */ + conn->scope_id = data->set.scope_id; + + /* Remove the fragment part of the path. Per RFC 2396, this is always the + last part of the URI. We are looking for the first '#' so that we deal + gracefully with non conformant URI such as http://example.com#foo#bar. */ + fragment = strchr(path, '#'); + if(fragment) { + *fragment = 0; + + /* we know the path part ended with a fragment, so we know the full URL + string does too and we need to cut it off from there so it isn't used + over proxy */ + fragment = strchr(data->change.url, '#'); + if(fragment) + *fragment = 0; + } + + /* + * So if the URL was A://B/C#D, + * protop is A + * conn->host.name is B + * data->state.path is /C + */ + + return findprotocol(data, conn, protop); +} + +/* + * If we're doing a resumed transfer, we need to setup our stuff + * properly. + */ +static CURLcode setup_range(struct SessionHandle *data) +{ + struct UrlState *s = &data->state; + s->resume_from = data->set.set_resume_from; + if(s->resume_from || data->set.str[STRING_SET_RANGE]) { + if(s->rangestringalloc) + free(s->range); + + if(s->resume_from) + s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from); + else + s->range = strdup(data->set.str[STRING_SET_RANGE]); + + s->rangestringalloc = (s->range)?TRUE:FALSE; + + if(!s->range) + return CURLE_OUT_OF_MEMORY; + + /* tell ourselves to fetch this range */ + s->use_range = TRUE; /* enable range download */ + } + else + s->use_range = FALSE; /* disable range download */ + + return CURLE_OK; +} + + +/* + * setup_connection_internals() - + * + * Setup connection internals specific to the requested protocol in the + * SessionHandle. This is inited and setup before the connection is made but + * is about the particular protocol that is to be used. + * + * This MUST get called after proxy magic has been figured out. + */ +static CURLcode setup_connection_internals(struct connectdata *conn) +{ + const struct Curl_handler * p; + CURLcode result; + struct SessionHandle *data = conn->data; + + /* in some case in the multi state-machine, we go back to the CONNECT state + and then a second (or third or...) call to this function will be made + without doing a DISCONNECT or DONE in between (since the connection is + yet in place) and therefore this function needs to first make sure + there's no lingering previous data allocated. */ + Curl_free_request_state(data); + + memset(&data->req, 0, sizeof(struct SingleRequest)); + data->req.maxdownload = -1; + + conn->socktype = SOCK_STREAM; /* most of them are TCP streams */ + + /* Perform setup complement if some. */ + p = conn->handler; + + if(p->setup_connection) { + result = (*p->setup_connection)(conn); + + if(result) + return result; + + p = conn->handler; /* May have changed. */ + } + + if(conn->port < 0) + /* we check for -1 here since if proxy was detected already, this + was very likely already set to the proxy port */ + conn->port = p->defport; + + /* only if remote_port was not already parsed off the URL we use the + default port number */ + if(conn->remote_port < 0) + conn->remote_port = (unsigned short)conn->given->defport; + + return CURLE_OK; +} + +/* + * Curl_free_request_state() should free temp data that was allocated in the + * SessionHandle for this single request. + */ + +CURL_STATIC void Curl_free_request_state(struct SessionHandle *data) +{ + Curl_safefree(data->req.protop); + Curl_safefree(data->req.newurl); +} + + +#ifndef CURL_DISABLE_PROXY +/**************************************************************** +* Checks if the host is in the noproxy list. returns true if it matches +* and therefore the proxy should NOT be used. +****************************************************************/ +static bool check_noproxy(const char* name, const char* no_proxy) +{ + /* no_proxy=domain1.dom,host.domain2.dom + * (a comma-separated list of hosts which should + * not be proxied, or an asterisk to override + * all proxy variables) + */ + size_t tok_start; + size_t tok_end; + const char* separator = ", "; + size_t no_proxy_len; + size_t namelen; + char *endptr; + + if(no_proxy && no_proxy[0]) { + if(Curl_raw_equal("*", no_proxy)) { + return TRUE; + } + + /* NO_PROXY was specified and it wasn't just an asterisk */ + + no_proxy_len = strlen(no_proxy); + endptr = strchr(name, ':'); + if(endptr) + namelen = endptr - name; + else + namelen = strlen(name); + + for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) { + while(tok_start < no_proxy_len && + strchr(separator, no_proxy[tok_start]) != NULL) { + /* Look for the beginning of the token. */ + ++tok_start; + } + + if(tok_start == no_proxy_len) + break; /* It was all trailing separator chars, no more tokens. */ + + for(tok_end = tok_start; tok_end < no_proxy_len && + strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end) + /* Look for the end of the token. */ + ; + + /* To match previous behaviour, where it was necessary to specify + * ".local.com" to prevent matching "notlocal.com", we will leave + * the '.' off. + */ + if(no_proxy[tok_start] == '.') + ++tok_start; + + if((tok_end - tok_start) <= namelen) { + /* Match the last part of the name to the domain we are checking. */ + const char *checkn = name + namelen - (tok_end - tok_start); + if(Curl_raw_nequal(no_proxy + tok_start, checkn, + tok_end - tok_start)) { + if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') { + /* We either have an exact match, or the previous character is a . + * so it is within the same domain, so no proxy for this host. + */ + return TRUE; + } + } + } /* if((tok_end - tok_start) <= namelen) */ + } /* for(tok_start = 0; tok_start < no_proxy_len; + tok_start = tok_end + 1) */ + } /* NO_PROXY was specified and it wasn't just an asterisk */ + + return FALSE; +} + +/**************************************************************** +* Detect what (if any) proxy to use. Remember that this selects a host +* name and is not limited to HTTP proxies only. +* The returned pointer must be freed by the caller (unless NULL) +****************************************************************/ +static char *detect_proxy(struct connectdata *conn) +{ + char *proxy = NULL; + +#ifndef CURL_DISABLE_HTTP + /* If proxy was not specified, we check for default proxy environment + * variables, to enable i.e Lynx compliance: + * + * http_proxy=http://some.server.dom:port/ + * https_proxy=http://some.server.dom:port/ + * ftp_proxy=http://some.server.dom:port/ + * no_proxy=domain1.dom,host.domain2.dom + * (a comma-separated list of hosts which should + * not be proxied, or an asterisk to override + * all proxy variables) + * all_proxy=http://some.server.dom:port/ + * (seems to exist for the CERN www lib. Probably + * the first to check for.) + * + * For compatibility, the all-uppercase versions of these variables are + * checked if the lowercase versions don't exist. + */ + char *no_proxy=NULL; + char proxy_env[128]; + + no_proxy=curl_getenv("no_proxy"); + if(!no_proxy) + no_proxy=curl_getenv("NO_PROXY"); + + if(!check_noproxy(conn->host.name, no_proxy)) { + /* It was not listed as without proxy */ + const char *protop = conn->handler->scheme; + char *envp = proxy_env; + char *prox; + + /* Now, build _proxy and check for such a one to use */ + while(*protop) + *envp++ = (char)tolower((int)*protop++); + + /* append _proxy */ + strcpy(envp, "_proxy"); + + /* read the protocol proxy: */ + prox=curl_getenv(proxy_env); + + /* + * We don't try the uppercase version of HTTP_PROXY because of + * security reasons: + * + * When curl is used in a webserver application + * environment (cgi or php), this environment variable can + * be controlled by the web server user by setting the + * http header 'Proxy:' to some value. + * + * This can cause 'internal' http/ftp requests to be + * arbitrarily redirected by any external attacker. + */ + if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) { + /* There was no lowercase variable, try the uppercase version: */ + Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env)); + prox=curl_getenv(proxy_env); + } + + if(prox) + proxy = prox; /* use this */ + else { + proxy = curl_getenv("all_proxy"); /* default proxy to use */ + if(!proxy) + proxy=curl_getenv("ALL_PROXY"); + } + } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified + non-proxy */ + free(no_proxy); + +#else /* !CURL_DISABLE_HTTP */ + + (void)conn; +#endif /* CURL_DISABLE_HTTP */ + + return proxy; +} + +/* + * If this is supposed to use a proxy, we need to figure out the proxy + * host name, so that we can re-use an existing connection + * that may exist registered to the same proxy host. + * proxy will be freed before this function returns. + */ +static CURLcode parse_proxy(struct SessionHandle *data, + struct connectdata *conn, char *proxy) +{ + char *prox_portno; + char *endofprot; + + /* We use 'proxyptr' to point to the proxy name from now on... */ + char *proxyptr; + char *portptr; + char *atsign; + + /* We do the proxy host string parsing here. We want the host name and the + * port name. Accept a protocol:// prefix + */ + + /* Parse the protocol part if present */ + endofprot = strstr(proxy, "://"); + if(endofprot) { + proxyptr = endofprot+3; + if(checkprefix("socks5h", proxy)) + conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME; + else if(checkprefix("socks5", proxy)) + conn->proxytype = CURLPROXY_SOCKS5; + else if(checkprefix("socks4a", proxy)) + conn->proxytype = CURLPROXY_SOCKS4A; + else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy)) + conn->proxytype = CURLPROXY_SOCKS4; + /* Any other xxx:// : change to http proxy */ + } + else + proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */ + + /* Is there a username and password given in this proxy url? */ + atsign = strchr(proxyptr, '@'); + if(atsign) { + char *proxyuser = NULL; + char *proxypasswd = NULL; + CURLcode result = + parse_login_details(proxyptr, atsign - proxyptr, + &proxyuser, &proxypasswd, NULL); + if(!result) { + /* found user and password, rip them out. note that we are + unescaping them, as there is otherwise no way to have a + username or password with reserved characters like ':' in + them. */ + Curl_safefree(conn->proxyuser); + if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH) + conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL); + else + conn->proxyuser = strdup(""); + + if(!conn->proxyuser) + result = CURLE_OUT_OF_MEMORY; + else { + Curl_safefree(conn->proxypasswd); + if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH) + conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL); + else + conn->proxypasswd = strdup(""); + + if(!conn->proxypasswd) + result = CURLE_OUT_OF_MEMORY; + } + + if(!result) { + conn->bits.proxy_user_passwd = TRUE; /* enable it */ + atsign++; /* the right side of the @-letter */ + + proxyptr = atsign; /* now use this instead */ + } + } + + free(proxyuser); + free(proxypasswd); + + if(result) + return result; + } + + /* start scanning for port number at this point */ + portptr = proxyptr; + + /* detect and extract RFC6874-style IPv6-addresses */ + if(*proxyptr == '[') { + char *ptr = ++proxyptr; /* advance beyond the initial bracket */ + while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.'))) + ptr++; + if(*ptr == '%') { + /* There might be a zone identifier */ + if(strncmp("%25", ptr, 3)) + infof(data, "Please URL encode %% as %%25, see RFC 6874.\n"); + ptr++; + /* Allow unresered characters as defined in RFC 3986 */ + while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') || + (*ptr == '.') || (*ptr == '_') || (*ptr == '~'))) + ptr++; + } + if(*ptr == ']') + /* yeps, it ended nicely with a bracket as well */ + *ptr++ = 0; + else + infof(data, "Invalid IPv6 address format\n"); + portptr = ptr; + /* Note that if this didn't end with a bracket, we still advanced the + * proxyptr first, but I can't see anything wrong with that as no host + * name nor a numeric can legally start with a bracket. + */ + } + + /* Get port number off proxy.server.com:1080 */ + prox_portno = strchr(portptr, ':'); + if(prox_portno) { + *prox_portno = 0x0; /* cut off number from host name */ + prox_portno ++; + /* now set the local port number */ + conn->port = strtol(prox_portno, NULL, 10); + } + else { + if(proxyptr[0]=='/') + /* If the first character in the proxy string is a slash, fail + immediately. The following code will otherwise clear the string which + will lead to code running as if no proxy was set! */ + return CURLE_COULDNT_RESOLVE_PROXY; + + /* without a port number after the host name, some people seem to use + a slash so we strip everything from the first slash */ + atsign = strchr(proxyptr, '/'); + if(atsign) + *atsign = 0x0; /* cut off path part from host name */ + + if(data->set.proxyport) + /* None given in the proxy string, then get the default one if it is + given */ + conn->port = data->set.proxyport; + } + + /* now, clone the cleaned proxy host name */ + conn->proxy.rawalloc = strdup(proxyptr); + conn->proxy.name = conn->proxy.rawalloc; + + if(!conn->proxy.rawalloc) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +/* + * Extract the user and password from the authentication string + */ +static CURLcode parse_proxy_auth(struct SessionHandle *data, + struct connectdata *conn) +{ + char proxyuser[MAX_CURL_USER_LENGTH]=""; + char proxypasswd[MAX_CURL_PASSWORD_LENGTH]=""; + + if(data->set.str[STRING_PROXYUSERNAME] != NULL) { + strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME], + MAX_CURL_USER_LENGTH); + proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/ + } + if(data->set.str[STRING_PROXYPASSWORD] != NULL) { + strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD], + MAX_CURL_PASSWORD_LENGTH); + proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/ + } + + conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL); + if(!conn->proxyuser) + return CURLE_OUT_OF_MEMORY; + + conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL); + if(!conn->proxypasswd) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} +#endif /* CURL_DISABLE_PROXY */ + +/* + * parse_url_login() + * + * Parse the login details (user name, password and options) from the URL and + * strip them out of the host name + * + * Inputs: data->set.use_netrc (CURLOPT_NETRC) + * conn->host.name + * + * Outputs: (almost :- all currently undefined) + * conn->bits.user_passwd - non-zero if non-default passwords exist + * user - non-zero length if defined + * passwd - non-zero length if defined + * options - non-zero length if defined + * conn->host.name - remove user name and password + */ +static CURLcode parse_url_login(struct SessionHandle *data, + struct connectdata *conn, + char **user, char **passwd, char **options) +{ + CURLcode result = CURLE_OK; + char *userp = NULL; + char *passwdp = NULL; + char *optionsp = NULL; + + /* At this point, we're hoping all the other special cases have + * been taken care of, so conn->host.name is at most + * [user[:password][;options]]@]hostname + * + * We need somewhere to put the embedded details, so do that first. + */ + + char *ptr = strchr(conn->host.name, '@'); + char *login = conn->host.name; + + DEBUGASSERT(!**user); + DEBUGASSERT(!**passwd); + DEBUGASSERT(!**options); + + if(!ptr) + goto out; + + /* We will now try to extract the + * possible login information in a string like: + * ftp://user:password@ftp.my.site:8021/README */ + conn->host.name = ++ptr; + + /* So the hostname is sane. Only bother interpreting the + * results if we could care. It could still be wasted + * work because it might be overtaken by the programmatically + * set user/passwd, but doing that first adds more cases here :-( + */ + + if(data->set.use_netrc == CURL_NETRC_REQUIRED) + goto out; + + /* We could use the login information in the URL so extract it */ + result = parse_login_details(login, ptr - login - 1, + &userp, &passwdp, &optionsp); + if(result) + goto out; + + if(userp) { + char *newname; + + /* We have a user in the URL */ + conn->bits.userpwd_in_url = TRUE; + conn->bits.user_passwd = TRUE; /* enable user+password */ + + /* Decode the user */ + newname = curl_easy_unescape(data, userp, 0, NULL); + if(!newname) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + free(*user); + *user = newname; + } + + if(passwdp) { + /* We have a password in the URL so decode it */ + char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL); + if(!newpasswd) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + free(*passwd); + *passwd = newpasswd; + } + + if(optionsp) { + /* We have an options list in the URL so decode it */ + char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL); + if(!newoptions) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + free(*options); + *options = newoptions; + } + + + out: + + free(userp); + free(passwdp); + free(optionsp); + + return result; +} + +/* + * parse_login_details() + * + * This is used to parse a login string for user name, password and options in + * the following formats: + * + * user + * user:password + * user:password;options + * user;options + * user;options:password + * :password + * :password;options + * ;options + * ;options:password + * + * Parameters: + * + * login [in] - The login string. + * len [in] - The length of the login string. + * userp [in/out] - The address where a pointer to newly allocated memory + * holding the user will be stored upon completion. + * passdwp [in/out] - The address where a pointer to newly allocated memory + * holding the password will be stored upon completion. + * optionsp [in/out] - The address where a pointer to newly allocated memory + * holding the options will be stored upon completion. + * + * Returns CURLE_OK on success. + */ +static CURLcode parse_login_details(const char *login, const size_t len, + char **userp, char **passwdp, + char **optionsp) +{ + CURLcode result = CURLE_OK; + char *ubuf = NULL; + char *pbuf = NULL; + char *obuf = NULL; + const char *psep = NULL; + const char *osep = NULL; + size_t ulen; + size_t plen; + size_t olen; + + /* Attempt to find the password separator */ + if(passwdp) { + psep = strchr(login, ':'); + + /* Within the constraint of the login string */ + if(psep >= login + len) + psep = NULL; + } + + /* Attempt to find the options separator */ + if(optionsp) { + osep = strchr(login, ';'); + + /* Within the constraint of the login string */ + if(osep >= login + len) + osep = NULL; + } + + /* Calculate the portion lengths */ + ulen = (psep ? + (size_t)(osep && psep > osep ? osep - login : psep - login) : + (osep ? (size_t)(osep - login) : len)); + plen = (psep ? + (osep && osep > psep ? (size_t)(osep - psep) : + (size_t)(login + len - psep)) - 1 : 0); + olen = (osep ? + (psep && psep > osep ? (size_t)(psep - osep) : + (size_t)(login + len - osep)) - 1 : 0); + + /* Allocate the user portion buffer */ + if(userp && ulen) { + ubuf = malloc(ulen + 1); + if(!ubuf) + result = CURLE_OUT_OF_MEMORY; + } + + /* Allocate the password portion buffer */ + if(!result && passwdp && plen) { + pbuf = malloc(plen + 1); + if(!pbuf) { + free(ubuf); + result = CURLE_OUT_OF_MEMORY; + } + } + + /* Allocate the options portion buffer */ + if(!result && optionsp && olen) { + obuf = malloc(olen + 1); + if(!obuf) { + free(pbuf); + free(ubuf); + result = CURLE_OUT_OF_MEMORY; + } + } + + if(!result) { + /* Store the user portion if necessary */ + if(ubuf) { + memcpy(ubuf, login, ulen); + ubuf[ulen] = '\0'; + Curl_safefree(*userp); + *userp = ubuf; + } + + /* Store the password portion if necessary */ + if(pbuf) { + memcpy(pbuf, psep + 1, plen); + pbuf[plen] = '\0'; + Curl_safefree(*passwdp); + *passwdp = pbuf; + } + + /* Store the options portion if necessary */ + if(obuf) { + memcpy(obuf, osep + 1, olen); + obuf[olen] = '\0'; + Curl_safefree(*optionsp); + *optionsp = obuf; + } + } + + return result; +} + +/************************************************************* + * Figure out the remote port number and fix it in the URL + * + * No matter if we use a proxy or not, we have to figure out the remote + * port number of various reasons. + * + * To be able to detect port number flawlessly, we must not confuse them + * IPv6-specified addresses in the [0::1] style. (RFC2732) + * + * The conn->host.name is currently [user:passwd@]host[:port] where host + * could be a hostname, IPv4 address or IPv6 address. + * + * The port number embedded in the URL is replaced, if necessary. + *************************************************************/ +static CURLcode parse_remote_port(struct SessionHandle *data, + struct connectdata *conn) +{ + char *portptr; + char endbracket; + + /* Note that at this point, the IPv6 address cannot contain any scope + suffix as that has already been removed in the parseurlandfillconn() + function */ + if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c", + &endbracket)) && + (']' == endbracket)) { + /* this is a RFC2732-style specified IP-address */ + conn->bits.ipv6_ip = TRUE; + + conn->host.name++; /* skip over the starting bracket */ + portptr = strchr(conn->host.name, ']'); + if(portptr) { + *portptr++ = '\0'; /* zero terminate, killing the bracket */ + if(':' != *portptr) + portptr = NULL; /* no port number available */ + } + } + else { +#ifdef ENABLE_IPV6 + struct in6_addr in6; + if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) { + /* This is a numerical IPv6 address, meaning this is a wrongly formatted + URL */ + failf(data, "IPv6 numerical address used in URL without brackets"); + return CURLE_URL_MALFORMAT; + } +#endif + + portptr = strrchr(conn->host.name, ':'); + } + + if(data->set.use_port && data->state.allow_port) { + /* if set, we use this and ignore the port possibly given in the URL */ + conn->remote_port = (unsigned short)data->set.use_port; + if(portptr) + *portptr = '\0'; /* cut off the name there anyway - if there was a port + number - since the port number is to be ignored! */ + if(conn->bits.httpproxy) { + /* we need to create new URL with the new port number */ + char *url; + char type[12]=""; + + if(conn->bits.type_set) + snprintf(type, sizeof(type), ";type=%c", + data->set.prefer_ascii?'A': + (data->set.ftp_list_only?'D':'I')); + + /* + * This synthesized URL isn't always right--suffixes like ;type=A are + * stripped off. It would be better to work directly from the original + * URL and simply replace the port part of it. + */ + url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme, + conn->bits.ipv6_ip?"[":"", conn->host.name, + conn->bits.ipv6_ip?"]":"", conn->remote_port, + data->state.slash_removed?"/":"", data->state.path, + type); + if(!url) + return CURLE_OUT_OF_MEMORY; + + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + + data->change.url = url; + data->change.url_alloc = TRUE; + } + } + else if(portptr) { + /* no CURLOPT_PORT given, extract the one from the URL */ + + char *rest; + long port; + + port=strtol(portptr+1, &rest, 10); /* Port number must be decimal */ + + if((port < 0) || (port > 0xffff)) { + /* Single unix standard says port numbers are 16 bits long */ + failf(data, "Port number out of range"); + return CURLE_URL_MALFORMAT; + } + + else if(rest != &portptr[1]) { + *portptr = '\0'; /* cut off the name there */ + conn->remote_port = curlx_ultous(port); + } + else + /* Browser behavior adaptation. If there's a colon with no digits after, + just cut off the name there which makes us ignore the colon and just + use the default port. Firefox and Chrome both do that. */ + *portptr = '\0'; + } + return CURLE_OK; +} + +/* + * Override the login details from the URL with that in the CURLOPT_USERPWD + * option or a .netrc file, if applicable. + */ +static CURLcode override_login(struct SessionHandle *data, + struct connectdata *conn, + char **userp, char **passwdp, char **optionsp) +{ + if(data->set.str[STRING_USERNAME]) { + free(*userp); + *userp = strdup(data->set.str[STRING_USERNAME]); + if(!*userp) + return CURLE_OUT_OF_MEMORY; + } + + if(data->set.str[STRING_PASSWORD]) { + free(*passwdp); + *passwdp = strdup(data->set.str[STRING_PASSWORD]); + if(!*passwdp) + return CURLE_OUT_OF_MEMORY; + } + + if(data->set.str[STRING_OPTIONS]) { + free(*optionsp); + *optionsp = strdup(data->set.str[STRING_OPTIONS]); + if(!*optionsp) + return CURLE_OUT_OF_MEMORY; + } + + conn->bits.netrc = FALSE; + if(data->set.use_netrc != CURL_NETRC_IGNORED) { + int ret = Curl_parsenetrc(conn->host.name, + userp, passwdp, + data->set.str[STRING_NETRC_FILE]); + if(ret > 0) { + infof(data, "Couldn't find host %s in the " + DOT_CHAR "netrc file; using defaults\n", + conn->host.name); + } + else if(ret < 0 ) { + return CURLE_OUT_OF_MEMORY; + } + else { + /* set bits.netrc TRUE to remember that we got the name from a .netrc + file, so that it is safe to use even if we followed a Location: to a + different host or similar. */ + conn->bits.netrc = TRUE; + + conn->bits.user_passwd = TRUE; /* enable user+password */ + } + } + + return CURLE_OK; +} + +/* + * Set the login details so they're available in the connection + */ +static CURLcode set_login(struct connectdata *conn, + const char *user, const char *passwd, + const char *options) +{ + CURLcode result = CURLE_OK; + + /* If our protocol needs a password and we have none, use the defaults */ + if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) { + /* Store the default user */ + conn->user = strdup(CURL_DEFAULT_USER); + + /* Store the default password */ + if(conn->user) + conn->passwd = strdup(CURL_DEFAULT_PASSWORD); + else + conn->passwd = NULL; + + /* This is the default password, so DON'T set conn->bits.user_passwd */ + } + else { + /* Store the user, zero-length if not set */ + conn->user = strdup(user); + + /* Store the password (only if user is present), zero-length if not set */ + if(conn->user) + conn->passwd = strdup(passwd); + else + conn->passwd = NULL; + } + + if(!conn->user || !conn->passwd) + result = CURLE_OUT_OF_MEMORY; + + /* Store the options, null if not set */ + if(!result && options[0]) { + conn->options = strdup(options); + + if(!conn->options) + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + +/************************************************************* + * Resolve the address of the server or proxy + *************************************************************/ +static CURLcode resolve_server(struct SessionHandle *data, + struct connectdata *conn, + bool *async) +{ + CURLcode result=CURLE_OK; + long timeout_ms = Curl_timeleft(data, NULL, TRUE); + + /************************************************************* + * Resolve the name of the server or proxy + *************************************************************/ + if(conn->bits.reuse) + /* We're reusing the connection - no need to resolve anything, and + fix_hostname() was called already in create_conn() for the re-use + case. */ + *async = FALSE; + + else { + /* this is a fresh connect */ + int rc; + struct Curl_dns_entry *hostaddr; + + /* set a pointer to the hostname we display */ + fix_hostname(data, conn, &conn->host); + +#ifdef USE_UNIX_SOCKETS + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + /* Unix domain sockets are local. The host gets ignored, just use the + * specified domain socket address. Do not cache "DNS entries". There is + * no DNS involved and we already have the filesystem path available */ + const char *path = data->set.str[STRING_UNIX_SOCKET_PATH]; + + hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); + if(!hostaddr) + result = CURLE_OUT_OF_MEMORY; + else if((hostaddr->addr = Curl_unix2addr(path)) != NULL) + hostaddr->inuse++; + else { + /* Long paths are not supported for now */ + if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) { + failf(data, "Unix socket path too long: '%s'", path); + result = CURLE_COULDNT_RESOLVE_HOST; + } + else + result = CURLE_OUT_OF_MEMORY; + free(hostaddr); + hostaddr = NULL; + } + } + else +#endif + if(!conn->proxy.name || !*conn->proxy.name) { + /* If not connecting via a proxy, extract the port from the URL, if it is + * there, thus overriding any defaults that might have been set above. */ + conn->port = conn->remote_port; /* it is the same port */ + + /* Resolve target host right on */ + rc = Curl_resolv_timeout(conn, conn->host.name, (int)conn->port, + &hostaddr, timeout_ms); + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + + else if(rc == CURLRESOLV_TIMEDOUT) + result = CURLE_OPERATION_TIMEDOUT; + + else if(!hostaddr) { + failf(data, "Couldn't resolve host '%s'", conn->host.dispname); + result = CURLE_COULDNT_RESOLVE_HOST; + /* don't return yet, we need to clean up the timeout first */ + } + } + else { + /* This is a proxy that hasn't been resolved yet. */ + + /* IDN-fix the proxy name */ + fix_hostname(data, conn, &conn->proxy); + + /* resolve proxy */ + rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port, + &hostaddr, timeout_ms); + + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + + else if(rc == CURLRESOLV_TIMEDOUT) + result = CURLE_OPERATION_TIMEDOUT; + + else if(!hostaddr) { + failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname); + result = CURLE_COULDNT_RESOLVE_PROXY; + /* don't return yet, we need to clean up the timeout first */ + } + } + DEBUGASSERT(conn->dns_entry == NULL); + conn->dns_entry = hostaddr; + } + + return result; +} + +/* + * Cleanup the connection just allocated before we can move along and use the + * previously existing one. All relevant data is copied over and old_conn is + * ready for freeing once this function returns. + */ +static void reuse_conn(struct connectdata *old_conn, + struct connectdata *conn) +{ + free(old_conn->proxy.rawalloc); + + /* free the SSL config struct from this connection struct as this was + allocated in vain and is targeted for destruction */ + Curl_free_ssl_config(&old_conn->ssl_config); + + conn->data = old_conn->data; + + /* get the user+password information from the old_conn struct since it may + * be new for this request even when we re-use an existing connection */ + conn->bits.user_passwd = old_conn->bits.user_passwd; + if(conn->bits.user_passwd) { + /* use the new user name and password though */ + Curl_safefree(conn->user); + Curl_safefree(conn->passwd); + conn->user = old_conn->user; + conn->passwd = old_conn->passwd; + old_conn->user = NULL; + old_conn->passwd = NULL; + } + + conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd; + if(conn->bits.proxy_user_passwd) { + /* use the new proxy user name and proxy password though */ + Curl_safefree(conn->proxyuser); + Curl_safefree(conn->proxypasswd); + conn->proxyuser = old_conn->proxyuser; + conn->proxypasswd = old_conn->proxypasswd; + old_conn->proxyuser = NULL; + old_conn->proxypasswd = NULL; + } + + /* host can change, when doing keepalive with a proxy or if the case is + different this time etc */ + Curl_safefree(conn->host.rawalloc); + conn->host=old_conn->host; + + /* persist connection info in session handle */ + Curl_persistconninfo(conn); + + /* re-use init */ + conn->bits.reuse = TRUE; /* yes, we're re-using here */ + + Curl_safefree(old_conn->user); + Curl_safefree(old_conn->passwd); + Curl_safefree(old_conn->proxyuser); + Curl_safefree(old_conn->proxypasswd); + Curl_safefree(old_conn->localdev); + + Curl_llist_destroy(old_conn->send_pipe, NULL); + Curl_llist_destroy(old_conn->recv_pipe, NULL); + + old_conn->send_pipe = NULL; + old_conn->recv_pipe = NULL; + + Curl_safefree(old_conn->master_buffer); +} + +/** + * create_conn() sets up a new connectdata struct, or re-uses an already + * existing one, and resolves host name. + * + * if this function returns CURLE_OK and *async is set to TRUE, the resolve + * response will be coming asynchronously. If *async is FALSE, the name is + * already resolved. + * + * @param data The sessionhandle pointer + * @param in_connect is set to the next connection data pointer + * @param async is set TRUE when an async DNS resolution is pending + * @see Curl_setup_conn() + * + * *NOTE* this function assigns the conn->data pointer! + */ + +static CURLcode create_conn(struct SessionHandle *data, + struct connectdata **in_connect, + bool *async) +{ + CURLcode result = CURLE_OK; + struct connectdata *conn; + struct connectdata *conn_temp = NULL; + size_t urllen; + char *user = NULL; + char *passwd = NULL; + char *options = NULL; + bool reuse; + char *proxy = NULL; + bool prot_missing = FALSE; + bool no_connections_available = FALSE; + bool force_reuse = FALSE; + size_t max_host_connections = Curl_multi_max_host_connections(data->multi); + size_t max_total_connections = Curl_multi_max_total_connections(data->multi); + + *async = FALSE; + + /************************************************************* + * Check input data + *************************************************************/ + + if(!data->change.url) { + result = CURLE_URL_MALFORMAT; + goto out; + } + + /* First, split up the current URL in parts so that we can use the + parts for checking against the already present connections. In order + to not have to modify everything at once, we allocate a temporary + connection data struct and fill in for comparison purposes. */ + conn = allocate_conn(data); + + if(!conn) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + /* We must set the return variable as soon as possible, so that our + parent can cleanup any possible allocs we may have done before + any failure */ + *in_connect = conn; + + /* This initing continues below, see the comment "Continue connectdata + * initialization here" */ + + /*********************************************************** + * We need to allocate memory to store the path in. We get the size of the + * full URL to be sure, and we need to make it at least 256 bytes since + * other parts of the code will rely on this fact + ***********************************************************/ +#define LEAST_PATH_ALLOC 256 + urllen=strlen(data->change.url); + if(urllen < LEAST_PATH_ALLOC) + urllen=LEAST_PATH_ALLOC; + + /* + * We malloc() the buffers below urllen+2 to make room for 2 possibilities: + * 1 - an extra terminating zero + * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used) + */ + + Curl_safefree(data->state.pathbuffer); + data->state.path = NULL; + + data->state.pathbuffer = malloc(urllen+2); + if(NULL == data->state.pathbuffer) { + result = CURLE_OUT_OF_MEMORY; /* really bad error */ + goto out; + } + data->state.path = data->state.pathbuffer; + + conn->host.rawalloc = malloc(urllen+2); + if(NULL == conn->host.rawalloc) { + Curl_safefree(data->state.pathbuffer); + data->state.path = NULL; + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + conn->host.name = conn->host.rawalloc; + conn->host.name[0] = 0; + + user = strdup(""); + passwd = strdup(""); + options = strdup(""); + if(!user || !passwd || !options) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd, + &options); + if(result) + goto out; + + /************************************************************* + * No protocol part in URL was used, add it! + *************************************************************/ + if(prot_missing) { + /* We're guessing prefixes here and if we're told to use a proxy or if + we're gonna follow a Location: later or... then we need the protocol + part added so that we have a valid URL. */ + char *reurl; + + reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url); + + if(!reurl) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + + data->change.url = reurl; + data->change.url_alloc = TRUE; /* free this later */ + } + + /************************************************************* + * If the protocol can't handle url query strings, then cut + * off the unhandable part + *************************************************************/ + if((conn->given->flags&PROTOPT_NOURLQUERY)) { + char *path_q_sep = strchr(conn->data->state.path, '?'); + if(path_q_sep) { + /* according to rfc3986, allow the query (?foo=bar) + also on protocols that can't handle it. + + cut the string-part after '?' + */ + + /* terminate the string */ + path_q_sep[0] = 0; + } + } + + if(data->set.str[STRING_BEARER]) { + conn->xoauth2_bearer = strdup(data->set.str[STRING_BEARER]); + if(!conn->xoauth2_bearer) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + +#ifndef CURL_DISABLE_PROXY + /************************************************************* + * Extract the user and password from the authentication string + *************************************************************/ + if(conn->bits.proxy_user_passwd) { + result = parse_proxy_auth(data, conn); + if(result) + goto out; + } + + /************************************************************* + * Detect what (if any) proxy to use + *************************************************************/ + if(data->set.str[STRING_PROXY]) { + proxy = strdup(data->set.str[STRING_PROXY]); + /* if global proxy is set, this is it */ + if(NULL == proxy) { + failf(data, "memory shortage"); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + + if(data->set.str[STRING_NOPROXY] && + check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) { + free(proxy); /* proxy is in exception list */ + proxy = NULL; + } + else if(!proxy) + proxy = detect_proxy(conn); + +#ifdef USE_UNIX_SOCKETS + if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) { + free(proxy); /* Unix domain sockets cannot be proxied, so disable it */ + proxy = NULL; + } +#endif + + if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) { + free(proxy); /* Don't bother with an empty proxy string or if the + protocol doesn't work with network */ + proxy = NULL; + } + + /*********************************************************************** + * If this is supposed to use a proxy, we need to figure out the proxy host + * name, proxy type and port number, so that we can re-use an existing + * connection that may exist registered to the same proxy host. + ***********************************************************************/ + if(proxy) { + result = parse_proxy(data, conn, proxy); + + free(proxy); /* parse_proxy copies the proxy string */ + proxy = NULL; + + if(result) + goto out; + + if((conn->proxytype == CURLPROXY_HTTP) || + (conn->proxytype == CURLPROXY_HTTP_1_0)) { +#ifdef CURL_DISABLE_HTTP + /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ + result = CURLE_UNSUPPORTED_PROTOCOL; + goto out; +#else + /* force this connection's protocol to become HTTP if not already + compatible - if it isn't tunneling through */ + if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) && + !conn->bits.tunnel_proxy) + conn->handler = &Curl_handler_http; + + conn->bits.httpproxy = TRUE; +#endif + } + else + conn->bits.httpproxy = FALSE; /* not a HTTP proxy */ + conn->bits.proxy = TRUE; + } + else { + /* we aren't using the proxy after all... */ + conn->bits.proxy = FALSE; + conn->bits.httpproxy = FALSE; + conn->bits.proxy_user_passwd = FALSE; + conn->bits.tunnel_proxy = FALSE; + } + +#endif /* CURL_DISABLE_PROXY */ + + /************************************************************* + * If the protocol is using SSL and HTTP proxy is used, we set + * the tunnel_proxy bit. + *************************************************************/ + if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy) + conn->bits.tunnel_proxy = TRUE; + + /************************************************************* + * Figure out the remote port number and fix it in the URL + *************************************************************/ + result = parse_remote_port(data, conn); + if(result) + goto out; + + /* Check for overridden login details and set them accordingly so they + they are known when protocol->setup_connection is called! */ + result = override_login(data, conn, &user, &passwd, &options); + if(result) + goto out; + result = set_login(conn, user, passwd, options); + if(result) + goto out; + + /************************************************************* + * Setup internals depending on protocol. Needs to be done after + * we figured out what/if proxy to use. + *************************************************************/ + result = setup_connection_internals(conn); + if(result) + goto out; + + conn->recv[FIRSTSOCKET] = Curl_recv_plain; + conn->send[FIRSTSOCKET] = Curl_send_plain; + conn->recv[SECONDARYSOCKET] = Curl_recv_plain; + conn->send[SECONDARYSOCKET] = Curl_send_plain; + + /*********************************************************************** + * file: is a special case in that it doesn't need a network connection + ***********************************************************************/ +#ifndef CURL_DISABLE_FILE + if(conn->handler->flags & PROTOPT_NONETWORK) { + bool done; + /* this is supposed to be the connect function so we better at least check + that the file is present here! */ + DEBUGASSERT(conn->handler->connect_it); + result = conn->handler->connect_it(conn, &done); + + /* Setup a "faked" transfer that'll do nothing */ + if(!result) { + conn->data = data; + conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */ + + ConnectionStore(data, conn); + + /* + * Setup whatever necessary for a resumed transfer + */ + result = setup_range(data); + if(result) { + DEBUGASSERT(conn->handler->done); + /* we ignore the return code for the protocol-specific DONE */ + (void)conn->handler->done(conn, result, FALSE); + goto out; + } + + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ + -1, NULL); /* no upload */ + } + + /* since we skip do_init() */ + do_init(conn); + + goto out; + } +#endif + + /* Get a cloned copy of the SSL config situation stored in the + connection struct. But to get this going nicely, we must first make + sure that the strings in the master copy are pointing to the correct + strings in the session handle strings array! + + Keep in mind that the pointers in the master copy are pointing to strings + that will be freed as part of the SessionHandle struct, but all cloned + copies will be separately allocated. + */ + data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH]; + data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE]; + data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE]; + data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; + data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST]; +#ifdef USE_TLS_SRP + data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME]; + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; +#endif + + if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + prune_dead_connections(data); + + /************************************************************* + * Check the current list of connections to see if we can + * re-use an already existing one or if we have to create a + * new one. + *************************************************************/ + + /* reuse_fresh is TRUE if we are told to use a new connection by force, but + we only acknowledge this option if this is not a re-used connection + already (which happens due to follow-location or during a HTTP + authentication phase). */ + if(data->set.reuse_fresh && !data->state.this_is_a_follow) + reuse = FALSE; + else + reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse); + + /* If we found a reusable connection, we may still want to + open a new connection if we are pipelining. */ + if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) { + size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size; + if(pipelen > 0) { + infof(data, "Found connection %ld, with requests in the pipe (%zu)\n", + conn_temp->connection_id, pipelen); + + if(conn_temp->bundle->num_connections < max_host_connections && + data->state.conn_cache->num_connections < max_total_connections) { + /* We want a new connection anyway */ + reuse = FALSE; + + infof(data, "We can reuse, but we want a new connection anyway\n"); + } + } + } + + if(reuse) { + /* + * We already have a connection for this, we got the former connection + * in the conn_temp variable and thus we need to cleanup the one we + * just allocated before we can move along and use the previously + * existing one. + */ + conn_temp->inuse = TRUE; /* mark this as being in use so that no other + handle in a multi stack may nick it */ + reuse_conn(conn, conn_temp); + free(conn); /* we don't need this anymore */ + conn = conn_temp; + *in_connect = conn; + + /* set a pointer to the hostname we display */ + fix_hostname(data, conn, &conn->host); + + infof(data, "Re-using existing connection! (#%ld) with %s %s\n", + conn->connection_id, + conn->bits.proxy?"proxy":"host", + conn->proxy.name?conn->proxy.dispname:conn->host.dispname); + } + else { + /* We have decided that we want a new connection. However, we may not + be able to do that if we have reached the limit of how many + connections we are allowed to open. */ + struct connectbundle *bundle; + + bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache); + if(max_host_connections > 0 && bundle && + (bundle->num_connections >= max_host_connections)) { + struct connectdata *conn_candidate; + + /* The bundle is full. Let's see if we can kill a connection. */ + conn_candidate = find_oldest_idle_connection_in_bundle(data, bundle); + + if(conn_candidate) { + /* Set the connection's owner correctly, then kill it */ + conn_candidate->data = data; + (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE); + } + else + no_connections_available = TRUE; + } + + if(max_total_connections > 0 && + (data->state.conn_cache->num_connections >= max_total_connections)) { + struct connectdata *conn_candidate; + + /* The cache is full. Let's see if we can kill a connection. */ + conn_candidate = find_oldest_idle_connection(data); + + if(conn_candidate) { + /* Set the connection's owner correctly, then kill it */ + conn_candidate->data = data; + (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE); + } + else + no_connections_available = TRUE; + } + + + if(no_connections_available) { + infof(data, "No connections available.\n"); + + conn_free(conn); + *in_connect = NULL; + + result = CURLE_NO_CONNECTION_AVAILABLE; + goto out; + } + else { + /* + * This is a brand new connection, so let's store it in the connection + * cache of ours! + */ + ConnectionStore(data, conn); + } + +#if defined(USE_NTLM) + /* If NTLM is requested in a part of this connection, make sure we don't + assume the state is fine as this is a fresh connection and NTLM is + connection based. */ + if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + data->state.authhost.done) { + infof(data, "NTLM picked AND auth done set, clear picked!\n"); + data->state.authhost.picked = CURLAUTH_NONE; + } + + if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + data->state.authproxy.done) { + infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n"); + data->state.authproxy.picked = CURLAUTH_NONE; + } +#endif + } + + /* Mark the connection as used */ + conn->inuse = TRUE; + + /* Setup and init stuff before DO starts, in preparing for the transfer. */ + do_init(conn); + + /* + * Setup whatever necessary for a resumed transfer + */ + result = setup_range(data); + if(result) + goto out; + + /* Continue connectdata initialization here. */ + + /* + * Inherit the proper values from the urldata struct AFTER we have arranged + * the persistent connection stuff + */ + conn->fread_func = data->set.fread_func; + conn->fread_in = data->set.in; + conn->seek_func = data->set.seek_func; + conn->seek_client = data->set.seek_client; + + /************************************************************* + * Resolve the address of the server or proxy + *************************************************************/ + result = resolve_server(data, conn, async); + + out: + + free(options); + free(passwd); + free(user); + free(proxy); + return result; +} + +/* Curl_setup_conn() is called after the name resolve initiated in + * create_conn() is all done. + * + * Curl_setup_conn() also handles reused connections + * + * conn->data MUST already have been setup fine (in create_conn) + */ + +CURL_STATIC CURLcode Curl_setup_conn(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + Curl_pgrsTime(data, TIMER_NAMELOOKUP); + + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* nothing to setup when not using a network */ + *protocol_done = TRUE; + return result; + } + *protocol_done = FALSE; /* default to not done */ + + /* set proxy_connect_closed to false unconditionally already here since it + is used strictly to provide extra information to a parent function in the + case of proxy CONNECT failures and we must make sure we don't have it + lingering set from a previous invoke */ + conn->bits.proxy_connect_closed = FALSE; + + /* + * Set user-agent. Used for HTTP, but since we can attempt to tunnel + * basically anything through a http proxy we can't limit this based on + * protocol. + */ + if(data->set.str[STRING_USERAGENT]) { + Curl_safefree(conn->allocptr.uagent); + conn->allocptr.uagent = + aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]); + if(!conn->allocptr.uagent) + return CURLE_OUT_OF_MEMORY; + } + + data->req.headerbytecount = 0; + +#ifdef CURL_DO_LINEEND_CONV + data->state.crlf_conversions = 0; /* reset CRLF conversion counter */ +#endif /* CURL_DO_LINEEND_CONV */ + + /* set start time here for timeout purposes in the connect procedure, it + is later set again for the progress meter purpose */ + conn->now = Curl_tvnow(); + + if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) { + conn->bits.tcpconnect[FIRSTSOCKET] = FALSE; + result = Curl_connecthost(conn, conn->dns_entry); + if(result) + return result; + } + else { + Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */ + Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */ + conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; + *protocol_done = TRUE; + Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]); + Curl_verboseconnect(conn); + } + + conn->now = Curl_tvnow(); /* time this *after* the connect is done, we + set this here perhaps a second time */ + +#ifdef __EMX__ + /* + * This check is quite a hack. We're calling _fsetmode to fix the problem + * with fwrite converting newline characters (you get mangled text files, + * and corrupted binary files when you download to stdout and redirect it to + * a file). + */ + + if((data->set.out)->_handle == NULL) { + _fsetmode(stdout, "b"); + } +#endif + + return result; +} + +CURL_STATIC CURLcode Curl_connect(struct SessionHandle *data, + struct connectdata **in_connect, + bool *asyncp, + bool *protocol_done) +{ + CURLcode result; + + *asyncp = FALSE; /* assume synchronous resolves by default */ + + /* call the stuff that needs to be called */ + result = create_conn(data, in_connect, asyncp); + + if(!result) { + /* no error */ + if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size) + /* pipelining */ + *protocol_done = TRUE; + else if(!*asyncp) { + /* DNS resolution is done: that's either because this is a reused + connection, in which case DNS was unnecessary, or because DNS + really did finish already (synch resolver/fast async resolve) */ + result = Curl_setup_conn(*in_connect, protocol_done); + } + } + + if(result == CURLE_NO_CONNECTION_AVAILABLE) { + *in_connect = NULL; + return result; + } + + if(result && *in_connect) { + /* We're not allowed to return failure with memory left allocated + in the connectdata struct, free those here */ + Curl_disconnect(*in_connect, FALSE); /* close the connection */ + *in_connect = NULL; /* return a NULL */ + } + + return result; +} + +CURL_STATIC CURLcode Curl_done(struct connectdata **connp, + CURLcode status, /* an error if this is called after an + error was detected */ + bool premature) +{ + CURLcode result; + struct connectdata *conn; + struct SessionHandle *data; + + DEBUGASSERT(*connp); + + conn = *connp; + data = conn->data; + + if(conn->bits.done) + /* Stop if Curl_done() has already been called */ + return CURLE_OK; + + Curl_getoff_all_pipelines(data, conn); + + if((conn->send_pipe->size + conn->recv_pipe->size != 0 && + !data->set.reuse_forbid && + !conn->bits.close)) + /* Stop if pipeline is not empty and we do not have to close + connection. */ + return CURLE_OK; + + conn->bits.done = TRUE; /* called just now! */ + + /* Cleanup possible redirect junk */ + free(data->req.newurl); + data->req.newurl = NULL; + free(data->req.location); + data->req.location = NULL; + + Curl_resolver_cancel(conn); + + if(conn->dns_entry) { + Curl_resolv_unlock(data, conn->dns_entry); /* done with this */ + conn->dns_entry = NULL; + } + + switch(status) { + case CURLE_ABORTED_BY_CALLBACK: + case CURLE_READ_ERROR: + case CURLE_WRITE_ERROR: + /* When we're aborted due to a callback return code it basically have to + be counted as premature as there is trouble ahead if we don't. We have + many callbacks and protocols work differently, we could potentially do + this more fine-grained in the future. */ + premature = TRUE; + default: + break; + } + + /* this calls the protocol-specific function pointer previously set */ + if(conn->handler->done) + result = conn->handler->done(conn, status, premature); + else + result = status; + + if(!result && Curl_pgrsDone(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + /* if the transfer was completed in a paused state there can be buffered + data left to write and then kill */ + free(data->state.tempwrite); + data->state.tempwrite = NULL; + + /* if data->set.reuse_forbid is TRUE, it means the libcurl client has + forced us to close this connection. This is ignored for requests taking + place in a NTLM authentication handshake + + if conn->bits.close is TRUE, it means that the connection should be + closed in spite of all our efforts to be nice, due to protocol + restrictions in our or the server's end + + if premature is TRUE, it means this connection was said to be DONE before + the entire request operation is complete and thus we can't know in what + state it is for re-using, so we're forced to close it. In a perfect world + we can add code that keep track of if we really must close it here or not, + but currently we have no such detail knowledge. + */ + + if((data->set.reuse_forbid +#if defined(USE_NTLM) + && !(conn->ntlm.state == NTLMSTATE_TYPE2 || + conn->proxyntlm.state == NTLMSTATE_TYPE2) +#endif + ) || conn->bits.close || premature) { + CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */ + + /* If we had an error already, make sure we return that one. But + if we got a new error, return that. */ + if(!result && res2) + result = res2; + } + else { + /* the connection is no longer in use */ + if(ConnectionDone(data, conn)) { + /* remember the most recently used connection */ + data->state.lastconnect = conn; + + infof(data, "Connection #%ld to host %s left intact\n", + conn->connection_id, + conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname); + } + else + data->state.lastconnect = NULL; + } + + *connp = NULL; /* to make the caller of this function better detect that + this was either closed or handed over to the connection + cache here, and therefore cannot be used from this point on + */ + Curl_free_request_state(data); + + return result; +} + +/* + * do_init() inits the readwrite session. This is inited each time (in the DO + * function before the protocol-specific DO functions are invoked) for a + * transfer, sometimes multiple times on the same SessionHandle. Make sure + * nothing in here depends on stuff that are setup dynamically for the + * transfer. + */ + +static CURLcode do_init(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + struct SingleRequest *k = &data->req; + + conn->bits.done = FALSE; /* Curl_done() is not called yet */ + conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */ + data->state.expect100header = FALSE; + + if(data->set.opt_no_body) + /* in HTTP lingo, no body means using the HEAD request... */ + data->set.httpreq = HTTPREQ_HEAD; + else if(HTTPREQ_HEAD == data->set.httpreq) + /* ... but if unset there really is no perfect method that is the + "opposite" of HEAD but in reality most people probably think GET + then. The important thing is that we can't let it remain HEAD if the + opt_no_body is set FALSE since then we'll behave wrong when getting + HTTP. */ + data->set.httpreq = HTTPREQ_GET; + + k->start = Curl_tvnow(); /* start time */ + k->now = k->start; /* current time is now */ + k->header = TRUE; /* assume header */ + + k->bytecount = 0; + + k->buf = data->state.buffer; + k->uploadbuf = data->state.uploadbuffer; + k->hbufp = data->state.headerbuff; + k->ignorebody=FALSE; + + Curl_speedinit(data); + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + + return CURLE_OK; +} + +/* + * do_complete is called when the DO actions are complete. + * + * We init chunking and trailer bits to their default values here immediately + * before receiving any header data for the current request in the pipeline. + */ +static void do_complete(struct connectdata *conn) +{ + conn->data->req.chunk=FALSE; + conn->data->req.maxfd = (conn->sockfd>conn->writesockfd? + conn->sockfd:conn->writesockfd)+1; + Curl_pgrsTime(conn->data, TIMER_PRETRANSFER); +} + +CURL_STATIC CURLcode Curl_do(struct connectdata **connp, bool *done) +{ + CURLcode result=CURLE_OK; + struct connectdata *conn = *connp; + struct SessionHandle *data = conn->data; + + if(conn->handler->do_it) { + /* generic protocol-specific function pointer set in curl_connect() */ + result = conn->handler->do_it(conn, done); + + /* This was formerly done in transfer.c, but we better do it here */ + if((CURLE_SEND_ERROR == result) && conn->bits.reuse) { + /* + * If the connection is using an easy handle, call reconnect + * to re-establish the connection. Otherwise, let the multi logic + * figure out how to re-establish the connection. + */ + if(!data->multi) { + result = Curl_reconnect_request(connp); + + if(!result) { + /* ... finally back to actually retry the DO phase */ + conn = *connp; /* re-assign conn since Curl_reconnect_request + creates a new connection */ + result = conn->handler->do_it(conn, done); + } + } + else + return result; + } + + if(!result && *done) + /* do_complete must be called after the protocol-specific DO function */ + do_complete(conn); + } + return result; +} + +/* + * Curl_do_more() is called during the DO_MORE multi state. It is basically a + * second stage DO state which (wrongly) was introduced to support FTP's + * second connection. + * + * TODO: A future libcurl should be able to work away this state. + * + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to + * DOING state there's more work to do! + */ + +CURL_STATIC CURLcode Curl_do_more(struct connectdata *conn, int *complete) +{ + CURLcode result=CURLE_OK; + + *complete = 0; + + if(conn->handler->do_more) + result = conn->handler->do_more(conn, complete); + + if(!result && (*complete == 1)) + /* do_complete must be called after the protocol-specific DO function */ + do_complete(conn); + + return result; +} diff --git a/libcurl/src/lib/url.h b/libcurl/src/lib/url.h new file mode 100644 index 0000000..d36a479 --- /dev/null +++ b/libcurl/src/lib/url.h @@ -0,0 +1,82 @@ +#ifndef HEADER_CURL_URL_H +#define HEADER_CURL_URL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* + * Prototypes for library-wide functions provided by url.c + */ + +CURL_STATIC CURLcode Curl_open(struct SessionHandle **curl); +CURL_STATIC CURLcode Curl_init_userdefined(struct UserDefined *set); +CURL_STATIC CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, + va_list arg); +CURL_STATIC CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src); +CURL_STATIC void Curl_freeset(struct SessionHandle * data); +CURL_STATIC CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */ +CURL_STATIC CURLcode Curl_connect(struct SessionHandle *, struct connectdata **, + bool *async, bool *protocol_connect); +CURL_STATIC CURLcode Curl_do(struct connectdata **, bool *done); +CURL_STATIC CURLcode Curl_do_more(struct connectdata *, int *completed); +CURL_STATIC CURLcode Curl_done(struct connectdata **, CURLcode, bool premature); +CURL_STATIC CURLcode Curl_disconnect(struct connectdata *, bool dead_connection); +CURL_STATIC CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done); +CURL_STATIC CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done); +CURL_STATIC CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done); +CURL_STATIC CURLcode Curl_setup_conn(struct connectdata *conn, + bool *protocol_done); +CURL_STATIC void Curl_free_request_state(struct SessionHandle *data); + +CURL_STATIC int Curl_protocol_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +CURL_STATIC int Curl_doing_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + +CURL_STATIC bool Curl_isPipeliningEnabled(const struct SessionHandle *handle); +CURL_STATIC CURLcode Curl_addHandleToPipeline(struct SessionHandle *handle, + struct curl_llist *pipeline); +CURL_STATIC int Curl_removeHandleFromPipeline(struct SessionHandle *handle, + struct curl_llist *pipeline); +/* remove the specified connection from all (possible) pipelines and related + queues */ +CURL_STATIC void Curl_getoff_all_pipelines(struct SessionHandle *data, + struct connectdata *conn); + +CURL_STATIC void Curl_close_connections(struct SessionHandle *data); + +#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ +#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi + service */ + +CURL_STATIC CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define Curl_verboseconnect(x) Curl_nop_stmt +#else +CURL_STATIC void Curl_verboseconnect(struct connectdata *conn); +#endif + + +#endif /* HEADER_CURL_URL_H */ diff --git a/libcurl/src/lib/urldata.h b/libcurl/src/lib/urldata.h new file mode 100644 index 0000000..b1b1a67 --- /dev/null +++ b/libcurl/src/lib/urldata.h @@ -0,0 +1,1695 @@ +#ifndef HEADER_CURL_URLDATA_H +#define HEADER_CURL_URLDATA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This file is for lib internal stuff */ + +#include "curl_setup.h" + +#define PORT_FTP 21 +#define PORT_FTPS 990 +#define PORT_TELNET 23 +#define PORT_HTTP 80 +#define PORT_HTTPS 443 +#define PORT_DICT 2628 +#define PORT_LDAP 389 +#define PORT_LDAPS 636 +#define PORT_TFTP 69 +#define PORT_SSH 22 +#define PORT_IMAP 143 +#define PORT_IMAPS 993 +#define PORT_POP3 110 +#define PORT_POP3S 995 +#define PORT_SMB 445 +#define PORT_SMBS 445 +#define PORT_SMTP 25 +#define PORT_SMTPS 465 /* sometimes called SSMTP */ +#define PORT_RTSP 554 +#define PORT_RTMP 1935 +#define PORT_RTMPT PORT_HTTP +#define PORT_RTMPS PORT_HTTPS +#define PORT_GOPHER 70 + +#define DICT_MATCH "/MATCH:" +#define DICT_MATCH2 "/M:" +#define DICT_MATCH3 "/FIND:" +#define DICT_DEFINE "/DEFINE:" +#define DICT_DEFINE2 "/D:" +#define DICT_DEFINE3 "/LOOKUP:" + +#define CURL_DEFAULT_USER "anonymous" +#define CURL_DEFAULT_PASSWORD "ftp@example.com" + +/* Convenience defines for checking protocols or their SSL based version. Each + protocol handler should only ever have a single CURLPROTO_ in its protocol + field. */ +#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS) +#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS) +#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S) +#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS) +#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS) + +#define DEFAULT_CONNCACHE_SIZE 5 + +/* length of longest IPv6 address string including the trailing null */ +#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + +/* Default FTP/IMAP etc response timeout in milliseconds. + Symbian OS panics when given a timeout much greater than 1/2 hour. +*/ +#define RESP_TIMEOUT (1800*1000) + +#include "cookie.h" +#include "formdata.h" + +#ifdef USE_OPENSSL +#include +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif +#endif /* USE_OPENSSL */ + +#ifdef USE_GNUTLS +#include +#endif + +#ifdef USE_POLARSSL +#include +#include +#if POLARSSL_VERSION_NUMBER<0x01010000 +#include +#else +#include +#include +#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */ +#endif /* USE_POLARSSL */ + +#ifdef USE_CYASSL +#undef OCSP_REQUEST /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */ +#undef OCSP_RESPONSE /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */ +#include +#endif + +#ifdef USE_NSS +#include +#include +#endif + +#ifdef USE_GSKIT +#include +#endif + +#ifdef USE_AXTLS +#include +#include +#undef malloc +#undef calloc +#undef realloc +#endif /* USE_AXTLS */ + +#ifdef USE_SCHANNEL +#include "curl_sspi.h" +#include +#include +#endif + +#ifdef USE_DARWINSSL +#include +/* For some reason, when building for iOS, the omnibus header above does + * not include SecureTransport.h as of iOS SDK 5.1. */ +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#include "timeval.h" + +#ifdef HAVE_ZLIB_H +#include /* for content-encoding */ +#ifdef __SYMBIAN32__ +/* zlib pollutes the namespace with this definition */ +#undef WIN32 +#endif +#endif + +#include + +#include "http_chunks.h" /* for the structs and enum stuff */ +#include "hostip.h" +#include "hash.h" +#include "splay.h" + +#include "imap.h" +#include "pop3.h" +#include "smtp.h" +#include "ftp.h" +#include "file.h" +#include "ssh.h" +#include "http.h" +#include "rtsp.h" +#include "smb.h" +#include "wildcard.h" +#include "multihandle.h" + +#ifdef HAVE_GSSAPI +# ifdef HAVE_GSSGNU +# include +# elif defined HAVE_GSSMIT +# include +# include +# else +# include +# endif +#endif + +#ifdef HAVE_LIBSSH2_H +#include +#include +#endif /* HAVE_LIBSSH2_H */ + +/* Download buffer size, keep it fairly big for speed reasons */ +#undef BUFSIZE +#define BUFSIZE CURL_MAX_WRITE_SIZE + +/* Initial size of the buffer to store headers in, it'll be enlarged in case + of need. */ +#define HEADERSIZE 256 + +#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU + +/* Some convenience macros to get the larger/smaller value out of two given. + We prefix with CURL to prevent name collisions. */ +#define CURLMAX(x,y) ((x)>(y)?(x):(y)) +#define CURLMIN(x,y) ((x)<(y)?(x):(y)) + + +#ifdef HAVE_GSSAPI +/* Types needed for krb5-ftp connections */ +struct krb5buffer { + void *data; + size_t size; + size_t index; + int eof_flag; +}; + +enum protection_level { + PROT_NONE, /* first in list */ + PROT_CLEAR, + PROT_SAFE, + PROT_CONFIDENTIAL, + PROT_PRIVATE, + PROT_CMD, + PROT_LAST /* last in list */ +}; +#endif + +#ifdef USE_SCHANNEL +/* Structs to store Schannel handles */ +struct curl_schannel_cred { + CredHandle cred_handle; + TimeStamp time_stamp; + int refcount; + bool cached; +}; + +struct curl_schannel_ctxt { + CtxtHandle ctxt_handle; + TimeStamp time_stamp; +}; +#endif + +/* enum for the nonblocking SSL connection state machine */ +typedef enum { + ssl_connect_1, + ssl_connect_2, + ssl_connect_2_reading, + ssl_connect_2_writing, + ssl_connect_3, + ssl_connect_done +} ssl_connect_state; + +typedef enum { + ssl_connection_none, + ssl_connection_negotiating, + ssl_connection_complete +} ssl_connection_state; + +/* struct for data related to each SSL connection */ +struct ssl_connect_data { + /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm + but at least asked to or meaning to use it. See 'state' for the exact + current state of the connection. */ + bool use; + ssl_connection_state state; +#ifdef USE_OPENSSL + /* these ones requires specific SSL-types */ + SSL_CTX* ctx; + SSL* handle; + X509* server_cert; + ssl_connect_state connecting_state; +#endif /* USE_OPENSSL */ +#ifdef USE_GNUTLS + gnutls_session_t session; + gnutls_certificate_credentials_t cred; +#ifdef USE_TLS_SRP + gnutls_srp_client_credentials_t srp_client_cred; +#endif + ssl_connect_state connecting_state; +#endif /* USE_GNUTLS */ +#ifdef USE_POLARSSL + ctr_drbg_context ctr_drbg; + entropy_context entropy; + ssl_context ssl; + ssl_session ssn; + int server_fd; + x509_crt cacert; + x509_crt clicert; + x509_crl crl; + rsa_context rsa; + ssl_connect_state connecting_state; +#endif /* USE_POLARSSL */ +#ifdef USE_CYASSL + SSL_CTX* ctx; + SSL* handle; + ssl_connect_state connecting_state; +#endif /* USE_CYASSL */ +#ifdef USE_NSS + PRFileDesc *handle; + char *client_nickname; + struct SessionHandle *data; + struct curl_llist *obj_list; + PK11GenericObject *obj_clicert; + ssl_connect_state connecting_state; +#endif /* USE_NSS */ +#ifdef USE_GSKIT + gsk_handle handle; + int iocport; + ssl_connect_state connecting_state; +#endif +#ifdef USE_AXTLS + SSL_CTX* ssl_ctx; + SSL* ssl; + ssl_connect_state connecting_state; +#endif /* USE_AXTLS */ +#ifdef USE_SCHANNEL + struct curl_schannel_cred *cred; + struct curl_schannel_ctxt *ctxt; + SecPkgContext_StreamSizes stream_sizes; + ssl_connect_state connecting_state; + size_t encdata_length, decdata_length; + size_t encdata_offset, decdata_offset; + unsigned char *encdata_buffer, *decdata_buffer; + unsigned long req_flags, ret_flags; +#endif /* USE_SCHANNEL */ +#ifdef USE_DARWINSSL + SSLContextRef ssl_ctx; + curl_socket_t ssl_sockfd; + ssl_connect_state connecting_state; + bool ssl_direction; /* true if writing, false if reading */ + size_t ssl_write_buffered_length; +#endif /* USE_DARWINSSL */ +}; + +struct ssl_config_data { + long version; /* what version the client wants to use */ + long certverifyresult; /* result from the certificate verification */ + + bool verifypeer; /* set TRUE if this is desired */ + bool verifyhost; /* set TRUE if CN/SAN must match hostname */ + bool verifystatus; /* set TRUE if certificate status must be checked */ + char *CApath; /* certificate dir (doesn't work on windows) */ + char *CAfile; /* certificate to verify peer against */ + const char *CRLfile; /* CRL to check certificate revocation */ + const char *issuercert;/* optional issuer certificate filename */ + char *random_file; /* path to file containing "random" data */ + char *egdsocket; /* path to file containing the EGD daemon socket */ + char *cipher_list; /* list of ciphers to use */ + size_t max_ssl_sessions; /* SSL session id cache size */ + curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ + void *fsslctxp; /* parameter for call back */ + bool sessionid; /* cache session IDs or not */ + bool certinfo; /* gather lots of certificate info */ + bool falsestart; + +#ifdef USE_TLS_SRP + char *username; /* TLS username (for, e.g., SRP) */ + char *password; /* TLS password (for, e.g., SRP) */ + enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ +#endif +}; + +/* information stored about one single SSL session */ +struct curl_ssl_session { + char *name; /* host name for which this ID was used */ + void *sessionid; /* as returned from the SSL layer */ + size_t idsize; /* if known, otherwise 0 */ + long age; /* just a number, the higher the more recent */ + int remote_port; /* remote port to connect to */ + struct ssl_config_data ssl_config; /* setup for this session */ +}; + +/* Struct used for Digest challenge-response authentication */ +struct digestdata { +#if defined(USE_WINDOWS_SSPI) + BYTE *input_token; + size_t input_token_len; +#else + char *nonce; + char *cnonce; + char *realm; + int algo; + bool stale; /* set true for re-negotiation */ + char *opaque; + char *qop; + char *algorithm; + int nc; /* nounce count */ +#endif +}; + +typedef enum { + NTLMSTATE_NONE, + NTLMSTATE_TYPE1, + NTLMSTATE_TYPE2, + NTLMSTATE_TYPE3, + NTLMSTATE_LAST +} curlntlm; + +#ifdef USE_WINDOWS_SSPI +#include "curl_sspi.h" +#endif + +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) +#include +#endif + +/* Struct used for GSSAPI (Kerberos V5) authentication */ +#if defined(USE_KERBEROS5) +struct kerberos5data { +#if defined(USE_WINDOWS_SSPI) + CredHandle *credentials; + CtxtHandle *context; + TCHAR *spn; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + size_t token_max; + BYTE *output_token; +#else + gss_ctx_id_t context; + gss_name_t spn; +#endif +}; +#endif + +/* Struct used for NTLM challenge-response authentication */ +#if defined(USE_NTLM) +struct ntlmdata { + curlntlm state; +#ifdef USE_WINDOWS_SSPI + CredHandle *credentials; + CtxtHandle *context; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + size_t token_max; + BYTE *output_token; + BYTE *input_token; + size_t input_token_len; +#else + unsigned int flags; + unsigned char nonce[8]; + void* target_info; /* TargetInfo received in the ntlm type-2 message */ + unsigned int target_info_len; +#endif +}; +#endif + +#ifdef USE_SPNEGO +struct negotiatedata { + /* When doing Negotiate (SPNEGO) auth, we first need to send a token + and then validate the received one. */ + enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state; +#ifdef HAVE_GSSAPI + OM_uint32 status; + gss_ctx_id_t context; + gss_name_t server_name; + gss_buffer_desc output_token; +#else +#ifdef USE_WINDOWS_SSPI + DWORD status; + CredHandle *credentials; + CtxtHandle *context; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + TCHAR *server_name; + size_t token_max; + BYTE *output_token; + size_t output_token_length; +#endif +#endif +}; +#endif + + +/* + * Boolean values that concerns this connection. + */ +struct ConnectBits { + /* always modify bits.close with the connclose() and connkeep() macros! */ + bool close; /* if set, we close the connection after this request */ + bool reuse; /* if set, this is a re-used connection */ + bool proxy; /* if set, this transfer is done through a proxy - any type */ + bool httpproxy; /* if set, this transfer is done through a http proxy */ + bool user_passwd; /* do we use user+password for this connection? */ + bool proxy_user_passwd; /* user+password for the proxy? */ + bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6 + IP address */ + bool ipv6; /* we communicate with a site using an IPv6 address */ + + bool do_more; /* this is set TRUE if the ->curl_do_more() function is + supposed to be called, after ->curl_do() */ + bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set + the first time on the first connect function call */ + bool protoconnstart;/* the protocol layer has STARTED its operation after + the TCP layer connect */ + + bool retry; /* this connection is about to get closed and then + re-attempted at another connection. */ + bool tunnel_proxy; /* if CONNECT is used to "tunnel" through the proxy. + This is implicit when SSL-protocols are used through + proxies, but can also be enabled explicitly by + apps */ + bool authneg; /* TRUE when the auth phase has started, which means + that we are creating a request with an auth header, + but it is not the final request in the auth + negotiation. */ + bool rewindaftersend;/* TRUE when the sending couldn't be stopped even + though it will be discarded. When the whole send + operation is done, we must call the data rewind + callback. */ + bool ftp_use_epsv; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out + EPSV doesn't work we disable it for the forthcoming + requests */ + + bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out + EPRT doesn't work we disable it for the forthcoming + requests */ + bool netrc; /* name+password provided by netrc */ + bool userpwd_in_url; /* name+password found in url */ + + bool done; /* set to FALSE when Curl_do() is called and set to TRUE + when Curl_done() is called, to prevent Curl_done() to + get invoked twice when the multi interface is + used. */ + bool stream_was_rewound; /* Indicates that the stream was rewound after a + request read past the end of its response byte + boundary */ + bool proxy_connect_closed; /* set true if a proxy disconnected the + connection in a CONNECT request with auth, so + that libcurl should reconnect and continue. */ + bool bound; /* set true if bind() has already been done on this socket/ + connection */ + bool type_set; /* type= was used in the URL */ +}; + +struct hostname { + char *rawalloc; /* allocated "raw" version of the name */ + char *encalloc; /* allocated IDN-encoded version of the name */ + char *name; /* name to use internally, might be encoded, might be raw */ + const char *dispname; /* name to display, as 'name' might be encoded */ +}; + +/* + * Flags on the keepon member of the Curl_transfer_keeper + */ + +#define KEEP_NONE 0 +#define KEEP_RECV (1<<0) /* there is or may be data to read */ +#define KEEP_SEND (1<<1) /* there is or may be data to write */ +#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there + might still be data to read */ +#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there + might still be data to write */ +#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */ +#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */ + +#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) +#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) + + +#ifdef HAVE_LIBZ +typedef enum { + ZLIB_UNINIT, /* uninitialized */ + ZLIB_INIT, /* initialized */ + ZLIB_GZIP_HEADER, /* reading gzip header */ + ZLIB_GZIP_INFLATING, /* inflating gzip stream */ + ZLIB_INIT_GZIP /* initialized in transparent gzip mode */ +} zlibInitState; +#endif + +#ifdef CURLRES_ASYNCH +struct Curl_async { + char *hostname; + int port; + struct Curl_dns_entry *dns; + bool done; /* set TRUE when the lookup is complete */ + int status; /* if done is TRUE, this is the status from the callback */ + void *os_specific; /* 'struct thread_data' for Windows */ +}; +#endif + +#define FIRSTSOCKET 0 +#define SECONDARYSOCKET 1 + +/* These function pointer types are here only to allow easier typecasting + within the source when we need to cast between data pointers (such as NULL) + and function pointers. */ +typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *); +typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool); + +enum expect100 { + EXP100_SEND_DATA, /* enough waiting, just send the body now */ + EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ + EXP100_SENDING_REQUEST, /* still sending the request but will wait for + the 100 header once done with the request */ + EXP100_FAILED /* used on 417 Expectation Failed */ +}; + +enum upgrade101 { + UPGR101_INIT, /* default state */ + UPGR101_REQUESTED, /* upgrade requested */ + UPGR101_RECEIVED, /* response received */ + UPGR101_WORKING /* talking upgraded protocol */ +}; + +/* + * Request specific data in the easy handle (SessionHandle). Previously, + * these members were on the connectdata struct but since a conn struct may + * now be shared between different SessionHandles, we store connection-specific + * data here. This struct only keeps stuff that's interesting for *this* + * request, as it will be cleared between multiple ones + */ +struct SingleRequest { + curl_off_t size; /* -1 if unknown at this point */ + curl_off_t *bytecountp; /* return number of bytes read or NULL */ + + curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch, + -1 means unlimited */ + curl_off_t *writebytecountp; /* return number of bytes written or NULL */ + + curl_off_t bytecount; /* total number of bytes read */ + curl_off_t writebytecount; /* number of bytes written */ + + long headerbytecount; /* only count received headers */ + long deductheadercount; /* this amount of bytes doesn't count when we check + if anything has been transferred at the end of a + connection. We use this counter to make only a + 100 reply (without a following second response + code) result in a CURLE_GOT_NOTHING error code */ + + struct timeval start; /* transfer started at this time */ + struct timeval now; /* current time */ + bool header; /* incoming data has HTTP header */ + enum { + HEADER_NORMAL, /* no bad header at all */ + HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest + is normal data */ + HEADER_ALLBAD /* all was believed to be header */ + } badheader; /* the header was deemed bad and will be + written as body */ + int headerline; /* counts header lines to better track the + first one */ + char *hbufp; /* points at *end* of header line */ + size_t hbuflen; + char *str; /* within buf */ + char *str_start; /* within buf */ + char *end_ptr; /* within buf */ + char *p; /* within headerbuff */ + bool content_range; /* set TRUE if Content-Range: was found */ + curl_off_t offset; /* possible resume offset read from the + Content-Range: header */ + int httpcode; /* error code from the 'HTTP/1.? XXX' or + 'RTSP/1.? XXX' line */ + struct timeval start100; /* time stamp to wait for the 100 code from */ + enum expect100 exp100; /* expect 100 continue state */ + enum upgrade101 upgr101; /* 101 upgrade state */ + + int auto_decoding; /* What content encoding. sec 3.5, RFC2616. */ + +#define IDENTITY 0 /* No encoding */ +#define DEFLATE 1 /* zlib deflate [RFC 1950 & 1951] */ +#define GZIP 2 /* gzip algorithm [RFC 1952] */ +#define COMPRESS 3 /* Not handled, added for completeness */ + +#ifdef HAVE_LIBZ + zlibInitState zlib_init; /* possible zlib init state; + undefined if Content-Encoding header. */ + z_stream z; /* State structure for zlib. */ +#endif + + time_t timeofdoc; + long bodywrites; + + char *buf; + char *uploadbuf; + curl_socket_t maxfd; + + int keepon; + + bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload + and we're uploading the last chunk */ + + bool ignorebody; /* we read a response-body but we ignore it! */ + bool ignorecl; /* This HTTP response has no body so we ignore the Content- + Length: header */ + + char *location; /* This points to an allocated version of the Location: + header data */ + char *newurl; /* Set to the new URL to use when a redirect or a retry is + wanted */ + + /* 'upload_present' is used to keep a byte counter of how much data there is + still left in the buffer, aimed for upload. */ + ssize_t upload_present; + + /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a + buffer, so the next read should read from where this pointer points to, + and the 'upload_present' contains the number of bytes available at this + position */ + char *upload_fromhere; + + bool chunk; /* if set, this is a chunked transfer-encoding */ + bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding + on upload */ + bool getheader; /* TRUE if header parsing is wanted */ + + bool forbidchunk; /* used only to explicitly forbid chunk-upload for + specific upload buffers. See readmoredata() in + http.c for details. */ + + void *protop; /* Allocated protocol-specific data. Each protocol + handler makes sure this points to data it needs. */ +}; + +/* + * Specific protocol handler. + */ + +struct Curl_handler { + const char * scheme; /* URL scheme name. */ + + /* Complement to setup_connection_internals(). */ + CURLcode (*setup_connection)(struct connectdata *); + + /* These two functions MUST be set to be protocol dependent */ + CURLcode (*do_it)(struct connectdata *, bool *done); + Curl_done_func done; + + /* If the curl_do() function is better made in two halves, this + * curl_do_more() function will be called afterwards, if set. For example + * for doing the FTP stuff after the PASV/PORT command. + */ + Curl_do_more_func do_more; + + /* This function *MAY* be set to a protocol-dependent function that is run + * after the connect() and everything is done, as a step in the connection. + * The 'done' pointer points to a bool that should be set to TRUE if the + * function completes before return. If it doesn't complete, the caller + * should call the curl_connecting() function until it is. + */ + CURLcode (*connect_it)(struct connectdata *, bool *done); + + /* See above. Currently only used for FTP. */ + CURLcode (*connecting)(struct connectdata *, bool *done); + CURLcode (*doing)(struct connectdata *, bool *done); + + /* Called from the multi interface during the PROTOCONNECT phase, and it + should then return a proper fd set */ + int (*proto_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DOING phase, and it should + then return a proper fd set */ + int (*doing_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DO_MORE phase, and it should + then return a proper fd set */ + int (*domore_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DO_DONE, PERFORM and + WAITPERFORM phases, and it should then return a proper fd set. Not setting + this will make libcurl use the generic default one. */ + int (*perform_getsock)(const struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* This function *MAY* be set to a protocol-dependent function that is run + * by the curl_disconnect(), as a step in the disconnection. If the handler + * is called because the connection has been considered dead, dead_connection + * is set to TRUE. + */ + CURLcode (*disconnect)(struct connectdata *, bool dead_connection); + + /* If used, this function gets called from transfer.c:readwrite_data() to + allow the protocol to do extra reads/writes */ + CURLcode (*readwrite)(struct SessionHandle *data, struct connectdata *conn, + ssize_t *nread, bool *readmore); + + long defport; /* Default port. */ + unsigned int protocol; /* See CURLPROTO_* - this needs to be the single + specific protocol bit */ + unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ +}; + +#define PROTOPT_NONE 0 /* nothing extra */ +#define PROTOPT_SSL (1<<0) /* uses SSL */ +#define PROTOPT_DUAL (1<<1) /* this protocol uses two connections */ +#define PROTOPT_CLOSEACTION (1<<2) /* need action before socket close */ +/* some protocols will have to call the underlying functions without regard to + what exact state the socket signals. IE even if the socket says "readable", + the send function might need to be called while uploading, or vice versa. +*/ +#define PROTOPT_DIRLOCK (1<<3) +#define PROTOPT_NONETWORK (1<<4) /* protocol doesn't use the network! */ +#define PROTOPT_NEEDSPWD (1<<5) /* needs a password, and if none is set it + gets a default */ +#define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle + url query strings (?foo=bar) ! */ +#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per + request instead of per connection */ + + +/* return the count of bytes sent, or -1 on error */ +typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + const void *buf, /* data to write */ + size_t len, /* max amount to write */ + CURLcode *err); /* error to return */ + +/* return the count of bytes read, or -1 on error */ +typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + char *buf, /* store data here */ + size_t len, /* max amount to read */ + CURLcode *err); /* error to return */ + +/* + * The connectdata struct contains all fields and variables that should be + * unique for an entire connection. + */ +struct connectdata { + /* 'data' is the CURRENT SessionHandle using this connection -- take great + caution that this might very well vary between different times this + connection is used! */ + struct SessionHandle *data; + + /* chunk is for HTTP chunked encoding, but is in the general connectdata + struct only because we can do just about any protocol through a HTTP proxy + and a HTTP proxy may in fact respond using chunked encoding */ + struct Curl_chunker chunk; + + curl_closesocket_callback fclosesocket; /* function closing the socket(s) */ + void *closesocket_client; + + bool inuse; /* This is a marker for the connection cache logic. If this is + TRUE this handle is being used by an easy handle and cannot + be used by any other easy handle without careful + consideration (== only for pipelining). */ + + /**** Fields set when inited and not modified again */ + long connection_id; /* Contains a unique number to make it easier to + track the connections in the log output */ + + /* 'dns_entry' is the particular host we use. This points to an entry in the + DNS cache and it will not get pruned while locked. It gets unlocked in + Curl_done(). This entry will be NULL if the connection is re-used as then + there is no name resolve done. */ + struct Curl_dns_entry *dns_entry; + + /* 'ip_addr' is the particular IP we connected to. It points to a struct + within the DNS cache, so this pointer is only valid as long as the DNS + cache entry remains locked. It gets unlocked in Curl_done() */ + Curl_addrinfo *ip_addr; + Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */ + + /* 'ip_addr_str' is the ip_addr data as a human readable string. + It remains available as long as the connection does, which is longer than + the ip_addr itself. */ + char ip_addr_str[MAX_IPADR_LEN]; + + unsigned int scope_id; /* Scope id for IPv6 */ + + int socktype; /* SOCK_STREAM or SOCK_DGRAM */ + + struct hostname host; + struct hostname proxy; + + long port; /* which port to use locally */ + int remote_port; /* what remote port to connect to, not the proxy port! */ + + /* 'primary_ip' and 'primary_port' get filled with peer's numerical + ip address and port number whenever an outgoing connection is + *attempted* from the primary socket to a remote address. When more + than one address is tried for a connection these will hold data + for the last attempt. When the connection is actually established + these are updated with data which comes directly from the socket. */ + + char primary_ip[MAX_IPADR_LEN]; + long primary_port; + + /* 'local_ip' and 'local_port' get filled with local's numerical + ip address and port number whenever an outgoing connection is + **established** from the primary socket to a remote address. */ + + char local_ip[MAX_IPADR_LEN]; + long local_port; + + char *user; /* user name string, allocated */ + char *passwd; /* password string, allocated */ + char *options; /* options string, allocated */ + + char *xoauth2_bearer; /* bearer token for xoauth2, allocated */ + + char *proxyuser; /* proxy user name string, allocated */ + char *proxypasswd; /* proxy password string, allocated */ + curl_proxytype proxytype; /* what kind of proxy that is in use */ + + int httpversion; /* the HTTP version*10 reported by the server */ + int rtspversion; /* the RTSP version*10 reported by the server */ + + struct timeval now; /* "current" time */ + struct timeval created; /* creation time */ + curl_socket_t sock[2]; /* two sockets, the second is used for the data + transfer when doing FTP */ + curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */ + bool sock_accepted[2]; /* TRUE if the socket on this index was created with + accept() */ + Curl_recv *recv[2]; + Curl_send *send[2]; + + struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ + struct ssl_config_data ssl_config; + + struct ConnectBits bits; /* various state-flags for this connection */ + + /* connecttime: when connect() is called on the current IP address. Used to + be able to track when to move on to try next IP - but only when the multi + interface is used. */ + struct timeval connecttime; + /* The two fields below get set in Curl_connecthost */ + int num_addr; /* number of addresses to try to connect to */ + long timeoutms_per_addr; /* how long time in milliseconds to spend on + trying to connect to each IP address */ + + const struct Curl_handler *handler; /* Connection's protocol handler */ + const struct Curl_handler *given; /* The protocol first given */ + + long ip_version; /* copied from the SessionHandle at creation time */ + + /**** curl_get() phase fields */ + + curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */ + curl_socket_t writesockfd; /* socket to write to, it may very + well be the same we read from. + CURL_SOCKET_BAD disables */ + + /** Dynamicly allocated strings, MUST be freed before this **/ + /** struct is killed. **/ + struct dynamically_allocated_data { + char *proxyuserpwd; + char *uagent; + char *accept_encoding; + char *userpwd; + char *rangeline; + char *ref; + char *host; + char *cookiehost; + char *rtsp_transport; + char *te; /* TE: request header */ + } allocptr; + +#ifdef HAVE_GSSAPI + int sec_complete; /* if Kerberos is enabled for this connection */ + enum protection_level command_prot; + enum protection_level data_prot; + enum protection_level request_data_prot; + size_t buffer_size; + struct krb5buffer in_buffer; + void *app_data; + const struct Curl_sec_client_mech *mech; + struct sockaddr_in local_addr; +#endif + +#if defined(USE_KERBEROS5) /* Consider moving some of the above GSS-API */ + struct kerberos5data krb5; /* variables into the structure definition, */ +#endif /* however, some of them are ftp specific. */ + + /* the two following *_inuse fields are only flags, not counters in any way. + If TRUE it means the channel is in use, and if FALSE it means the channel + is up for grabs by one. */ + + bool readchannel_inuse; /* whether the read channel is in use by an easy + handle */ + bool writechannel_inuse; /* whether the write channel is in use by an easy + handle */ + struct curl_llist *send_pipe; /* List of handles waiting to + send on this pipeline */ + struct curl_llist *recv_pipe; /* List of handles waiting to read + their responses on this pipeline */ + char* master_buffer; /* The master buffer allocated on-demand; + used for pipelining. */ + size_t read_pos; /* Current read position in the master buffer */ + size_t buf_len; /* Length of the buffer?? */ + + + curl_seek_callback seek_func; /* function that seeks the input */ + void *seek_client; /* pointer to pass to the seek() above */ + + /*************** Request - specific items ************/ + + /* previously this was in the urldata struct */ + curl_read_callback fread_func; /* function that reads the input */ + void *fread_in; /* pointer to pass to the fread() above */ + +#if defined(USE_NTLM) + struct ntlmdata ntlm; /* NTLM differs from other authentication schemes + because it authenticates connections, not + single requests! */ + struct ntlmdata proxyntlm; /* NTLM data for proxy */ + +#if defined(NTLM_WB_ENABLED) + /* used for communication with Samba's winbind daemon helper ntlm_auth */ + curl_socket_t ntlm_auth_hlpr_socket; + pid_t ntlm_auth_hlpr_pid; + char* challenge_header; + char* response_header; +#endif +#endif + + char syserr_buf [256]; /* buffer for Curl_strerror() */ + +#ifdef CURLRES_ASYNCH + /* data used for the asynch name resolve callback */ + struct Curl_async async; +#endif + + /* These three are used for chunked-encoding trailer support */ + char *trailer; /* allocated buffer to store trailer in */ + int trlMax; /* allocated buffer size */ + int trlPos; /* index of where to store data */ + + union { + struct ftp_conn ftpc; + struct http_conn httpc; + struct ssh_conn sshc; + struct tftp_state_data *tftpc; + struct imap_conn imapc; + struct pop3_conn pop3c; + struct smtp_conn smtpc; + struct rtsp_conn rtspc; + struct smb_conn smbc; + void *generic; /* RTMP and LDAP use this */ + } proto; + + int cselect_bits; /* bitmask of socket events */ + int waitfor; /* current READ/WRITE bits to wait for */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + int socks5_gssapi_enctype; +#endif + + bool verifypeer; + bool verifyhost; + + /* When this connection is created, store the conditions for the local end + bind. This is stored before the actual bind and before any connection is + made and will serve the purpose of being used for comparison reasons so + that subsequent bound-requested connections aren't accidentally re-using + wrong connections. */ + char *localdev; + unsigned short localport; + int localportrange; + + /* tunnel as in tunnel through a HTTP proxy with CONNECT */ + enum { + TUNNEL_INIT, /* init/default/no tunnel state */ + TUNNEL_CONNECT, /* CONNECT has been sent off */ + TUNNEL_COMPLETE /* CONNECT response received completely */ + } tunnel_state[2]; /* two separate ones to allow FTP */ + struct connectbundle *bundle; /* The bundle we are member of */ + + int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ +}; + +/* The end of connectdata. */ + +/* + * Struct to keep statistical and informational data. + */ +struct PureInfo { + int httpcode; /* Recent HTTP, FTP, or RTSP response code */ + int httpproxycode; /* response code from proxy when received separate */ + int httpversion; /* the http version number X.Y = X*10+Y */ + long filetime; /* If requested, this is might get set. Set to -1 if the time + was unretrievable. We cannot have this of type time_t, + since time_t is unsigned on several platforms such as + OpenVMS. */ + bool timecond; /* set to TRUE if the time condition didn't match, which + thus made the document NOT get fetched */ + long header_size; /* size of read header(s) in bytes */ + long request_size; /* the amount of bytes sent in the request(s) */ + unsigned long proxyauthavail; /* what proxy auth types were announced */ + unsigned long httpauthavail; /* what host auth types were announced */ + long numconnects; /* how many new connection did libcurl created */ + char *contenttype; /* the content type of the object */ + char *wouldredirect; /* URL this would've been redirected to if asked to */ + + /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip' + and, 'conn_local_port' are copied over from the connectdata struct in + order to allow curl_easy_getinfo() to return this information even when + the session handle is no longer associated with a connection, and also + allow curl_easy_reset() to clear this information from the session handle + without disturbing information which is still alive, and that might be + reused, in the connection cache. */ + + char conn_primary_ip[MAX_IPADR_LEN]; + long conn_primary_port; + + char conn_local_ip[MAX_IPADR_LEN]; + long conn_local_port; + + struct curl_certinfo certs; /* info about the certs, only populated in + OpenSSL builds. Asked for with + CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +}; + + +struct Progress { + long lastshow; /* time() of the last displayed progress meter or NULL to + force redraw at next call */ + curl_off_t size_dl; /* total expected size */ + curl_off_t size_ul; /* total expected size */ + curl_off_t downloaded; /* transferred so far */ + curl_off_t uploaded; /* transferred so far */ + + curl_off_t current_speed; /* uses the currently fastest transfer */ + + bool callback; /* set when progress callback is used */ + int width; /* screen width at download start */ + int flags; /* see progress.h */ + + double timespent; + + curl_off_t dlspeed; + curl_off_t ulspeed; + + double t_nslookup; + double t_connect; + double t_appconnect; + double t_pretransfer; + double t_starttransfer; + double t_redirect; + + struct timeval start; + struct timeval t_startsingle; + struct timeval t_startop; + struct timeval t_acceptdata; +#define CURR_TIME (5+1) /* 6 entries for 5 seconds */ + + curl_off_t speeder[ CURR_TIME ]; + struct timeval speeder_time[ CURR_TIME ]; + int speeder_c; +}; + +typedef enum { + HTTPREQ_NONE, /* first in list */ + HTTPREQ_GET, + HTTPREQ_POST, + HTTPREQ_POST_FORM, /* we make a difference internally */ + HTTPREQ_PUT, + HTTPREQ_HEAD, + HTTPREQ_CUSTOM, + HTTPREQ_LAST /* last in list */ +} Curl_HttpReq; + +typedef enum { + RTSPREQ_NONE, /* first in list */ + RTSPREQ_OPTIONS, + RTSPREQ_DESCRIBE, + RTSPREQ_ANNOUNCE, + RTSPREQ_SETUP, + RTSPREQ_PLAY, + RTSPREQ_PAUSE, + RTSPREQ_TEARDOWN, + RTSPREQ_GET_PARAMETER, + RTSPREQ_SET_PARAMETER, + RTSPREQ_RECORD, + RTSPREQ_RECEIVE, + RTSPREQ_LAST /* last in list */ +} Curl_RtspReq; + +/* + * Values that are generated, temporary or calculated internally for a + * "session handle" must be defined within the 'struct UrlState'. This struct + * will be used within the SessionHandle struct. When the 'SessionHandle' + * struct is cloned, this data MUST NOT be copied. + * + * Remember that any "state" information goes globally for the curl handle. + * Session-data MUST be put in the connectdata struct and here. */ +#define MAX_CURL_USER_LENGTH 256 +#define MAX_CURL_PASSWORD_LENGTH 256 + +struct auth { + unsigned long want; /* Bitmask set to the authentication methods wanted by + app (with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH). */ + unsigned long picked; + unsigned long avail; /* Bitmask for what the server reports to support for + this resource */ + bool done; /* TRUE when the auth phase is done and ready to do the *actual* + request */ + bool multi; /* TRUE if this is not yet authenticated but within the auth + multipass negotiation */ + bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should + be RFC compliant */ +}; + +struct UrlState { + + /* Points to the connection cache */ + struct conncache *conn_cache; + + /* when curl_easy_perform() is called, the multi handle is "owned" by + the easy handle so curl_easy_cleanup() on such an easy handle will + also close the multi handle! */ + bool multi_owned_by_easy; + + /* buffers to store authentication data in, as parsed from input options */ + struct timeval keeps_speed; /* for the progress meter really */ + + struct connectdata *lastconnect; /* The last connection, NULL if undefined */ + + char *headerbuff; /* allocated buffer to store headers in */ + size_t headersize; /* size of the allocation */ + + char buffer[BUFSIZE+1]; /* download buffer */ + char uploadbuffer[BUFSIZE+1]; /* upload buffer */ + curl_off_t current_speed; /* the ProgressShow() funcion sets this, + bytes / second */ + bool this_is_a_follow; /* this is a followed Location: request */ + + char *first_host; /* if set, this should be the host name that we will + sent authorization to, no else. Used to make Location: + following not keep sending user+password... This is + strdup() data. + */ + struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ + long sessionage; /* number of the most recent session */ + char *tempwrite; /* allocated buffer to keep data in when a write + callback returns to make the connection paused */ + size_t tempwritesize; /* size of the 'tempwrite' allocated buffer */ + int tempwritetype; /* type of the 'tempwrite' buffer as a bitmask that is + used with Curl_client_write() */ + char *scratch; /* huge buffer[BUFSIZE*2] when doing upload CRLF replacing */ + bool errorbuf; /* Set to TRUE if the error buffer is already filled in. + This must be set to FALSE every time _easy_perform() is + called. */ + int os_errno; /* filled in with errno whenever an error occurs */ +#ifdef HAVE_SIGNAL + /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ + void (*prev_signal)(int sig); +#endif + bool allow_port; /* Is set.use_port allowed to take effect or not. This + is always set TRUE when curl_easy_perform() is called. */ + struct digestdata digest; /* state data for host Digest auth */ + struct digestdata proxydigest; /* state data for proxy Digest auth */ + +#ifdef USE_SPNEGO + struct negotiatedata negotiate; /* state data for host Negotiate auth */ + struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ +#endif + + struct auth authhost; /* auth details for host */ + struct auth authproxy; /* auth details for proxy */ + + bool authproblem; /* TRUE if there's some problem authenticating */ + + void *resolver; /* resolver state, if it is used in the URL state - + ares_channel f.e. */ + +#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H) + ENGINE *engine; +#endif /* USE_OPENSSL */ + struct timeval expiretime; /* set this with Curl_expire() only */ + struct Curl_tree timenode; /* for the splay stuff */ + struct curl_llist *timeoutlist; /* list of pending timeouts */ + + /* a place to store the most recently set FTP entrypath */ + char *most_recent_ftp_entrypath; + + /* set after initial USER failure, to prevent an authentication loop */ + bool ftp_trying_alternative; + + int httpversion; /* the lowest HTTP version*10 reported by any server + involved in this request */ + bool expect100header; /* TRUE if we added Expect: 100-continue */ + + bool pipe_broke; /* TRUE if the connection we were pipelined on broke + and we need to restart from the beginning */ + +#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \ + !defined(__SYMBIAN32__) +/* do FTP line-end conversions on most platforms */ +#define CURL_DO_LINEEND_CONV + /* for FTP downloads: track CRLF sequences that span blocks */ + bool prev_block_had_trailing_cr; + /* for FTP downloads: how many CRLFs did we converted to LFs? */ + curl_off_t crlf_conversions; +#endif + char *pathbuffer;/* allocated buffer to store the URL's path part in */ + char *path; /* path to use, points to somewhere within the pathbuffer + area */ + bool slash_removed; /* set TRUE if the 'path' points to a path where the + initial URL slash separator has been taken off */ + bool use_range; + bool rangestringalloc; /* the range string is malloc()'ed */ + + char *range; /* range, if used. See README for detailed specification on + this syntax. */ + curl_off_t resume_from; /* continue [ftp] transfer from here */ + + /* This RTSP state information survives requests and connections */ + long rtsp_next_client_CSeq; /* the session's next client CSeq */ + long rtsp_next_server_CSeq; /* the session's next server CSeq */ + long rtsp_CSeq_recv; /* most recent CSeq received */ + + curl_off_t infilesize; /* size of file to upload, -1 means unknown. + Copied from set.filesize at start of operation */ +}; + + +/* + * This 'DynamicStatic' struct defines dynamic states that actually change + * values in the 'UserDefined' area, which MUST be taken into consideration + * if the UserDefined struct is cloned or similar. You can probably just + * copy these, but each one indicate a special action on other data. + */ + +struct DynamicStatic { + char *url; /* work URL, copied from UserDefined */ + bool url_alloc; /* URL string is malloc()'ed */ + char *referer; /* referer string */ + bool referer_alloc; /* referer sting is malloc()ed */ + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ + struct curl_slist *resolve; /* set to point to the set.resolve list when + this should be dealt with in pretransfer */ +}; + +/* + * This 'UserDefined' struct must only contain data that is set once to go + * for many (perhaps) independent connections. Values that are generated or + * calculated internally for the "session handle" MUST be defined within the + * 'struct UrlState' instead. The only exceptions MUST note the changes in + * the 'DynamicStatic' struct. + * Character pointer fields point to dynamic storage, unless otherwise stated. + */ + +struct Curl_multi; /* declared and used only in multi.c */ + +enum dupstring { + STRING_CERT, /* client certificate file name */ + STRING_CERT_TYPE, /* format for certificate (default: PEM)*/ + STRING_COOKIE, /* HTTP cookie string to send */ + STRING_COOKIEJAR, /* dump all cookies to this file */ + STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */ + STRING_DEVICE, /* local network interface/address to use */ + STRING_ENCODING, /* Accept-Encoding string */ + STRING_FTP_ACCOUNT, /* ftp account data */ + STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */ + STRING_FTPPORT, /* port to send with the FTP PORT command */ + STRING_KEY, /* private key file name */ + STRING_KEY_PASSWD, /* plain text private key password */ + STRING_KEY_TYPE, /* format for private key (default: PEM) */ + STRING_KRB_LEVEL, /* krb security level */ + STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find + $HOME/.netrc */ + STRING_PROXY, /* proxy to use */ + STRING_SET_RANGE, /* range, if used */ + STRING_SET_REFERER, /* custom string for the HTTP referer field */ + STRING_SET_URL, /* what original URL to work on */ + STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAFILE, /* certificate file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */ + STRING_SSL_CIPHER_LIST, /* list of ciphers to use */ + STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */ + STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */ + STRING_USERAGENT, /* User-Agent string */ + STRING_SSL_CRLFILE, /* crl file to check certificate */ + STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ + STRING_USERNAME, /* , if used */ + STRING_PASSWORD, /* , if used */ + STRING_OPTIONS, /* , if used */ + STRING_PROXYUSERNAME, /* Proxy , if used */ + STRING_PROXYPASSWORD, /* Proxy , if used */ + STRING_NOPROXY, /* List of hosts which should not use the proxy, if + used */ + STRING_RTSP_SESSION_ID, /* Session ID to use */ + STRING_RTSP_STREAM_URI, /* Stream URI for this request */ + STRING_RTSP_TRANSPORT, /* Transport for this session */ +#ifdef USE_LIBSSH2 + STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */ + STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */ + STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */ + STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */ +#endif +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */ +#endif + STRING_MAIL_FROM, + STRING_MAIL_AUTH, + +#ifdef USE_TLS_SRP + STRING_TLSAUTH_USERNAME, /* TLS auth */ + STRING_TLSAUTH_PASSWORD, /* TLS auth */ +#endif + STRING_BEARER, /* , if used */ +#ifdef USE_UNIX_SOCKETS + STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */ +#endif + + /* -- end of zero-terminated strings -- */ + + STRING_LASTZEROTERMINATED, + + /* -- below this are pointers to binary data that cannot be strdup'ed. + Each such pointer must be added manually to Curl_dupset() --- */ + + STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ + + STRING_LAST /* not used, just an end-of-list marker */ +}; + +struct UserDefined { + FILE *err; /* the stderr user data goes here */ + void *debugdata; /* the data that will be passed to fdebug */ + char *errorbuffer; /* (Static) store failure messages in here */ + long proxyport; /* If non-zero, use this port number by default. If the + proxy string features a ":[port]" that one will override + this. */ + void *out; /* the fetched file goes here */ + void *in; /* the uploaded file is read from here */ + void *writeheader; /* write the header to this if non-NULL */ + void *rtp_out; /* write RTP to this if non-NULL */ + long use_port; /* which port to use (when not using default) */ + unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */ + unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */ + long followlocation; /* as in HTTP Location: */ + long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1 + for infinity */ + + int keep_post; /* keep POSTs as POSTs after a 30x request; each + bit represents a request, from 301 to 303 */ + bool free_referer; /* set TRUE if 'referer' points to a string we + allocated */ + void *postfields; /* if POST, set the fields' values here */ + curl_seek_callback seek_func; /* function that seeks the input */ + curl_off_t postfieldsize; /* if POST, this might have a size to use instead + of strlen(), and then the data *may* be binary + (contain zero bytes) */ + unsigned short localport; /* local port number to bind to */ + int localportrange; /* number of additional port numbers to test in case the + 'localport' one can't be bind()ed */ + curl_write_callback fwrite_func; /* function that stores the output */ + curl_write_callback fwrite_header; /* function that stores headers */ + curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */ + curl_read_callback fread_func; /* function that reads the input */ + int is_fread_set; /* boolean, has read callback been set to non-NULL? */ + int is_fwrite_set; /* boolean, has write callback been set to non-NULL? */ + curl_progress_callback fprogress; /* OLD and deprecated progress callback */ + curl_xferinfo_callback fxferinfo; /* progress callback */ + curl_debug_callback fdebug; /* function that write informational data */ + curl_ioctl_callback ioctl_func; /* function for I/O control */ + curl_sockopt_callback fsockopt; /* function for setting socket options */ + void *sockopt_client; /* pointer to pass to the socket options callback */ + curl_opensocket_callback fopensocket; /* function for checking/translating + the address and opening the + socket */ + void* opensocket_client; + curl_closesocket_callback fclosesocket; /* function for closing the + socket */ + void* closesocket_client; + + void *seek_client; /* pointer to pass to the seek callback */ + /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ + /* function to convert from the network encoding: */ + curl_conv_callback convfromnetwork; + /* function to convert to the network encoding: */ + curl_conv_callback convtonetwork; + /* function to convert from UTF-8 encoding: */ + curl_conv_callback convfromutf8; + + void *progress_client; /* pointer to pass to the progress callback */ + void *ioctl_client; /* pointer to pass to the ioctl callback */ + long timeout; /* in milliseconds, 0 means no timeout */ + long connecttimeout; /* in milliseconds, 0 means no timeout */ + long accepttimeout; /* in milliseconds, 0 means no timeout */ + long server_response_timeout; /* in milliseconds, 0 means no timeout */ + long tftp_blksize ; /* in bytes, 0 means use default */ + curl_off_t filesize; /* size of file to upload, -1 means unknown */ + long low_speed_limit; /* bytes/second */ + long low_speed_time; /* number of seconds */ + curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */ + curl_off_t max_recv_speed; /* high speed limit in bytes/second for + download */ + curl_off_t set_resume_from; /* continue [ftp] transfer from here */ + struct curl_slist *headers; /* linked list of extra headers */ + struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */ + struct curl_httppost *httppost; /* linked list of POST data */ + bool sep_headers; /* handle host and proxy headers separately */ + bool cookiesession; /* new cookie session? */ + bool crlf; /* convert crlf on ftp upload(?) */ + struct curl_slist *quote; /* after connection is established */ + struct curl_slist *postquote; /* after the transfer */ + struct curl_slist *prequote; /* before the transfer, after type */ + struct curl_slist *source_quote; /* 3rd party quote */ + struct curl_slist *source_prequote; /* in 3rd party transfer mode - before + the transfer on source host */ + struct curl_slist *source_postquote; /* in 3rd party transfer mode - after + the transfer on source host */ + struct curl_slist *telnet_options; /* linked list of telnet options */ + struct curl_slist *resolve; /* list of names to add/remove from + DNS cache */ + curl_TimeCond timecondition; /* kind of time/date comparison */ + time_t timevalue; /* what time to compare with */ + Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ + long httpversion; /* when non-zero, a specific HTTP version requested to + be used in the library's request(s) */ + struct ssl_config_data ssl; /* user defined SSL stuff */ + curl_proxytype proxytype; /* what kind of proxy that is in use */ + long dns_cache_timeout; /* DNS cache timeout */ + long buffer_size; /* size of receive buffer to use */ + void *private_data; /* application-private data */ + + struct curl_slist *http200aliases; /* linked list of aliases for http200 */ + + long ipver; /* the CURL_IPRESOLVE_* defines in the public header file + 0 - whatever, 1 - v2, 2 - v6 */ + + curl_off_t max_filesize; /* Maximum file size to download */ + + curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */ + + int ftp_create_missing_dirs; /* 1 - create directories that don't exist + 2 - the same but also allow MKD to fail once + */ + + curl_sshkeycallback ssh_keyfunc; /* key matching callback */ + void *ssh_keyfunc_userp; /* custom pointer to callback */ + +/* Here follows boolean settings that define how to behave during + this session. They are STATIC, set by libcurl users or at least initially + and they don't change during operations. */ + + bool printhost; /* printing host name in debug info */ + bool get_filetime; /* get the time and get of the remote file */ + bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */ + bool prefer_ascii; /* ASCII rather than binary */ + bool ftp_append; /* append, not overwrite, on upload */ + bool ftp_list_only; /* switch FTP command for listing directories */ + bool ftp_use_port; /* use the FTP PORT command */ + bool hide_progress; /* don't use the progress meter */ + bool http_fail_on_error; /* fail on HTTP error codes >= 400 */ + bool http_follow_location; /* follow HTTP redirects */ + bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */ + bool http_disable_hostname_check_before_authentication; + bool include_header; /* include received protocol headers in data output */ + bool http_set_referer; /* is a custom referer used */ + bool http_auto_referer; /* set "correct" referer when following location: */ + bool opt_no_body; /* as set with CURLOPT_NOBODY */ + bool set_port; /* custom port number used */ + bool upload; /* upload request */ + enum CURL_NETRC_OPTION + use_netrc; /* defined in include/curl.h */ + bool verbose; /* output verbosity */ + bool krb; /* Kerberos connection requested */ + bool reuse_forbid; /* forbidden to be reused, close after use */ + bool reuse_fresh; /* do not re-use an existing connection */ + bool ftp_use_epsv; /* if EPSV is to be attempted or not */ + bool ftp_use_eprt; /* if EPRT is to be attempted or not */ + bool ftp_use_pret; /* if PRET is to be used before PASV or not */ + + curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or + IMAP or POP3 or others! */ + curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */ + curl_ftpccc ftp_ccc; /* FTP CCC options */ + bool no_signal; /* do not use any signal/alarm handler */ + bool global_dns_cache; /* subject for future removal */ + bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */ + bool ignorecl; /* ignore content length */ + bool ftp_skip_ip; /* skip the IP address the FTP server passes on to + us */ + bool connect_only; /* make connection, let application use the socket */ + bool ssl_enable_beast; /* especially allow this flaw for interoperability's + sake*/ + long ssh_auth_types; /* allowed SSH auth types */ + bool http_te_skip; /* pass the raw body data to the user, even when + transfer-encoded (chunked, compressed) */ + bool http_ce_skip; /* pass the raw body data to the user, even when + content-encoded (chunked, compressed) */ + long new_file_perms; /* Permissions to use when creating remote files */ + long new_directory_perms; /* Permissions to use when creating remote dirs */ + bool proxy_transfer_mode; /* set transfer mode (;type=) when doing FTP + via an HTTP proxy */ + char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ + unsigned int scope_id; /* Scope id for IPv6 */ + long allowed_protocols; + long redir_protocols; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + long socks5_gssapi_nec; /* flag to support nec socks5 server */ +#endif + struct curl_slist *mail_rcpt; /* linked list of mail recipients */ + bool sasl_ir; /* Enable/disable SASL initial response */ + /* Common RTSP header options */ + Curl_RtspReq rtspreq; /* RTSP request type */ + long rtspversion; /* like httpversion, for RTSP */ + bool wildcardmatch; /* enable wildcard matching */ + curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer + starts */ + curl_chunk_end_callback chunk_end; /* called after part transferring + stopped */ + curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds + to pattern (e.g. if WILDCARDMATCH is on) */ + void *fnmatch_data; + + long gssapi_delegation; /* GSS-API credential delegation, see the + documentation of CURLOPT_GSSAPI_DELEGATION */ + + bool tcp_keepalive; /* use TCP keepalives */ + long tcp_keepidle; /* seconds in idle before sending keepalive probe */ + long tcp_keepintvl; /* seconds between TCP keepalive probes */ + + size_t maxconnects; /* Max idle connections in the connection cache */ + + bool ssl_enable_npn; /* TLS NPN extension? */ + bool ssl_enable_alpn; /* TLS ALPN extension? */ + bool path_as_is; /* allow dotdots? */ + long expect_100_timeout; /* in milliseconds */ +}; + +struct Names { + struct curl_hash *hostcache; + enum { + HCACHE_NONE, /* not pointing to anything */ + HCACHE_GLOBAL, /* points to the (shrug) global one */ + HCACHE_MULTI, /* points to a shared one in the multi handle */ + HCACHE_SHARED /* points to a shared one in a shared object */ + } hostcachetype; +}; + +/* + * The 'connectdata' struct MUST have all the connection oriented stuff as we + * may have several simultaneous connections and connection structs in memory. + * + * The 'struct UserDefined' must only contain data that is set once to go for + * many (perhaps) independent connections. Values that are generated or + * calculated internally for the "session handle" must be defined within the + * 'struct UrlState' instead. + */ + +struct SessionHandle { + /* first, two fields for the linked list of these */ + struct SessionHandle *next; + struct SessionHandle *prev; + + struct connectdata *easy_conn; /* the "unit's" connection */ + + CURLMstate mstate; /* the handle's state */ + CURLcode result; /* previous result */ + + struct Curl_message msg; /* A single posted message. */ + + /* Array with the plain socket numbers this handle takes care of, in no + particular order. Note that all sockets are added to the sockhash, where + the state etc are also kept. This array is mostly used to detect when a + socket is to be removed from the hash. See singlesocket(). */ + curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; + int numsocks; + + struct Names dns; + struct Curl_multi *multi; /* if non-NULL, points to the multi handle + struct to which this "belongs" when used by + the multi interface */ + struct Curl_multi *multi_easy; /* if non-NULL, points to the multi handle + struct to which this "belongs" when used + by the easy interface */ + struct Curl_share *share; /* Share, handles global variable mutexing */ + struct SingleRequest req; /* Request-specific data */ + struct UserDefined set; /* values set by the libcurl user */ + struct DynamicStatic change; /* possibly modified userdefined data */ + struct CookieInfo *cookies; /* the cookies, read from files and servers. + NOTE that the 'cookie' field in the + UserDefined struct defines if the "engine" + is to be used or not. */ + struct Progress progress; /* for all the progress meter data */ + struct UrlState state; /* struct for fields used for state info and + other dynamic purposes */ + struct WildcardData wildcard; /* wildcard download state info */ + struct PureInfo info; /* stats, reports and info data */ + struct curl_tlssessioninfo tsi; /* Information about the TLS session, only + valid after a client has asked for it */ +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) + iconv_t outbound_cd; /* for translating to the network encoding */ + iconv_t inbound_cd; /* for translating from the network encoding */ + iconv_t utf8_cd; /* for translating to UTF8 */ +#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ + unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */ +}; + +#define LIBCURL_NAME "libcurl" + +#endif /* HEADER_CURL_URLDATA_H */ diff --git a/libcurl/src/lib/version.c b/libcurl/src/lib/version.c new file mode 100644 index 0000000..34d2c02 --- /dev/null +++ b/libcurl/src/lib/version.c @@ -0,0 +1,362 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "vtls/vtls.h" +#include "http2.h" +#include "curl_printf.h" + +#ifdef USE_ARES +# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) +# define CARES_STATICLIB +# endif +# include +#endif + +#ifdef USE_LIBIDN +#include +#endif + +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#include +#endif + +#ifdef USE_LIBRTMP +#include +#endif + +#ifdef USE_LIBSSH2 +#include +#endif + +#ifdef HAVE_LIBSSH2_VERSION +/* get it run-time if possible */ +#define CURL_LIBSSH2_VERSION libssh2_version(0) +#else +/* use build-time if run-time not possible */ +#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION +#endif + +char *curl_version(void) +{ + static char version[200]; + char *ptr = version; + size_t len; + size_t left = sizeof(version); + + strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION); + len = strlen(ptr); + left -= len; + ptr += len; + + if(left > 1) { + len = Curl_ssl_version(ptr + 1, left - 1); + + if(len > 0) { + *ptr = ' '; + left -= ++len; + ptr += len; + } + } + +#ifdef HAVE_LIBZ + len = snprintf(ptr, left, " zlib/%s", zlibVersion()); + left -= len; + ptr += len; +#endif +#ifdef USE_ARES + /* this function is only present in c-ares, not in the original ares */ + len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL)); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBIDN + if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) { + len = snprintf(ptr, left, " libidn/%s", stringprep_check_version(NULL)); + left -= len; + ptr += len; + } +#endif +#ifdef USE_WIN32_IDN + len = snprintf(ptr, left, " WinIDN"); + left -= len; + ptr += len; +#endif +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#ifdef _LIBICONV_VERSION + len = snprintf(ptr, left, " iconv/%d.%d", + _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255); +#else + /* version unknown */ + len = snprintf(ptr, left, " iconv"); +#endif /* _LIBICONV_VERSION */ + left -= len; + ptr += len; +#endif +#ifdef USE_LIBSSH2 + len = snprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION); + left -= len; + ptr += len; +#endif +#ifdef USE_NGHTTP2 + len = Curl_http2_ver(ptr, left); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBRTMP + { + char suff[2]; + if(RTMP_LIB_VERSION & 0xff) { + suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1; + suff[1] = '\0'; + } + else + suff[0] = '\0'; + + snprintf(ptr, left, " librtmp/%d.%d%s", + RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff, + suff); +/* + If another lib version is added below this one, this code would + also have to do: + + len = what snprintf() returned + + left -= len; + ptr += len; +*/ + } +#endif + + return version; +} + +/* data for curl_version_info + + Keep the list sorted alphabetically. It is also written so that each + protocol line has its own #if line to make things easier on the eye. + */ + +static const char * const protocol_names[] = { +#ifndef CURL_DISABLE_DICT + "dict", +#endif +#ifndef CURL_DISABLE_FILE + "file", +#endif +#ifndef CURL_DISABLE_FTP + "ftp", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + "ftps", +#endif +#ifndef CURL_DISABLE_GOPHER + "gopher", +#endif +#ifndef CURL_DISABLE_HTTP + "http", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + "https", +#endif +#ifndef CURL_DISABLE_IMAP + "imap", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) + "imaps", +#endif +#ifndef CURL_DISABLE_LDAP + "ldap", +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + "ldaps", +#endif +#endif +#ifndef CURL_DISABLE_POP3 + "pop3", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) + "pop3s", +#endif +#ifdef USE_LIBRTMP + "rtmp", +#endif +#ifndef CURL_DISABLE_RTSP + "rtsp", +#endif +#ifdef USE_LIBSSH2 + "scp", +#endif +#ifdef USE_LIBSSH2 + "sftp", +#endif +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) && \ + (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)) + "smb", +# ifdef USE_SSL + "smbs", +# endif +#endif +#ifndef CURL_DISABLE_SMTP + "smtp", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) + "smtps", +#endif +#ifndef CURL_DISABLE_TELNET + "telnet", +#endif +#ifndef CURL_DISABLE_TFTP + "tftp", +#endif + + NULL +}; + +static curl_version_info_data version_info = { + CURLVERSION_NOW, + LIBCURL_VERSION, + LIBCURL_VERSION_NUM, + OS, /* as found by configure or set by hand at build-time */ + 0 /* features is 0 by default */ +#ifdef ENABLE_IPV6 + | CURL_VERSION_IPV6 +#endif +#ifdef USE_SSL + | CURL_VERSION_SSL +#endif +#ifdef USE_NTLM + | CURL_VERSION_NTLM +#endif +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + | CURL_VERSION_NTLM_WB +#endif +#ifdef USE_SPNEGO + | CURL_VERSION_SPNEGO +#endif +#ifdef USE_KERBEROS5 + | CURL_VERSION_KERBEROS5 +#endif +#ifdef HAVE_GSSAPI + | CURL_VERSION_GSSAPI +#endif +#ifdef USE_WINDOWS_SSPI + | CURL_VERSION_SSPI +#endif +#ifdef HAVE_LIBZ + | CURL_VERSION_LIBZ +#endif +#ifdef DEBUGBUILD + | CURL_VERSION_DEBUG +#endif +#ifdef CURLDEBUG + | CURL_VERSION_CURLDEBUG +#endif +#ifdef CURLRES_ASYNCH + | CURL_VERSION_ASYNCHDNS +#endif +#if (CURL_SIZEOF_CURL_OFF_T > 4) && \ + ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) + | CURL_VERSION_LARGEFILE +#endif +#if defined(CURL_DOES_CONVERSIONS) + | CURL_VERSION_CONV +#endif +#if defined(USE_TLS_SRP) + | CURL_VERSION_TLSAUTH_SRP +#endif +#if defined(USE_NGHTTP2) + | CURL_VERSION_HTTP2 +#endif +#if defined(USE_UNIX_SOCKETS) + | CURL_VERSION_UNIX_SOCKETS +#endif + , + NULL, /* ssl_version */ + 0, /* ssl_version_num, this is kept at zero */ + NULL, /* zlib_version */ + protocol_names, + NULL, /* c-ares version */ + 0, /* c-ares version numerical */ + NULL, /* libidn version */ + 0, /* iconv version */ + NULL, /* ssh lib version */ +}; + +curl_version_info_data *curl_version_info(CURLversion stamp) +{ +#ifdef USE_LIBSSH2 + static char ssh_buffer[80]; +#endif + +#ifdef USE_SSL + static char ssl_buffer[80]; + Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer)); + version_info.ssl_version = ssl_buffer; +#endif + +#ifdef HAVE_LIBZ + version_info.libz_version = zlibVersion(); + /* libz left NULL if non-existing */ +#endif +#ifdef USE_ARES + { + int aresnum; + version_info.ares = ares_version(&aresnum); + version_info.ares_num = aresnum; + } +#endif +#ifdef USE_LIBIDN + /* This returns a version string if we use the given version or later, + otherwise it returns NULL */ + version_info.libidn = stringprep_check_version(LIBIDN_REQUIRED_VERSION); + if(version_info.libidn) + version_info.features |= CURL_VERSION_IDN; +#elif defined(USE_WIN32_IDN) + version_info.features |= CURL_VERSION_IDN; +#endif + +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#ifdef _LIBICONV_VERSION + version_info.iconv_ver_num = _LIBICONV_VERSION; +#else + /* version unknown */ + version_info.iconv_ver_num = -1; +#endif /* _LIBICONV_VERSION */ +#endif + +#ifdef USE_LIBSSH2 + snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION); + version_info.libssh_version = ssh_buffer; +#endif + + (void)stamp; /* avoid compiler warnings, we don't use this */ + + return &version_info; +} diff --git a/libcurl/src/lib/vtls/axtls.c b/libcurl/src/lib/vtls/axtls.c new file mode 100644 index 0000000..8d7e0f9 --- /dev/null +++ b/libcurl/src/lib/vtls/axtls.c @@ -0,0 +1,696 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, DirecTV, Contact: Eric Hu, . + * Copyright (C) 2010 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all axTLS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +#include "../curl_setup.h" + +#ifdef USE_AXTLS +#include +#include +#include "axtls.h" + +#include "../sendf.h" +#include "../inet_pton.h" +#include "vtls.h" +#include "../parsedate.h" +#include "../connect.h" /* for the connect timeout */ +#include "../select.h" +#include "../curl_printf.h" +#include "../hostcheck.h" +#if !defined(_MSC_VER) +#include +#endif + +/* The last #include files should be: */ +#include "../curl_memory.h" +#include "../memdebug.h" + + +/* Global axTLS init, called from Curl_ssl_init() */ +CURL_STATIC int Curl_axtls_init(void) +{ +/* axTLS has no global init. Everything is done through SSL and SSL_CTX + * structs stored in connectdata structure. Perhaps can move to axtls.h. + */ + return 1; +} + +CURL_STATIC int Curl_axtls_cleanup(void) +{ + /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */ + return 1; +} + +static CURLcode map_error_to_curl(int axtls_err) +{ + switch (axtls_err) { + case SSL_ERROR_NOT_SUPPORTED: + case SSL_ERROR_INVALID_VERSION: + case -70: /* protocol version alert from server */ + return CURLE_UNSUPPORTED_PROTOCOL; + break; + case SSL_ERROR_NO_CIPHER: + return CURLE_SSL_CIPHER; + break; + case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */ + case SSL_ERROR_NO_CERT_DEFINED: + case -42: /* bad certificate alert from server */ + case -43: /* unsupported cert alert from server */ + case -44: /* cert revoked alert from server */ + case -45: /* cert expired alert from server */ + case -46: /* cert unknown alert from server */ + return CURLE_SSL_CERTPROBLEM; + break; + case SSL_X509_ERROR(X509_NOT_OK): + case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT): + case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE): + case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID): + case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED): + case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED): + case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN): + case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): + case SSL_X509_ERROR(X509_INVALID_PRIV_KEY): + return CURLE_PEER_FAILED_VERIFICATION; + break; + case -48: /* unknown ca alert from server */ + return CURLE_SSL_CACERT; + break; + case -49: /* access denied alert from server */ + return CURLE_REMOTE_ACCESS_DENIED; + break; + case SSL_ERROR_CONN_LOST: + case SSL_ERROR_SOCK_SETUP_FAILURE: + case SSL_ERROR_INVALID_HANDSHAKE: + case SSL_ERROR_INVALID_PROT_MSG: + case SSL_ERROR_INVALID_HMAC: + case SSL_ERROR_INVALID_SESSION: + case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */ + case SSL_ERROR_FINISHED_INVALID: + case SSL_ERROR_NO_CLIENT_RENOG: + default: + return CURLE_SSL_CONNECT_ERROR; + break; + } +} + +static Curl_recv axtls_recv; +static Curl_send axtls_send; + +static void free_ssl_structs(struct ssl_connect_data *connssl) +{ + if(connssl->ssl) { + ssl_free (connssl->ssl); + connssl->ssl = NULL; + } + if(connssl->ssl_ctx) { + ssl_ctx_free(connssl->ssl_ctx); + connssl->ssl_ctx = NULL; + } +} + +/* + * For both blocking and non-blocking connects, this function sets up the + * ssl context and state. This function is called after the TCP connect + * has completed. + */ +static CURLcode connect_prep(struct connectdata *conn, int sockindex) +{ + struct SessionHandle *data = conn->data; + SSL_CTX *ssl_ctx; + SSL *ssl = NULL; + int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0}; + int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0}; + int i, ssl_fcn_return; + const uint8_t *ssl_sessionid; + size_t ssl_idsize; + + /* Assuming users will not compile in custom key/cert to axTLS. + * Also, even for blocking connects, use axTLS non-blocking feature. + */ + uint32_t client_option = SSL_NO_DEFAULT_KEY | + SSL_SERVER_VERIFY_LATER | + SSL_CONNECT_IN_PARTS; + + if(conn->ssl[sockindex].state == ssl_connection_complete) + /* to make us tolerant against being called more than once for the + same connection */ + return CURLE_OK; + + /* axTLS only supports TLSv1 */ + /* check to see if we've been told to use an explicit SSL/TLS version */ + switch(data->set.ssl.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + break; + default: + failf(data, "axTLS only supports TLS 1.0 and 1.1, " + "and it cannot be specified which one to use"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef AXTLSDEBUG + client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS; +#endif /* AXTLSDEBUG */ + + /* Allocate an SSL_CTX struct */ + ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS); + if(ssl_ctx == NULL) { + failf(data, "unable to create client SSL context"); + return CURLE_SSL_CONNECT_ERROR; + } + + conn->ssl[sockindex].ssl_ctx = ssl_ctx; + conn->ssl[sockindex].ssl = NULL; + + /* Load the trusted CA cert bundle file */ + if(data->set.ssl.CAfile) { + if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) + != SSL_OK) { + infof(data, "error reading ca cert file %s \n", + data->set.ssl.CAfile); + if(data->set.ssl.verifypeer) { + return CURLE_SSL_CACERT_BADFILE; + } + } + else + infof(data, "found certificates in %s\n", data->set.ssl.CAfile); + } + + /* gtls.c tasks we're skipping for now: + * 1) certificate revocation list checking + * 2) dns name assignment to host + * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore + * 4) set certificate priority. axTLS ignores type and sends certs in + * order added. can probably ignore this. + */ + + /* Load client certificate */ + if(data->set.str[STRING_CERT]) { + i=0; + /* Instead of trying to analyze cert type here, let axTLS try them all. */ + while(cert_types[i] != 0) { + ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], + data->set.str[STRING_CERT], NULL); + if(ssl_fcn_return == SSL_OK) { + infof(data, "successfully read cert file %s \n", + data->set.str[STRING_CERT]); + break; + } + i++; + } + /* Tried all cert types, none worked. */ + if(cert_types[i] == 0) { + failf(data, "%s is not x509 or pkcs12 format", + data->set.str[STRING_CERT]); + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load client key. + If a pkcs12 file successfully loaded a cert, then there's nothing to do + because the key has already been loaded. */ + if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) { + i=0; + /* Instead of trying to analyze key type here, let axTLS try them all. */ + while(key_types[i] != 0) { + ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], + data->set.str[STRING_KEY], NULL); + if(ssl_fcn_return == SSL_OK) { + infof(data, "successfully read key file %s \n", + data->set.str[STRING_KEY]); + break; + } + i++; + } + /* Tried all key types, none worked. */ + if(key_types[i] == 0) { + failf(data, "Failure: %s is not a supported key file", + data->set.str[STRING_KEY]); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* gtls.c does more here that is being left out for now + * 1) set session credentials. can probably ignore since axtls puts this + * info in the ssl_ctx struct + * 2) setting up callbacks. these seem gnutls specific + */ + + /* In axTLS, handshaking happens inside ssl_client_new. */ + if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) { + /* we got a session id, use it! */ + infof (data, "SSL re-using session ID\n"); + ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], + ssl_sessionid, (uint8_t)ssl_idsize); + } + else + ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); + + conn->ssl[sockindex].ssl = ssl; + return CURLE_OK; +} + +/* + * For both blocking and non-blocking connects, this function finalizes the + * SSL connection. + */ +static CURLcode connect_finish(struct connectdata *conn, int sockindex) +{ + struct SessionHandle *data = conn->data; + SSL *ssl = conn->ssl[sockindex].ssl; + const uint8_t *ssl_sessionid; + size_t ssl_idsize; + const char *peer_CN; + uint32_t dns_altname_index; + const char *dns_altname; + int8_t found_subject_alt_names = 0; + int8_t found_subject_alt_name_matching_conn = 0; + + /* Here, gtls.c gets the peer certificates and fails out depending on + * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? + */ + + /* Verify server's certificate */ + if(data->set.ssl.verifypeer) { + if(ssl_verify_cert(ssl) != SSL_OK) { + Curl_axtls_close(conn, sockindex); + failf(data, "server cert verify failed"); + return CURLE_PEER_FAILED_VERIFICATION; + } + } + else + infof(data, "\t server certificate verification SKIPPED\n"); + + /* Here, gtls.c does issuer verification. axTLS has no straightforward + * equivalent, so omitting for now.*/ + + /* Here, gtls.c does the following + * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but + * it seems useful. This is now implemented, by Oscar Koeroo + * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert + * 3) displays a bunch of cert information. axTLS doesn't support most of + * this, but a couple fields are available. + */ + + /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a + risk of an inifite loop */ + for(dns_altname_index = 0; ; dns_altname_index++) { + dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index); + if(dns_altname == NULL) { + break; + } + found_subject_alt_names = 1; + + infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n", + dns_altname, conn->host.name); + if(Curl_cert_hostcheck(dns_altname, conn->host.name)) { + found_subject_alt_name_matching_conn = 1; + break; + } + } + + /* RFC2818 checks */ + if(found_subject_alt_names && !found_subject_alt_name_matching_conn) { + if(data->set.ssl.verifyhost) { + /* Break connection ! */ + Curl_axtls_close(conn, sockindex); + failf(data, "\tsubjectAltName(s) do not match %s\n", + conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\tsubjectAltName(s) do not match %s\n", + conn->host.dispname); + } + else if(found_subject_alt_names == 0) { + /* Per RFC2818, when no Subject Alt Names were available, examine the peer + CN as a legacy fallback */ + peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); + if(peer_CN == NULL) { + if(data->set.ssl.verifyhost) { + Curl_axtls_close(conn, sockindex); + failf(data, "unable to obtain common name from peer certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "unable to obtain common name from peer certificate"); + } + else { + if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { + if(data->set.ssl.verifyhost) { + /* Break connection ! */ + Curl_axtls_close(conn, sockindex); + failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", + peer_CN, conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\tcommon name \"%s\" does not match \"%s\"\n", + peer_CN, conn->host.dispname); + } + } + } + + /* General housekeeping */ + conn->ssl[sockindex].state = ssl_connection_complete; + conn->recv[sockindex] = axtls_recv; + conn->send[sockindex] = axtls_send; + + /* Put our freshly minted SSL session in cache */ + ssl_idsize = ssl_get_session_id_size(ssl); + ssl_sessionid = ssl_get_session_id(ssl); + if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) + != CURLE_OK) + infof (data, "failed to add session to cache\n"); + + return CURLE_OK; +} + +/* + * Use axTLS's non-blocking connection feature to open an SSL connection. + * This is called after a TCP connection is already established. + */ +CURL_STATIC CURLcode Curl_axtls_connect_nonblocking( + struct connectdata *conn, + int sockindex, + bool *done) +{ + CURLcode conn_step; + int ssl_fcn_return; + int i; + + *done = FALSE; + /* connectdata is calloc'd and connecting_state is only changed in this + function, so this is safe, as the state is effectively initialized. */ + if(conn->ssl[sockindex].connecting_state == ssl_connect_1) { + conn_step = connect_prep(conn, sockindex); + if(conn_step != CURLE_OK) { + Curl_axtls_close(conn, sockindex); + return conn_step; + } + conn->ssl[sockindex].connecting_state = ssl_connect_2; + } + + if(conn->ssl[sockindex].connecting_state == ssl_connect_2) { + /* Check to make sure handshake was ok. */ + if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) { + /* Loop to perform more work in between sleeps. This is work around the + fact that axtls does not expose any knowledge about when work needs + to be performed. This can save ~25% of time on SSL handshakes. */ + for(i=0; i<5; i++) { + ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL); + if(ssl_fcn_return < 0) { + Curl_axtls_close(conn, sockindex); + ssl_display_error(ssl_fcn_return); /* goes to stdout. */ + return map_error_to_curl(ssl_fcn_return); + } + return CURLE_OK; + } + } + infof (conn->data, "handshake completed successfully\n"); + conn->ssl[sockindex].connecting_state = ssl_connect_3; + } + + if(conn->ssl[sockindex].connecting_state == ssl_connect_3) { + conn_step = connect_finish(conn, sockindex); + if(conn_step != CURLE_OK) { + Curl_axtls_close(conn, sockindex); + return conn_step; + } + + /* Reset connect state */ + conn->ssl[sockindex].connecting_state = ssl_connect_1; + + *done = TRUE; + return CURLE_OK; + } + + /* Unrecognized state. Things are very bad. */ + conn->ssl[sockindex].state = ssl_connection_none; + conn->ssl[sockindex].connecting_state = ssl_connect_1; + /* Return value perhaps not strictly correct, but distinguishes the issue.*/ + return CURLE_BAD_FUNCTION_ARGUMENT; +} + + +/* + * This function is called after the TCP connect has completed. Setup the TLS + * layer and do all necessary magic for a blocking connect. + */ +CURL_STATIC CURLcode +Curl_axtls_connect(struct connectdata *conn, + int sockindex) + +{ + struct SessionHandle *data = conn->data; + CURLcode conn_step = connect_prep(conn, sockindex); + int ssl_fcn_return; + SSL *ssl = conn->ssl[sockindex].ssl; + long timeout_ms; + + if(conn_step != CURLE_OK) { + Curl_axtls_close(conn, sockindex); + return conn_step; + } + + /* Check to make sure handshake was ok. */ + while(ssl_handshake_status(ssl) != SSL_OK) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + ssl_fcn_return = ssl_read(ssl, NULL); + if(ssl_fcn_return < 0) { + Curl_axtls_close(conn, sockindex); + ssl_display_error(ssl_fcn_return); /* goes to stdout. */ + return map_error_to_curl(ssl_fcn_return); + } + /* TODO: avoid polling */ +#if !defined(_MSC_VER) + usleep(10000); +#else + Sleep(10); +#endif + } + infof (conn->data, "handshake completed successfully\n"); + + conn_step = connect_finish(conn, sockindex); + if(conn_step != CURLE_OK) { + Curl_axtls_close(conn, sockindex); + return conn_step; + } + + return CURLE_OK; +} + +/* return number of sent (non-SSL) bytes */ +static ssize_t axtls_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *err) +{ + /* ssl_write() returns 'int' while write() and send() returns 'size_t' */ + int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); + + infof(conn->data, " axtls_send\n"); + + if(rc < 0 ) { + *err = map_error_to_curl(rc); + rc = -1; /* generic error code for send failure */ + } + + *err = CURLE_OK; + return rc; +} + +CURL_STATIC void Curl_axtls_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + infof(conn->data, " Curl_axtls_close\n"); + + /* line from openssl.c: (void)SSL_shutdown(connssl->ssl); + axTLS compat layer does nothing for SSL_shutdown */ + + /* The following line is from openssl.c. There seems to be no axTLS + equivalent. ssl_free and ssl_ctx_free close things. + SSL_set_connect_state(connssl->handle); */ + + free_ssl_structs(connssl); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +CURL_STATIC int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) +{ + /* Outline taken from openssl.c since functions are in axTLS compat layer. + axTLS's error set is much smaller, so a lot of error-handling was removed. + */ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; + uint8_t *buf; + ssize_t nread; + + infof(conn->data, " Curl_axtls_shutdown\n"); + + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + (void)SSL_shutdown(connssl->ssl); + */ + + if(connssl->ssl) { + int what = Curl_socket_ready(conn->sock[sockindex], + CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); + if(what > 0) { + /* Something to read, let's do it and hope that it is the close + notify alert from the server. buf is managed internally by + axTLS and will be released upon calling ssl_free via + free_ssl_structs. */ + nread = (ssize_t)ssl_read(connssl->ssl, &buf); + + if(nread < SSL_OK) { + failf(data, "close notify alert not received during shutdown"); + retval = -1; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + } + + free_ssl_structs(connssl); + } + return retval; +} + +static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *err) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + ssize_t ret = 0; + uint8_t *read_buf; + + infof(conn->data, " axtls_recv\n"); + + *err = CURLE_OK; + if(connssl) { + ret = ssl_read(connssl->ssl, &read_buf); + if(ret > SSL_OK) { + /* ssl_read returns SSL_OK if there is more data to read, so if it is + larger, then all data has been read already. */ + memcpy(buf, read_buf, + (size_t)ret > buffersize ? buffersize : (size_t)ret); + } + else if(ret == SSL_OK) { + /* more data to be read, signal caller to call again */ + *err = CURLE_AGAIN; + ret = -1; + } + else if(ret == -3) { + /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS + team approves proposed fix. */ + Curl_axtls_close(conn, num); + } + else { + failf(conn->data, "axTLS recv error (%d)", ret); + *err = map_error_to_curl((int) ret); + ret = -1; + } + } + + return ret; +} + +/* + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +CURL_STATIC int Curl_axtls_check_cxn(struct connectdata *conn) +{ + /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1); + axTLS compat layer always returns the last argument, so connection is + always alive? */ + + infof(conn->data, " Curl_axtls_check_cxn\n"); + return 1; /* connection still in place */ +} + +CURL_STATIC void Curl_axtls_session_free(void *ptr) +{ + (void)ptr; + /* free the ID */ + /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL + compatibility layer does nothing, so we do nothing too. */ +} + +CURL_STATIC size_t Curl_axtls_version(char *buffer, size_t size) +{ + return snprintf(buffer, size, "axTLS/%s", ssl_version()); +} + +CURL_STATIC int Curl_axtls_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length) +{ + static bool ssl_seeded = FALSE; + (void)data; + if(!ssl_seeded) { + ssl_seeded = TRUE; + /* Initialize the seed if not already done. This call is not exactly thread + * safe (and neither is the ssl_seeded check), but the worst effect of a + * race condition is that some global resources will leak. */ + RNG_initialize(); + } + get_random((int)length, entropy); + return 0; +} + +#endif /* USE_AXTLS */ diff --git a/libcurl/src/lib/vtls/axtls.h b/libcurl/src/lib/vtls/axtls.h new file mode 100644 index 0000000..e794fd9 --- /dev/null +++ b/libcurl/src/lib/vtls/axtls.h @@ -0,0 +1,71 @@ +#ifndef HEADER_CURL_AXTLS_H +#define HEADER_CURL_AXTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, DirecTV, Contact: Eric Hu + * Copyright (C) 2010 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_AXTLS +#include "curl/curl.h" +#include "../urldata.h" + +CURL_STATIC int Curl_axtls_init(void); +CURL_STATIC int Curl_axtls_cleanup(void); +CURL_STATIC CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex); +CURL_STATIC CURLcode Curl_axtls_connect_nonblocking( + struct connectdata *conn, + int sockindex, + bool *done); + + /* close a SSL connection */ +CURL_STATIC void Curl_axtls_close(struct connectdata *conn, int sockindex); + +CURL_STATIC void Curl_axtls_session_free(void *ptr); +CURL_STATIC size_t Curl_axtls_version(char *buffer, size_t size); +CURL_STATIC int Curl_axtls_shutdown(struct connectdata *conn, int sockindex); +CURL_STATIC int Curl_axtls_check_cxn(struct connectdata *conn); +CURL_STATIC int Curl_axtls_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length); + +/* Set the API backend definition to axTLS */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS + +/* API setup for axTLS */ +#define curlssl_init Curl_axtls_init +#define curlssl_cleanup Curl_axtls_cleanup +#define curlssl_connect Curl_axtls_connect +#define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking +#define curlssl_session_free(x) Curl_axtls_session_free(x) +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_axtls_close +#define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y) +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_axtls_version +#define curlssl_check_cxn(x) Curl_axtls_check_cxn(x) +#define curlssl_data_pending(x,y) ((void)x, (void)y, 0) +#define curlssl_random(x,y,z) Curl_axtls_random(x,y,z) + +#endif /* USE_AXTLS */ +#endif /* HEADER_CURL_AXTLS_H */ + diff --git a/libcurl/src/lib/vtls/cyassl.c b/libcurl/src/lib/vtls/cyassl.c new file mode 100644 index 0000000..92ae083 --- /dev/null +++ b/libcurl/src/lib/vtls/cyassl.c @@ -0,0 +1,734 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "../curl_setup.h" + +#ifdef USE_CYASSL + +#define WOLFSSL_OPTIONS_IGNORE_SYS +/* CyaSSL's version.h, which should contain only the version, should come +before all other CyaSSL includes and be immediately followed by build config +aka options.h. http://curl.haxx.se/mail/lib-2015-04/0069.html */ +#include +#if defined(HAVE_CYASSL_OPTIONS_H) && (LIBCYASSL_VERSION_HEX > 0x03004008) +#if defined(CYASSL_API) || defined(WOLFSSL_API) +/* Safety measure. If either is defined some API include was already included +and that's a problem since options.h hasn't been included yet. */ +#error "CyaSSL API was included before the CyaSSL build options." +#endif +#include +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "cyassl.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "rawstr.h" +#include "curl_printf.h" + +#include +#ifdef HAVE_CYASSL_ERROR_SSL_H +#include +#else +#include +#endif +#include + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if LIBCYASSL_VERSION_HEX < 0x02007002 /* < 2.7.2 */ +#define CYASSL_MAX_ERROR_SZ 80 +#endif + +static Curl_recv cyassl_recv; +static Curl_send cyassl_send; + + +static int do_file_type(const char *type) +{ + if(!type || !type[0]) + return SSL_FILETYPE_PEM; + if(Curl_raw_equal(type, "PEM")) + return SSL_FILETYPE_PEM; + if(Curl_raw_equal(type, "DER")) + return SSL_FILETYPE_ASN1; + return -1; +} + +/* + * This function loads all the client/CA certificates and CRLs. Setup the TLS + * layer and do all necessary magic. + */ +static CURLcode +cyassl_connect_step1(struct connectdata *conn, + int sockindex) +{ + char error_buffer[CYASSL_MAX_ERROR_SZ]; + struct SessionHandle *data = conn->data; + struct ssl_connect_data* conssl = &conn->ssl[sockindex]; + SSL_METHOD* req_method = NULL; + void* ssl_sessionid = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; +#ifdef HAVE_SNI + bool sni = FALSE; +#define use_sni(x) sni = (x) +#else +#define use_sni(x) Curl_nop_stmt +#endif + + if(conssl->state == ssl_connection_complete) + return CURLE_OK; + + /* check to see if we've been told to use an explicit SSL/TLS version */ + switch(data->set.ssl.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: +#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ + /* minimum protocol version is set later after the CTX object is created */ + req_method = SSLv23_client_method(); +#else + infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, " + "TLS 1.0 is used exclusively\n"); + req_method = TLSv1_client_method(); +#endif + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_0: + req_method = TLSv1_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_1: + req_method = TLSv1_1_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_2: + req_method = TLSv1_2_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_SSLv3: + req_method = SSLv3_client_method(); + use_sni(FALSE); + break; + case CURL_SSLVERSION_SSLv2: + failf(data, "CyaSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(!req_method) { + failf(data, "SSL: couldn't create a method!"); + return CURLE_OUT_OF_MEMORY; + } + + if(conssl->ctx) + SSL_CTX_free(conssl->ctx); + conssl->ctx = SSL_CTX_new(req_method); + + if(!conssl->ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + + switch(data->set.ssl.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: +#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ + /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is whatever + minimum version of TLS was built in and at least TLS 1.0. For later library + versions that could change (eg TLS 1.0 built in but defaults to TLS 1.1) so + we have this short circuit evaluation to find the minimum supported TLS + version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion + because only the former will work before the user's CTX callback is called. + */ + if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) && + (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) && + (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) { + failf(data, "SSL: couldn't set the minimum protocol version"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + break; + } + +#ifndef NO_FILESYSTEM + /* load trusted cacert */ + if(data->set.str[STRING_SSL_CAFILE]) { + if(1 != SSL_CTX_load_verify_locations(conssl->ctx, + data->set.str[STRING_SSL_CAFILE], + data->set.str[STRING_SSL_CAPATH])) { + if(data->set.ssl.verifypeer) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + data->set.str[STRING_SSL_CAFILE]? + data->set.str[STRING_SSL_CAFILE]: "none", + data->set.str[STRING_SSL_CAPATH]? + data->set.str[STRING_SSL_CAPATH] : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate + verification is required. */ + infof(data, "error setting certificate verify locations," + " continuing anyway:\n"); + } + } + else { + /* Everything is fine. */ + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: + "none", + data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: + "none"); + } + + /* Load the client certificate, and private key */ + if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) { + int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]); + + if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT], + file_type) != 1) { + failf(data, "unable to use client certificate (no key or wrong pass" + " phrase?)"); + return CURLE_SSL_CONNECT_ERROR; + } + + file_type = do_file_type(data->set.str[STRING_KEY_TYPE]); + if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY], + file_type) != 1) { + failf(data, "unable to set private key"); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* !NO_FILESYSTEM */ + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ + SSL_CTX_set_verify(conssl->ctx, + data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, + NULL); + +#ifdef HAVE_SNI + if(sni) { + struct in_addr addr4; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + size_t hostname_len = strlen(conn->host.name); + if((hostname_len < USHRT_MAX) && + (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) && +#endif + (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name, + (unsigned short)hostname_len) != 1)) { + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + } + } +#endif + + /* give application a chance to interfere with SSL set up. */ + if(data->set.ssl.fsslctx) { + CURLcode result = CURLE_OK; + result = (*data->set.ssl.fsslctx)(data, conssl->ctx, + data->set.ssl.fsslctxp); + if(result) { + failf(data, "error signaled by ssl ctx callback"); + return result; + } + } +#ifdef NO_FILESYSTEM + else if(data->set.ssl.verifypeer) { + failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built" + " with \"no filesystem\". Either disable peer verification" + " (insecure) or if you are building an application with libcurl you" + " can load certificates via CURLOPT_SSL_CTX_FUNCTION."); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + + /* Let's make an SSL structure */ + if(conssl->handle) + SSL_free(conssl->handle); + conssl->handle = SSL_new(conssl->ctx); + if(!conssl->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + + /* Check if there's a cached ID we can/should use here! */ + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { + /* we got a session id, use it! */ + if(!SSL_set_session(conssl->handle, ssl_sessionid)) { + failf(data, "SSL: SSL_set_session failed: %s", + ERR_error_string(SSL_get_error(conssl->handle, 0), error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof (data, "SSL re-using session ID\n"); + } + + /* pass the raw socket into the SSL layer */ + if(!SSL_set_fd(conssl->handle, (int)sockfd)) { + failf(data, "SSL: SSL_set_fd failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + conssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + + +static CURLcode +cyassl_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret = -1; + struct SessionHandle *data = conn->data; + struct ssl_connect_data* conssl = &conn->ssl[sockindex]; + + conn->recv[sockindex] = cyassl_recv; + conn->send[sockindex] = cyassl_send; + + /* Enable RFC2818 checks */ + if(data->set.ssl.verifyhost) { + ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name); + if(ret == SSL_FAILURE) + return CURLE_OUT_OF_MEMORY; + } + + ret = SSL_connect(conssl->handle); + if(ret != 1) { + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int detail = SSL_get_error(conssl->handle, ret); + + if(SSL_ERROR_WANT_READ == detail) { + conssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else if(SSL_ERROR_WANT_WRITE == detail) { + conssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } + /* There is no easy way to override only the CN matching. + * This will enable the override of both mismatching SubjectAltNames + * as also mismatching CN fields */ + else if(DOMAIN_NAME_MISMATCH == detail) { +#if 1 + failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", + conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; +#else + /* When the CyaSSL_check_domain_name() is used and you desire to continue + * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0', + * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only + * way to do this is currently to switch the CyaSSL_check_domain_name() + * in and out based on the 'data->set.ssl.verifyhost' value. */ + if(data->set.ssl.verifyhost) { + failf(data, + "\tsubject alt name(s) or common name do not match \"%s\"\n", + conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, + "\tsubject alt name(s) and/or common name do not match \"%s\"\n", + conn->host.dispname); + return CURLE_OK; + } +#endif + } +#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ + else if(ASN_NO_SIGNER_E == detail) { + if(data->set.ssl.verifypeer) { + failf(data, "\tCA signer not available for verification\n"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate + verification is required. */ + infof(data, "CA signer not available for verification, " + "continuing anyway\n"); + } + } +#endif + else { + failf(data, "SSL_connect failed with error %d: %s", detail, + ERR_error_string(detail, error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + } + + conssl->connecting_state = ssl_connect_3; + infof(data, "SSL connected\n"); + + return CURLE_OK; +} + + +static CURLcode +cyassl_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode result = CURLE_OK; + void *old_ssl_sessionid=NULL; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + bool incache; + SSL_SESSION *our_ssl_sessionid; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + our_ssl_sessionid = SSL_get_session(connssl->handle); + + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, + 0 /* unknown size */); + if(result) { + failf(data, "failed to store ssl session"); + return result; + } + } + + connssl->connecting_state = ssl_connect_done; + + return result; +} + + +static ssize_t cyassl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen); + + if(rc < 0) { + int err = SSL_get_error(conn->ssl[sockindex].handle, rc); + + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_write() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, "SSL write: %s, errno %d", + ERR_error_string(err, error_buffer), + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + } + return rc; +} + +CURL_STATIC void Curl_cyassl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *conssl = &conn->ssl[sockindex]; + + if(conssl->handle) { + (void)SSL_shutdown(conssl->handle); + SSL_free (conssl->handle); + conssl->handle = NULL; + } + if(conssl->ctx) { + SSL_CTX_free (conssl->ctx); + conssl->ctx = NULL; + } +} + +static ssize_t cyassl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + int nread = SSL_read(conn->ssl[num].handle, buf, buffsize); + + if(nread < 0) { + int err = SSL_get_error(conn->ssl[num].handle, nread); + + switch(err) { + case SSL_ERROR_ZERO_RETURN: /* no more data */ + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, "SSL read: %s, errno %d", + ERR_error_string(err, error_buffer), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + return nread; +} + + +CURL_STATIC void Curl_cyassl_session_free(void *ptr) +{ + (void)ptr; + /* CyaSSL reuses sessions on own, no free */ +} + + +CURL_STATIC size_t Curl_cyassl_version(char *buffer, size_t size) +{ +#ifdef WOLFSSL_VERSION + return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); +#elif defined(CYASSL_VERSION) + return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION); +#else + return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8"); +#endif +} + + +CURL_STATIC int Curl_cyassl_init(void) +{ + return (CyaSSL_Init() == SSL_SUCCESS); +} + + +CURL_STATIC bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex) +{ + if(conn->ssl[connindex].handle) /* SSL is in use */ + return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE; + else + return FALSE; +} + + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +CURL_STATIC int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->handle) { + SSL_free (connssl->handle); + connssl->handle = NULL; + } + return retval; +} + + +static CURLcode +cyassl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1==connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = cyassl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = cyassl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = cyassl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = cyassl_recv; + conn->send[sockindex] = cyassl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + + +CURL_STATIC CURLcode +Curl_cyassl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return cyassl_connect_common(conn, sockindex, TRUE, done); +} + + +CURL_STATIC CURLcode +Curl_cyassl_connect(struct connectdata *conn, + int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = cyassl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +CURL_STATIC int Curl_cyassl_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length) +{ + RNG rng; + (void)data; + if(InitRng(&rng)) + return 1; + if(length > UINT_MAX) + return 1; + if(RNG_GenerateBlock(&rng, entropy, (unsigned)length)) + return 1; + return 0; +} + +#endif diff --git a/libcurl/src/lib/vtls/cyassl.h b/libcurl/src/lib/vtls/cyassl.h new file mode 100644 index 0000000..0cc54a5 --- /dev/null +++ b/libcurl/src/lib/vtls/cyassl.h @@ -0,0 +1,70 @@ +#ifndef HEADER_CURL_CYASSL_H +#define HEADER_CURL_CYASSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "../curl_setup.h" + +#ifdef USE_CYASSL + +CURL_STATIC CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex); +CURL_STATIC bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex); +CURL_STATIC int Curl_cyassl_shutdown(struct connectdata* conn, int sockindex); + + /* close a SSL connection */ +CURL_STATIC void Curl_cyassl_close(struct connectdata *conn, int sockindex); + +CURL_STATIC void Curl_cyassl_session_free(void *ptr); +CURL_STATIC size_t Curl_cyassl_version(char *buffer, size_t size); +CURL_STATIC int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex); +CURL_STATIC int Curl_cyassl_init(void); +CURL_STATIC CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +CURL_STATIC int Curl_cyassl_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length); + +/* Set the API backend definition to Schannel */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL + +/* this backend supports CURLOPT_SSL_CTX_* */ +#define have_curlssl_ssl_ctx 1 + +/* API setup for CyaSSL */ +#define curlssl_init Curl_cyassl_init +#define curlssl_cleanup() Curl_nop_stmt +#define curlssl_connect Curl_cyassl_connect +#define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking +#define curlssl_session_free(x) Curl_cyassl_session_free(x) +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_cyassl_close +#define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y) +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_cyassl_version +#define curlssl_check_cxn(x) ((void)x, -1) +#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y) +#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z) + +#endif /* USE_CYASSL */ +#endif /* HEADER_CURL_CYASSL_H */ diff --git a/libcurl/src/lib/vtls/darwinssl.c b/libcurl/src/lib/vtls/darwinssl.c new file mode 100644 index 0000000..11f107f --- /dev/null +++ b/libcurl/src/lib/vtls/darwinssl.c @@ -0,0 +1,2484 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all iOS and Mac OS X SecureTransport-specific code for the + * TLS/SSL layer. No code but vtls.c should ever call or use these functions. + */ + +#include "../curl_setup.h" + +#include "../urldata.h" /* for the SessionHandle definition */ +#include "../curl_base64.h" +#include "../strtok.h" + +#ifdef USE_DARWINSSL + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include +#include +#include +#include + +/* The Security framework has changed greatly between iOS and different OS X + versions, and we will try to support as many of them as we can (back to + Leopard and iOS 5) by using macros and weak-linking. + + IMPORTANT: If TLS 1.1 and 1.2 support are important for you on OS X, then + you must build this project against the 10.8 SDK or later. */ +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 +#error "The darwinssl back-end requires Leopard or later." +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ + +#define CURL_BUILD_IOS 0 +#define CURL_BUILD_IOS_7 0 +#define CURL_BUILD_MAC 1 +/* This is the maximum API level we are allowed to use when building: */ +#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 +#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 +#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 +/* These macros mean "the following code is present to allow runtime backward + compatibility with at least this cat or earlier": + (You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET + environmental variable.) */ +#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050 +#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060 +#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 +#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 +#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090 + +#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE +#define CURL_BUILD_IOS 1 +#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +#define CURL_BUILD_MAC 0 +#define CURL_BUILD_MAC_10_5 0 +#define CURL_BUILD_MAC_10_6 0 +#define CURL_BUILD_MAC_10_7 0 +#define CURL_BUILD_MAC_10_8 0 +#define CURL_SUPPORT_MAC_10_5 0 +#define CURL_SUPPORT_MAC_10_6 0 +#define CURL_SUPPORT_MAC_10_7 0 +#define CURL_SUPPORT_MAC_10_8 0 +#define CURL_SUPPORT_MAC_10_9 0 + +#else +#error "The darwinssl back-end requires iOS or OS X." +#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ + +#if CURL_BUILD_MAC +#include +#endif /* CURL_BUILD_MAC */ + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "connect.h" +#include "select.h" +#include "vtls.h" +#include "darwinssl.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* From MacTypes.h (which we can't include because it isn't present in iOS: */ +#define ioErr -36 +#define paramErr -50 + +/* The following two functions were ripped from Apple sample code, + * with some modifications: */ +static OSStatus SocketRead(SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesToGo = *dataLength; + size_t initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = connssl->ssl_sockfd; + OSStatus rtn = noErr; + size_t bytesRead; + ssize_t rrtn; + int theErr; + + *dataLength = 0; + + for(;;) { + bytesRead = 0; + rrtn = read(sock, currData, bytesToGo); + if(rrtn <= 0) { + /* this is guesswork... */ + theErr = errno; + if(rrtn == 0) { /* EOF = server hung up */ + /* the framework will turn this into errSSLClosedNoNotify */ + rtn = errSSLClosedGraceful; + } + else /* do the switch */ + switch(theErr) { + case ENOENT: + /* connection closed */ + rtn = errSSLClosedGraceful; + break; + case ECONNRESET: + rtn = errSSLClosedAbort; + break; + case EAGAIN: + rtn = errSSLWouldBlock; + connssl->ssl_direction = false; + break; + default: + rtn = ioErr; + break; + } + break; + } + else { + bytesRead = rrtn; + } + bytesToGo -= bytesRead; + currData += bytesRead; + + if(bytesToGo == 0) { + /* filled buffer with incoming data, done */ + break; + } + } + *dataLength = initLen - bytesToGo; + + return rtn; +} + +static OSStatus SocketWrite(SSLConnectionRef connection, + const void *data, + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesSent = 0; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = connssl->ssl_sockfd; + ssize_t length; + size_t dataLen = *dataLength; + const UInt8 *dataPtr = (UInt8 *)data; + OSStatus ortn; + int theErr; + + *dataLength = 0; + + do { + length = write(sock, + (char*)dataPtr + bytesSent, + dataLen - bytesSent); + } while((length > 0) && + ( (bytesSent += length) < dataLen) ); + + if(length <= 0) { + theErr = errno; + if(theErr == EAGAIN) { + ortn = errSSLWouldBlock; + connssl->ssl_direction = true; + } + else { + ortn = ioErr; + } + } + else { + ortn = noErr; + } + *dataLength = bytesSent; + return ortn; +} + +CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) { + switch (cipher) { + /* SSL version 3.0 */ + case SSL_RSA_WITH_NULL_MD5: + return "SSL_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "SSL_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "SSL_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "SSL_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_SHA: + return "SSL_RSA_WITH_IDEA_CBC_SHA"; + break; + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_RSA_WITH_DES_CBC_SHA: + return "SSL_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_DES_CBC_SHA: + return "SSL_DH_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_DES_CBC_SHA: + return "SSL_DH_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "SSL_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_anon_WITH_DES_CBC_SHA: + return "SSL_DH_anon_WITH_DES_CBC_SHA"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; + break; + /* TLS 1.0 with AES (RFC 3268) + (Apparently these are used in SSLv3 implementations as well.) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; + /* SSL version 2.0 */ + case SSL_RSA_WITH_RC2_CBC_MD5: + return "SSL_RSA_WITH_RC2_CBC_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_MD5: + return "SSL_RSA_WITH_IDEA_CBC_MD5"; + break; + case SSL_RSA_WITH_DES_CBC_MD5: + return "SSL_RSA_WITH_DES_CBC_MD5"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_MD5: + return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; + break; + } + return "SSL_NULL_WITH_NULL_NULL"; +} + +CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { + switch(cipher) { + /* TLS 1.0 with AES (RFC 3268) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* TLS 1.0 with ECDSA (RFC 4492) */ + case TLS_ECDH_ECDSA_WITH_NULL_SHA: + return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_NULL_SHA: + return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_NULL_SHA: + return "TLS_ECDH_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_NULL_SHA: + return "TLS_ECDHE_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_NULL_SHA: + return "TLS_ECDH_anon_WITH_NULL_SHA"; + break; + case TLS_ECDH_anon_WITH_RC4_128_SHA: + return "TLS_ECDH_anon_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* TLS 1.2 (RFC 5246) */ + case TLS_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case TLS_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case TLS_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case TLS_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_WITH_NULL_SHA256: + return "TLS_RSA_WITH_NULL_SHA256"; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; + break; + /* TLS 1.2 with AES GCM (RFC 5288) */ + case TLS_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_anon_WITH_AES_128_GCM_SHA256: + return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: + return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; + break; + /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: + return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; + break; +#else + case SSL_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* TLS PSK (RFC 4279): */ + case TLS_PSK_WITH_RC4_128_SHA: + return "TLS_PSK_WITH_RC4_128_SHA"; + break; + case TLS_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA: + return "TLS_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA: + return "TLS_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_RC4_128_SHA: + return "TLS_DHE_PSK_WITH_RC4_128_SHA"; + break; + case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_RC4_128_SHA: + return "TLS_RSA_PSK_WITH_RC4_128_SHA"; + break; + case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; + break; + /* More TLS PSK (RFC 4785): */ + case TLS_PSK_WITH_NULL_SHA: + return "TLS_PSK_WITH_NULL_SHA"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA: + return "TLS_DHE_PSK_WITH_NULL_SHA"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA: + return "TLS_RSA_PSK_WITH_NULL_SHA"; + break; + /* Even more TLS PSK (RFC 5487): */ + case TLS_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_PSK_WITH_NULL_SHA256: + return "TLS_PSK_WITH_NULL_SHA256"; + break; + case TLS_PSK_WITH_NULL_SHA384: + return "TLS_PSK_WITH_NULL_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA256: + return "TLS_DHE_PSK_WITH_NULL_SHA256"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA256: + return "TLS_RSA_PSK_WITH_NULL_SHA256"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + } + return "TLS_NULL_WITH_NULL_NULL"; +} + +#if CURL_BUILD_MAC +CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) +{ + int mib[2]; + char *os_version; + size_t os_version_len; + char *os_version_major, *os_version_minor/*, *os_version_point*/; + char *tok_buf; + + /* Get the Darwin kernel version from the kernel using sysctl(): */ + mib[0] = CTL_KERN; + mib[1] = KERN_OSRELEASE; + if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1) + return; + os_version = malloc(os_version_len*sizeof(char)); + if(!os_version) + return; + if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) { + free(os_version); + return; + } + + /* Parse the version: */ + os_version_major = strtok_r(os_version, ".", &tok_buf); + os_version_minor = strtok_r(NULL, ".", &tok_buf); + /*os_version_point = strtok_r(NULL, ".", &tok_buf);*/ + *major = atoi(os_version_major); + *minor = atoi(os_version_minor); + free(os_version); +} +#endif /* CURL_BUILD_MAC */ + +/* Apple provides a myriad of ways of getting information about a certificate + into a string. Some aren't available under iOS or newer cats. So here's + a unified function for getting a string describing the certificate that + ought to work in all cats starting with Leopard. */ +CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert) +{ + CFStringRef server_cert_summary = CFSTR("(null)"); + +#if CURL_BUILD_IOS + /* iOS: There's only one way to do this. */ + server_cert_summary = SecCertificateCopySubjectSummary(cert); +#else +#if CURL_BUILD_MAC_10_7 + /* Lion & later: Get the long description if we can. */ + if(SecCertificateCopyLongDescription != NULL) + server_cert_summary = + SecCertificateCopyLongDescription(NULL, cert, NULL); + else +#endif /* CURL_BUILD_MAC_10_7 */ +#if CURL_BUILD_MAC_10_6 + /* Snow Leopard: Get the certificate summary. */ + if(SecCertificateCopySubjectSummary != NULL) + server_cert_summary = SecCertificateCopySubjectSummary(cert); + else +#endif /* CURL_BUILD_MAC_10_6 */ + /* Leopard is as far back as we go... */ + (void)SecCertificateCopyCommonName(cert, &server_cert_summary); +#endif /* CURL_BUILD_IOS */ + return server_cert_summary; +} + +#if CURL_SUPPORT_MAC_10_6 +/* The SecKeychainSearch API was deprecated in Lion, and using it will raise + deprecation warnings, so let's not compile this unless it's necessary: */ +static OSStatus CopyIdentityWithLabelOldSchool(char *label, + SecIdentityRef *out_c_a_k) +{ + OSStatus status = errSecItemNotFound; + SecKeychainAttributeList attr_list; + SecKeychainAttribute attr; + SecKeychainSearchRef search = NULL; + SecCertificateRef cert = NULL; + + /* Set up the attribute list: */ + attr_list.count = 1L; + attr_list.attr = &attr; + + /* Set up our lone search criterion: */ + attr.tag = kSecLabelItemAttr; + attr.data = label; + attr.length = (UInt32)strlen(label); + + /* Start searching: */ + status = SecKeychainSearchCreateFromAttributes(NULL, + kSecCertificateItemClass, + &attr_list, + &search); + if(status == noErr) { + status = SecKeychainSearchCopyNext(search, + (SecKeychainItemRef *)&cert); + if(status == noErr && cert) { + /* If we found a certificate, does it have a private key? */ + status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k); + CFRelease(cert); + } + } + + if(search) + CFRelease(search); + return status; +} +#endif /* CURL_SUPPORT_MAC_10_6 */ + +static OSStatus CopyIdentityWithLabel(char *label, + SecIdentityRef *out_cert_and_key) +{ + OSStatus status = errSecItemNotFound; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS + /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. + kSecClassIdentity was introduced in Lion. If both exist, let's use them + to find the certificate. */ + if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { + CFTypeRef keys[4]; + CFTypeRef values[4]; + CFDictionaryRef query_dict; + CFStringRef label_cf = CFStringCreateWithCString(NULL, label, + kCFStringEncodingUTF8); + + /* Set up our search criteria and expected results: */ + values[0] = kSecClassIdentity; /* we want a certificate and a key */ + keys[0] = kSecClass; + values[1] = kCFBooleanTrue; /* we want a reference */ + keys[1] = kSecReturnRef; + values[2] = kSecMatchLimitOne; /* one is enough, thanks */ + keys[2] = kSecMatchLimit; + /* identity searches need a SecPolicyRef in order to work */ + values[3] = SecPolicyCreateSSL(false, label_cf); + keys[3] = kSecMatchPolicy; + query_dict = CFDictionaryCreate(NULL, (const void **)keys, + (const void **)values, 4L, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease(values[3]); + CFRelease(label_cf); + + /* Do we have a match? */ + status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key); + CFRelease(query_dict); + } + else { +#if CURL_SUPPORT_MAC_10_6 + /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */ + status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key); +#endif /* CURL_SUPPORT_MAC_10_7 */ + } +#elif CURL_SUPPORT_MAC_10_6 + /* For developers building on older cats, we have no choice but to fall back + to SecKeychainSearch. */ + status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key); +#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ + return status; +} + +static OSStatus CopyIdentityFromPKCS12File(const char *cPath, + const char *cPassword, + SecIdentityRef *out_cert_and_key) +{ + OSStatus status = errSecItemNotFound; + CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL, + (const UInt8 *)cPath, strlen(cPath), false); + CFStringRef password = cPassword ? CFStringCreateWithCString(NULL, + cPassword, kCFStringEncodingUTF8) : NULL; + CFDataRef pkcs_data = NULL; + + /* We can import P12 files on iOS or OS X 10.7 or later: */ + /* These constants are documented as having first appeared in 10.6 but they + raise linker errors when used on that cat for some reason. */ +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS + if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data, + NULL, NULL, &status)) { + const void *cKeys[] = {kSecImportExportPassphrase}; + const void *cValues[] = {password}; + CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues, + password ? 1L : 0L, NULL, NULL); + CFArrayRef items = NULL; + + /* Here we go: */ + status = SecPKCS12Import(pkcs_data, options, &items); + if(status == noErr && items && CFArrayGetCount(items)) { + CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L); + const void *temp_identity = CFDictionaryGetValue(identity_and_trust, + kSecImportItemIdentity); + + /* Retain the identity; we don't care about any other data... */ + CFRetain(temp_identity); + *out_cert_and_key = (SecIdentityRef)temp_identity; + } + + if(items) + CFRelease(items); + CFRelease(options); + CFRelease(pkcs_data); + } +#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ + if(password) + CFRelease(password); + CFRelease(pkcs_url); + return status; +} + +/* This code was borrowed from nss.c, with some modifications: + * Determine whether the nickname passed in is a filename that needs to + * be loaded as a PEM or a regular NSS nickname. + * + * returns 1 for a file + * returns 0 for not a file + */ +CF_INLINE bool is_file(const char *filename) +{ + struct_stat st; + + if(filename == NULL) + return false; + + if(stat(filename, &st) == 0) + return S_ISREG(st.st_mode); + return false; +} + +static CURLcode darwinssl_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct SessionHandle *data = conn->data; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif /* ENABLE_IPV6 */ + size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; + SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + char *ssl_sessionid; + size_t ssl_sessionid_len; + OSStatus err = noErr; +#if CURL_BUILD_MAC + int darwinver_maj = 0, darwinver_min = 0; + + GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); +#endif /* CURL_BUILD_MAC */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) { /* use the newer API if avaialble */ + if(connssl->ssl_ctx) + CFRelease(connssl->ssl_ctx); + connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); + if(!connssl->ssl_ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + } + else { + /* The old ST API does not exist under iOS, so don't compile it: */ +#if CURL_SUPPORT_MAC_10_8 + if(connssl->ssl_ctx) + (void)SSLDisposeContext(connssl->ssl_ctx); + err = SSLNewContext(false, &(connssl->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(connssl->ssl_ctx) + (void)SSLDisposeContext(connssl->ssl_ctx); + err = SSLNewContext(false, &(connssl->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */ + + /* check to see if we've been told to use an explicit SSL/TLS version */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + switch(data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); + break; + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1); + break; + case CURL_SSLVERSION_TLSv1_1: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11); + break; + case CURL_SSLVERSION_TLSv1_2: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocolAll, + false); + switch (data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol11, + true); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol11, + true); + break; + case CURL_SSLVERSION_TLSv1_2: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); + switch(data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + failf(data, "Your version of the OS does not support TLSv1.1"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_2: + failf(data, "Your version of the OS does not support TLSv1.2"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + + if(data->set.str[STRING_KEY]) { + infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " + "Transport. The private key must be in the Keychain.\n"); + } + + if(data->set.str[STRING_CERT]) { + SecIdentityRef cert_and_key = NULL; + bool is_cert_file = is_file(data->set.str[STRING_CERT]); + + /* User wants to authenticate with a client cert. Look for it: + If we detect that this is a file on disk, then let's load it. + Otherwise, assume that the user wants to use an identity loaded + from the Keychain. */ + if(is_cert_file) { + if(!data->set.str[STRING_CERT_TYPE]) + infof(data, "WARNING: SSL: Certificate type not set, assuming " + "PKCS#12 format.\n"); + else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12", + strlen(data->set.str[STRING_CERT_TYPE])) != 0) + infof(data, "WARNING: SSL: The Security framework only supports " + "loading identities that are in PKCS#12 format.\n"); + + err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT], + data->set.str[STRING_KEY_PASSWD], &cert_and_key); + } + else + err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key); + + if(err == noErr) { + SecCertificateRef cert = NULL; + CFTypeRef certs_c[1]; + CFArrayRef certs; + + /* If we found one, print it out: */ + err = SecIdentityCopyCertificate(cert_and_key, &cert); + if(err == noErr) { + CFStringRef cert_summary = CopyCertSubject(cert); + char cert_summary_c[128]; + + if(cert_summary) { + memset(cert_summary_c, 0, 128); + if(CFStringGetCString(cert_summary, + cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Client certificate: %s\n", cert_summary_c); + } + CFRelease(cert_summary); + CFRelease(cert); + } + } + certs_c[0] = cert_and_key; + certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, + &kCFTypeArrayCallBacks); + err = SSLSetCertificate(connssl->ssl_ctx, certs); + if(certs) + CFRelease(certs); + if(err != noErr) { + failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err); + return CURLE_SSL_CERTPROBLEM; + } + CFRelease(cert_and_key); + } + else { + switch(err) { + case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ + failf(data, "SSL: Incorrect password for the certificate \"%s\" " + "and its private key.", data->set.str[STRING_CERT]); + break; + case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ + failf(data, "SSL: Couldn't make sense of the data in the " + "certificate \"%s\" and its private key.", + data->set.str[STRING_CERT]); + break; + case -25260: /* errSecPassphraseRequired */ + failf(data, "SSL The certificate \"%s\" requires a password.", + data->set.str[STRING_CERT]); + break; + case errSecItemNotFound: + failf(data, "SSL: Can't find the certificate \"%s\" and its private " + "key in the Keychain.", data->set.str[STRING_CERT]); + break; + default: + failf(data, "SSL: Can't load the certificate \"%s\" and its private " + "key: OSStatus %d", data->set.str[STRING_CERT], err); + break; + } + return CURLE_SSL_CERTPROBLEM; + } + } + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* Snow Leopard introduced the SSLSetSessionOption() function, but due to + a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag + works, it doesn't work as expected under Snow Leopard or Lion. + So we need to call SSLSetEnableCertVerify() on those older cats in order + to disable certificate validation if the user turned that off. + (SecureTransport will always validate the certificate chain by + default.) */ + /* (Note: Darwin 12.x.x is Mountain Lion.) */ +#if CURL_BUILD_MAC + if(SSLSetSessionOption != NULL && darwinver_maj >= 12) { +#else + if(SSLSetSessionOption != NULL) { +#endif /* CURL_BUILD_MAC */ + bool break_on_auth = !data->set.ssl.verifypeer || + data->set.str[STRING_SSL_CAFILE]; + err = SSLSetSessionOption(connssl->ssl_ctx, + kSSLSessionOptionBreakOnServerAuth, + break_on_auth); + if(err != noErr) { + failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLSetEnableCertVerify(connssl->ssl_ctx, + data->set.ssl.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + err = SSLSetEnableCertVerify(connssl->ssl_ctx, + data->set.ssl.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ + + if(data->set.str[STRING_SSL_CAFILE]) { + bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]); + + if(!is_cert_file) { + failf(data, "SSL: can't load CA certificate file %s", + data->set.str[STRING_SSL_CAFILE]); + return CURLE_SSL_CACERT_BADFILE; + } + if(!data->set.ssl.verifypeer) { + failf(data, "SSL: CA certificate set, but certificate verification " + "is disabled"); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* Configure hostname check. SNI is used if available. + * Both hostname check and SNI require SSLSetPeerDomainName(). + * Also: the verifyhost setting influences SNI usage */ + if(data->set.ssl.verifyhost) { + err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name, + strlen(conn->host.name)); + + if(err != noErr) { + infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", + err); + } + + if((Curl_inet_pton(AF_INET, conn->host.name, &addr)) + #ifdef ENABLE_IPV6 + || (Curl_inet_pton(AF_INET6, conn->host.name, &addr)) + #endif + ) { + infof(data, "WARNING: using IP address, SNI is being disabled by " + "the OS.\n"); + } + } + + /* Disable cipher suites that ST supports but are not safe. These ciphers + are unlikely to be used in any case since ST gives other ciphers a much + higher priority, but it's probably better that we not connect at all than + to give the user a false sense of security if the server only supports + insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ + (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count); + all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(all_ciphers && allowed_ciphers && + SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers, + &all_ciphers_count) == noErr) { + for(i = 0UL ; i < all_ciphers_count ; i++) { +#if CURL_BUILD_MAC + /* There's a known bug in early versions of Mountain Lion where ST's ECC + ciphers (cipher suite 0xC001 through 0xC032) simply do not work. + Work around the problem here by disabling those ciphers if we are + running in an affected version of OS X. */ + if(darwinver_maj == 12 && darwinver_min <= 3 && + all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { + continue; + } +#endif /* CURL_BUILD_MAC */ + switch(all_ciphers[i]) { + /* Disable NULL ciphersuites: */ + case SSL_NULL_WITH_NULL_NULL: + case SSL_RSA_WITH_NULL_MD5: + case SSL_RSA_WITH_NULL_SHA: + case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ + case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ + case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ + case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ + case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ + case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ + case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ + case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ + case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ + case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ + case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ + case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ + case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ + /* Disable anonymous ciphersuites: */ + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + case SSL_DH_anon_WITH_RC4_128_MD5: + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_anon_WITH_DES_CBC_SHA: + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ + case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ + case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ + case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ + case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ + case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ + case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ + case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ + case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ + /* Disable weak key ciphersuites: */ + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_RSA_WITH_DES_CBC_SHA: + case SSL_DH_DSS_WITH_DES_CBC_SHA: + case SSL_DH_RSA_WITH_DES_CBC_SHA: + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + /* Disable IDEA: */ + case SSL_RSA_WITH_IDEA_CBC_SHA: + case SSL_RSA_WITH_IDEA_CBC_MD5: + break; + default: /* enable everything else */ + allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; + break; + } + } + err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers, + allowed_ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + failf(data, "SSL: Failed to allocate memory for allowed ciphers"); + return CURLE_OUT_OF_MEMORY; + } + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* We want to enable 1/n-1 when using a CBC cipher unless the user + specifically doesn't want us doing that: */ + if(SSLSetSessionOption != NULL) { + SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord, + !data->set.ssl_enable_beast); + SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart, + data->set.ssl.falsestart); /* false start support */ + } +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* Check if there's a cached ID we can/should use here! */ + if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, + &ssl_sessionid_len)) { + /* we got a session id, use it! */ + err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + if(err != noErr) { + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + /* If there isn't one, then let's make one up! This has to be done prior + to starting the handshake. */ + else { + CURLcode result; + ssl_sessionid = + aprintf("%s:%d:%d:%s:%hu", data->set.str[STRING_SSL_CAFILE], + data->set.ssl.verifypeer, data->set.ssl.verifyhost, + conn->host.name, conn->remote_port); + ssl_sessionid_len = strlen(ssl_sessionid); + + err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + if(err != noErr) { + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len); + if(result) { + failf(data, "failed to store ssl session"); + return result; + } + } + + err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite); + if(err != noErr) { + failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + /* pass the raw socket into the SSL layers */ + /* We need to store the FD in a constant memory address, because + * SSLSetConnection() will not copy that address. I've found that + * conn->sock[sockindex] may change on its own. */ + connssl->ssl_sockfd = sockfd; + err = SSLSetConnection(connssl->ssl_ctx, connssl); + if(err != noErr) { + failf(data, "SSL: SSLSetConnection() failed: %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) +{ + char *sep_start, *sep_end, *cert_start, *cert_end; + size_t i, j, err; + size_t len; + unsigned char *b64; + + /* Jump through the separators at the beginning of the certificate. */ + sep_start = strstr(in, "-----"); + if(sep_start == NULL) + return 0; + cert_start = strstr(sep_start + 1, "-----"); + if(cert_start == NULL) + return -1; + + cert_start += 5; + + /* Find separator after the end of the certificate. */ + cert_end = strstr(cert_start, "-----"); + if(cert_end == NULL) + return -1; + + sep_end = strstr(cert_end + 1, "-----"); + if(sep_end == NULL) + return -1; + sep_end += 5; + + len = cert_end - cert_start; + b64 = malloc(len + 1); + if(!b64) + return -1; + + /* Create base64 string without linefeeds. */ + for(i = 0, j = 0; i < len; i++) { + if(cert_start[i] != '\r' && cert_start[i] != '\n') + b64[j++] = cert_start[i]; + } + b64[j] = '\0'; + + err = Curl_base64_decode((const char *)b64, out, outlen); + free(b64); + if(err) { + free(*out); + return -1; + } + + return sep_end - in; +} + +static int read_cert(const char *file, unsigned char **out, size_t *outlen) +{ + int fd; + ssize_t n, len = 0, cap = 512; + unsigned char buf[cap], *data; + + fd = open(file, 0); + if(fd < 0) + return -1; + + data = malloc(cap); + if(!data) { + close(fd); + return -1; + } + + for(;;) { + n = read(fd, buf, sizeof(buf)); + if(n < 0) { + close(fd); + free(data); + return -1; + } + else if(n == 0) { + close(fd); + break; + } + + if(len + n >= cap) { + cap *= 2; + data = realloc(data, cap); + if(!data) { + close(fd); + return -1; + } + } + + memcpy(data + len, buf, n); + len += n; + } + data[len] = '\0'; + + *out = data; + *outlen = len; + + return 0; +} + +static int sslerr_to_curlerr(struct SessionHandle *data, int err) +{ + switch(err) { + case errSSLXCertChainInvalid: + failf(data, "SSL certificate problem: Invalid certificate chain"); + return CURLE_SSL_CACERT; + case errSSLUnknownRootCert: + failf(data, "SSL certificate problem: Untrusted root certificate"); + return CURLE_SSL_CACERT; + case errSSLNoRootCert: + failf(data, "SSL certificate problem: No root certificate"); + return CURLE_SSL_CACERT; + case errSSLCertExpired: + failf(data, "SSL certificate problem: Certificate chain had an " + "expired certificate"); + return CURLE_SSL_CACERT; + case errSSLBadCert: + failf(data, "SSL certificate problem: Couldn't understand the server " + "certificate format"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLHostNameMismatch: + failf(data, "SSL certificate peer hostname mismatch"); + return CURLE_PEER_FAILED_VERIFICATION; + default: + failf(data, "SSL unexpected certificate error %d", err); + return CURLE_SSL_CACERT; + } +} + +static int append_cert_to_array(struct SessionHandle *data, + unsigned char *buf, size_t buflen, + CFMutableArrayRef array) +{ + CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); + if(!certdata) { + failf(data, "SSL: failed to allocate array for CA certificate"); + return CURLE_OUT_OF_MEMORY; + } + + SecCertificateRef cacert = + SecCertificateCreateWithData(kCFAllocatorDefault, certdata); + CFRelease(certdata); + if(!cacert) { + failf(data, "SSL: failed to create SecCertificate from CA certificate"); + return CURLE_SSL_CACERT; + } + + /* Check if cacert is valid. */ + CFStringRef subject = CopyCertSubject(cacert); + if(subject) { + char subject_cbuf[128]; + memset(subject_cbuf, 0, 128); + if(!CFStringGetCString(subject, + subject_cbuf, + 128, + kCFStringEncodingUTF8)) { + CFRelease(cacert); + failf(data, "SSL: invalid CA certificate subject"); + return CURLE_SSL_CACERT; + } + CFRelease(subject); + } + else { + CFRelease(cacert); + failf(data, "SSL: invalid CA certificate"); + return CURLE_SSL_CACERT; + } + + CFArrayAppendValue(array, cacert); + CFRelease(cacert); + + return CURLE_OK; +} + +static int verify_cert(const char *cafile, struct SessionHandle *data, + SSLContextRef ctx) +{ + int n = 0, rc; + long res; + unsigned char *certbuf, *der; + size_t buflen, derlen, offset = 0; + + if(read_cert(cafile, &certbuf, &buflen) < 0) { + failf(data, "SSL: failed to read or invalid CA certificate"); + return CURLE_SSL_CACERT; + } + + /* + * Certbuf now contains the contents of the certificate file, which can be + * - a single DER certificate, + * - a single PEM certificate or + * - a bunch of PEM certificates (certificate bundle). + * + * Go through certbuf, and convert any PEM certificate in it into DER + * format. + */ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + if(array == NULL) { + free(certbuf); + failf(data, "SSL: out of memory creating CA certificate array"); + return CURLE_OUT_OF_MEMORY; + } + + while(offset < buflen) { + n++; + + /* + * Check if the certificate is in PEM format, and convert it to DER. If + * this fails, we assume the certificate is in DER format. + */ + res = pem_to_der((const char *)certbuf + offset, &der, &derlen); + if(res < 0) { + free(certbuf); + CFRelease(array); + failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle", + n, offset); + return CURLE_SSL_CACERT; + } + offset += res; + + if(res == 0 && offset == 0) { + /* This is not a PEM file, probably a certificate in DER format. */ + rc = append_cert_to_array(data, certbuf, buflen, array); + free(certbuf); + if(rc != CURLE_OK) { + CFRelease(array); + return rc; + } + break; + } + else if(res == 0) { + /* No more certificates in the bundle. */ + free(certbuf); + break; + } + + rc = append_cert_to_array(data, der, derlen, array); + free(der); + if(rc != CURLE_OK) { + free(certbuf); + CFRelease(array); + return rc; + } + } + + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(trust == NULL) { + failf(data, "SSL: error getting certificate chain"); + CFRelease(array); + return CURLE_OUT_OF_MEMORY; + } + else if(ret != noErr) { + CFRelease(array); + return sslerr_to_curlerr(data, ret); + } + + ret = SecTrustSetAnchorCertificates(trust, array); + if(ret != noErr) { + CFRelease(trust); + return sslerr_to_curlerr(data, ret); + } + ret = SecTrustSetAnchorCertificatesOnly(trust, true); + if(ret != noErr) { + CFRelease(trust); + return sslerr_to_curlerr(data, ret); + } + + SecTrustResultType trust_eval = 0; + ret = SecTrustEvaluate(trust, &trust_eval); + CFRelease(array); + CFRelease(trust); + if(ret != noErr) { + return sslerr_to_curlerr(data, ret); + } + + switch (trust_eval) { + case kSecTrustResultUnspecified: + case kSecTrustResultProceed: + return CURLE_OK; + + case kSecTrustResultRecoverableTrustFailure: + case kSecTrustResultDeny: + default: + failf(data, "SSL: certificate verification failed (result: %d)", + trust_eval); + return CURLE_PEER_FAILED_VERIFICATION; + } +} + +static CURLcode +darwinssl_connect_step2(struct connectdata *conn, int sockindex) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + OSStatus err; + SSLCipherSuite cipher; + SSLProtocol protocol = 0; + + DEBUGASSERT(ssl_connect_2 == connssl->connecting_state + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); + + /* Here goes nothing: */ + err = SSLHandshake(connssl->ssl_ctx); + + if(err != noErr) { + switch (err) { + case errSSLWouldBlock: /* they're not done with us yet */ + connssl->connecting_state = connssl->ssl_direction ? + ssl_connect_2_writing : ssl_connect_2_reading; + return CURLE_OK; + + /* The below is errSSLServerAuthCompleted; it's not defined in + Leopard's headers */ + case -9841: + if(data->set.str[STRING_SSL_CAFILE]) { + int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data, + connssl->ssl_ctx); + if(res != CURLE_OK) + return res; + } + /* the documentation says we need to call SSLHandshake() again */ + return darwinssl_connect_step2(conn, sockindex); + + /* These are all certificate problems with the server: */ + case errSSLXCertChainInvalid: + failf(data, "SSL certificate problem: Invalid certificate chain"); + return CURLE_SSL_CACERT; + case errSSLUnknownRootCert: + failf(data, "SSL certificate problem: Untrusted root certificate"); + return CURLE_SSL_CACERT; + case errSSLNoRootCert: + failf(data, "SSL certificate problem: No root certificate"); + return CURLE_SSL_CACERT; + case errSSLCertExpired: + failf(data, "SSL certificate problem: Certificate chain had an " + "expired certificate"); + return CURLE_SSL_CACERT; + case errSSLBadCert: + failf(data, "SSL certificate problem: Couldn't understand the server " + "certificate format"); + return CURLE_SSL_CONNECT_ERROR; + + /* These are all certificate problems with the client: */ + case errSecAuthFailed: + failf(data, "SSL authentication failed"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLPeerHandshakeFail: + failf(data, "SSL peer handshake failed, the server most likely " + "requires a client certificate to connect"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLPeerUnknownCA: + failf(data, "SSL server rejected the client certificate due to " + "the certificate being signed by an unknown certificate " + "authority"); + return CURLE_SSL_CONNECT_ERROR; + + /* This error is raised if the server's cert didn't match the server's + host name: */ + case errSSLHostNameMismatch: + failf(data, "SSL certificate peer verification failed, the " + "certificate did not match \"%s\"\n", conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + + /* Generic handshake errors: */ + case errSSLConnectionRefused: + failf(data, "Server dropped the connection during the SSL handshake"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLClosedAbort: + failf(data, "Server aborted the SSL handshake"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLNegotiation: + failf(data, "Could not negotiate an SSL cipher suite with the server"); + return CURLE_SSL_CONNECT_ERROR; + /* Sometimes paramErr happens with buggy ciphers: */ + case paramErr: case errSSLInternal: + failf(data, "Internal SSL engine error encountered during the " + "SSL handshake"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLFatalAlert: + failf(data, "Fatal SSL engine error encountered during the SSL " + "handshake"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unknown SSL protocol error in connection to %s:%d", + conn->host.name, err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { + /* we have been connected fine, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_3; + + /* Informational message */ + (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher); + (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol); + switch (protocol) { + case kSSLProtocol2: + infof(data, "SSL 2.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kSSLProtocol3: + infof(data, "SSL 3.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kTLSProtocol1: + infof(data, "TLS 1.0 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + case kTLSProtocol11: + infof(data, "TLS 1.1 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; + case kTLSProtocol12: + infof(data, "TLS 1.2 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#endif + default: + infof(data, "Unknown protocol connection\n"); + break; + } + + return CURLE_OK; + } +} + +static CURLcode +darwinssl_connect_step3(struct connectdata *conn, + int sockindex) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CFStringRef server_cert_summary; + char server_cert_summary_c[128]; + CFArrayRef server_certs = NULL; + SecCertificateRef server_cert; + OSStatus err; + CFIndex i, count; + SecTrustRef trust = NULL; + + /* There is no step 3! + * Well, okay, if verbose mode is on, let's print the details of the + * server certificates. */ +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS +#if CURL_BUILD_IOS +#pragma unused(server_certs) + err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + server_cert = SecTrustGetCertificateAtIndex(trust, i); + server_cert_summary = CopyCertSubject(server_cert); + memset(server_cert_summary_c, 0, 128); + if(CFStringGetCString(server_cert_summary, + server_cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Server certificate: %s\n", server_cert_summary_c); + } + CFRelease(server_cert_summary); + } + CFRelease(trust); + } +#else + /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion. + The function SecTrustGetCertificateAtIndex() is officially present + in Lion, but it is unfortunately also present in Snow Leopard as + private API and doesn't work as expected. So we have to look for + a different symbol to make sure this code is only executed under + Lion or later. */ + if(SecTrustEvaluateAsync != NULL) { +#pragma unused(server_certs) + err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + server_cert = SecTrustGetCertificateAtIndex(trust, i); + server_cert_summary = CopyCertSubject(server_cert); + memset(server_cert_summary_c, 0, 128); + if(CFStringGetCString(server_cert_summary, + server_cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Server certificate: %s\n", server_cert_summary_c); + } + CFRelease(server_cert_summary); + } + CFRelease(trust); + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); + /* Just in case SSLCopyPeerCertificates() returns null too... */ + if(err == noErr && server_certs) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, + i); + + server_cert_summary = CopyCertSubject(server_cert); + memset(server_cert_summary_c, 0, 128); + if(CFStringGetCString(server_cert_summary, + server_cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Server certificate: %s\n", server_cert_summary_c); + } + CFRelease(server_cert_summary); + } + CFRelease(server_certs); + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_IOS */ +#else +#pragma unused(trust) + err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); + if(err == noErr) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); + server_cert_summary = CopyCertSubject(server_cert); + memset(server_cert_summary_c, 0, 128); + if(CFStringGetCString(server_cert_summary, + server_cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Server certificate: %s\n", server_cert_summary_c); + } + CFRelease(server_cert_summary); + } + CFRelease(server_certs); + } +#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ + + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; +} + +static Curl_recv darwinssl_recv; +static Curl_send darwinssl_send; + +static CURLcode +darwinssl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1==connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = darwinssl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if this + * connection is done nonblocking and this loop would execute again. This + * permits the owner of a multi handle to abort a connection attempt + * before step2 has completed while ensuring that a client using select() + * or epoll() will always have a valid fdset to wait on. + */ + result = darwinssl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + + if(ssl_connect_3 == connssl->connecting_state) { + result = darwinssl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = darwinssl_recv; + conn->send[sockindex] = darwinssl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +CURL_STATIC CURLcode +Curl_darwinssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return darwinssl_connect_common(conn, sockindex, TRUE, done); +} + +CURL_STATIC CURLcode +Curl_darwinssl_connect(struct connectdata *conn, + int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = darwinssl_connect_common(conn, sockindex, FALSE, &done); + + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +CURL_STATIC void Curl_darwinssl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->ssl_ctx) { + (void)SSLClose(connssl->ssl_ctx); +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) + CFRelease(connssl->ssl_ctx); +#if CURL_SUPPORT_MAC_10_8 + else + (void)SSLDisposeContext(connssl->ssl_ctx); +#endif /* CURL_SUPPORT_MAC_10_8 */ +#else + (void)SSLDisposeContext(connssl->ssl_ctx); +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + connssl->ssl_ctx = NULL; + } + connssl->ssl_sockfd = 0; +} + +CURL_STATIC int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; + ssize_t nread; + int what; + int rc; + char buf[120]; + + if(!connssl->ssl_ctx) + return 0; + + if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) + return 0; + + Curl_darwinssl_close(conn, sockindex); + + rc = 0; + + what = Curl_socket_ready(conn->sock[sockindex], + CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); + + for(;;) { + if(what < 0) { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + rc = -1; + break; + } + + if(!what) { /* timeout */ + failf(data, "SSL shutdown timeout"); + break; + } + + /* Something to read, let's do it and hope that it is the close + notify alert from the server. No way to SSL_Read now, so use read(). */ + + nread = read(conn->sock[sockindex], buf, sizeof(buf)); + + if(nread < 0) { + failf(data, "read: %s", strerror(errno)); + rc = -1; + } + + if(nread <= 0) + break; + + what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0); + } + + return rc; +} + +CURL_STATIC void Curl_darwinssl_session_free(void *ptr) +{ + /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a + cached session ID inside the Security framework. There is a private + function that does this, but I don't want to have to explain to you why I + got your application rejected from the App Store due to the use of a + private API, so the best we can do is free up our own char array that we + created way back in darwinssl_connect_step1... */ + Curl_safefree(ptr); +} + +CURL_STATIC size_t Curl_darwinssl_version(char *buffer, size_t size) +{ + return snprintf(buffer, size, "SecureTransport"); +} + +/* + * This function uses SSLGetSessionState to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +CURL_STATIC int Curl_darwinssl_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + OSStatus err; + SSLSessionState state; + + if(connssl->ssl_ctx) { + err = SSLGetSessionState(connssl->ssl_ctx, &state); + if(err == noErr) + return state == kSSLConnected || state == kSSLHandshake; + return -1; + } + return 0; +} + +CURL_STATIC bool Curl_darwinssl_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + OSStatus err; + size_t buffer; + + if(connssl->ssl_ctx) { /* SSL is in use */ + err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer); + if(err == noErr) + return buffer > 0UL; + return false; + } + else + return false; +} + +CURL_STATIC int Curl_darwinssl_random(unsigned char *entropy, + size_t length) +{ + /* arc4random_buf() isn't available on cats older than Lion, so let's + do this manually for the benefit of the older cats. */ + size_t i; + u_int32_t random_number = 0; + + for(i = 0 ; i < length ; i++) { + if(i % sizeof(u_int32_t) == 0) + random_number = arc4random(); + entropy[i] = random_number & 0xFF; + random_number >>= 8; + } + i = random_number = 0; + return 0; +} + +CURL_STATIC void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + (void)md5len; + (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); +} + +bool Curl_darwinssl_false_start(void) { +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + if(SSLSetSessionOption != NULL) + return TRUE; +#endif + return FALSE; +} + +static ssize_t darwinssl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + /*struct SessionHandle *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + size_t processed = 0UL; + OSStatus err; + + /* The SSLWrite() function works a little differently than expected. The + fourth argument (processed) is currently documented in Apple's + documentation as: "On return, the length, in bytes, of the data actually + written." + + Now, one could interpret that as "written to the socket," but actually, + it returns the amount of data that was written to a buffer internal to + the SSLContextRef instead. So it's possible for SSLWrite() to return + errSSLWouldBlock and a number of bytes "written" because those bytes were + encrypted and written to a buffer, not to the socket. + + So if this happens, then we need to keep calling SSLWrite() over and + over again with no new data until it quits returning errSSLWouldBlock. */ + + /* Do we have buffered data to write from the last time we were called? */ + if(connssl->ssl_write_buffered_length) { + /* Write the buffered data: */ + err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed); + switch (err) { + case noErr: + /* processed is always going to be 0 because we didn't write to + the buffer, so return how much was written to the socket */ + processed = connssl->ssl_write_buffered_length; + connssl->ssl_write_buffered_length = 0UL; + break; + case errSSLWouldBlock: /* argh, try again */ + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + else { + /* We've got new data to write: */ + err = SSLWrite(connssl->ssl_ctx, mem, len, &processed); + if(err != noErr) { + switch (err) { + case errSSLWouldBlock: + /* Data was buffered but not sent, we have to tell the caller + to try sending again, and remember how much was buffered */ + connssl->ssl_write_buffered_length = len; + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + } + return (ssize_t)processed; +} + +static ssize_t darwinssl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + /*struct SessionHandle *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[num]; + size_t processed = 0UL; + OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed); + + if(err != noErr) { + switch (err) { + case errSSLWouldBlock: /* return how much we read (if anything) */ + if(processed) + return (ssize_t)processed; + *curlcode = CURLE_AGAIN; + return -1L; + break; + + /* errSSLClosedGraceful - server gracefully shut down the SSL session + errSSLClosedNoNotify - server hung up on us instead of sending a + closure alert notice, read() is returning 0 + Either way, inform the caller that the server disconnected. */ + case errSSLClosedGraceful: + case errSSLClosedNoNotify: + *curlcode = CURLE_OK; + return -1L; + break; + + default: + failf(conn->data, "SSLRead() return error %d", err); + *curlcode = CURLE_RECV_ERROR; + return -1L; + break; + } + } + return (ssize_t)processed; +} + +#endif /* USE_DARWINSSL */ diff --git a/libcurl/src/lib/vtls/darwinssl.h b/libcurl/src/lib/vtls/darwinssl.h new file mode 100644 index 0000000..f287eca --- /dev/null +++ b/libcurl/src/lib/vtls/darwinssl.h @@ -0,0 +1,76 @@ +#ifndef HEADER_CURL_DARWINSSL_H +#define HEADER_CURL_DARWINSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "../curl_setup.h" + +#ifdef USE_DARWINSSL + +CURL_STATIC CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex); + +CURL_STATIC CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); + +/* close a SSL connection */ +CURL_STATIC void Curl_darwinssl_close(struct connectdata *conn, int sockindex); + +CURL_STATIC void Curl_darwinssl_session_free(void *ptr); +CURL_STATIC size_t Curl_darwinssl_version(char *buffer, size_t size); +CURL_STATIC int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex); +CURL_STATIC int Curl_darwinssl_check_cxn(struct connectdata *conn); +CURL_STATIC bool Curl_darwinssl_data_pending(const struct connectdata *conn, + int connindex); + +CURL_STATIC int Curl_darwinssl_random(unsigned char *entropy, + size_t length); +CURL_STATIC void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); +bool Curl_darwinssl_false_start(void); + +/* Set the API backend definition to SecureTransport */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL + +/* API setup for SecureTransport */ +#define curlssl_init() (1) +#define curlssl_cleanup() Curl_nop_stmt +#define curlssl_connect Curl_darwinssl_connect +#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking +#define curlssl_session_free(x) Curl_darwinssl_session_free(x) +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_darwinssl_close +#define curlssl_shutdown(x,y) 0 +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_darwinssl_version +#define curlssl_check_cxn Curl_darwinssl_check_cxn +#define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y) +#define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z)) +#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d) +#define curlssl_false_start() Curl_darwinssl_false_start() + +#endif /* USE_DARWINSSL */ +#endif /* HEADER_CURL_DARWINSSL_H */ diff --git a/libcurl/src/lib/vtls/gskit.c b/libcurl/src/lib/vtls/gskit.c new file mode 100644 index 0000000..f683c76 --- /dev/null +++ b/libcurl/src/lib/vtls/gskit.c @@ -0,0 +1,1069 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "../curl_setup.h" + +#ifdef USE_GSKIT + +#include +#include + +/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */ +#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST +#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230 +#endif + +#ifndef GSK_TLSV10_CIPHER_SPECS +#define GSK_TLSV10_CIPHER_SPECS 236 +#endif + +#ifndef GSK_TLSV11_CIPHER_SPECS +#define GSK_TLSV11_CIPHER_SPECS 237 +#endif + +#ifndef GSK_TLSV12_CIPHER_SPECS +#define GSK_TLSV12_CIPHER_SPECS 238 +#endif + +#ifndef GSK_PROTOCOL_TLSV11 +#define GSK_PROTOCOL_TLSV11 437 +#endif + +#ifndef GSK_PROTOCOL_TLSV12 +#define GSK_PROTOCOL_TLSV12 438 +#endif + +#ifndef GSK_FALSE +#define GSK_FALSE 0 +#endif + +#ifndef GSK_TRUE +#define GSK_TRUE 1 +#endif + + +#ifdef HAVE_LIMITS_H +# include +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "gskit.h" +#include "vtls.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strequal.h" +#include "x509asn1.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + + +/* SSL version flags. */ +#define CURL_GSKPROTO_SSLV2 0 +#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2) +#define CURL_GSKPROTO_SSLV3 1 +#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3) +#define CURL_GSKPROTO_TLSV10 2 +#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10) +#define CURL_GSKPROTO_TLSV11 3 +#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11) +#define CURL_GSKPROTO_TLSV12 4 +#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12) +#define CURL_GSKPROTO_LAST 5 + + +/* Supported ciphers. */ +typedef struct { + const char *name; /* Cipher name. */ + const char *gsktoken; /* Corresponding token for GSKit String. */ + unsigned int versions; /* SSL version flags. */ +} gskit_cipher; + +static const gskit_cipher ciphertable[] = { + { "null-md5", "01", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "null-sha", "02", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "exp-rc4-md5", "03", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, + { "rc4-md5", "04", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "rc4-sha", "05", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "exp-rc2-cbc-md5", "06", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, + { "exp-des-cbc-sha", "09", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK }, + { "des-cbc3-sha", "0A", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-sha", "2F", + CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-sha", "35", + CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK }, + { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-gcm-sha256", + "9C", CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-gcm-sha384", + "9D", CURL_GSKPROTO_TLSV12_MASK }, + { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK }, + { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK }, + { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK }, + { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK }, + { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK }, + { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK }, + { (const char *) NULL, (const char *) NULL, 0 } +}; + + +static bool is_separator(char c) +{ + /* Return whether character is a cipher list separator. */ + switch (c) { + case ' ': + case '\t': + case ':': + case ',': + case ';': + return true; + } + return false; +} + + +static CURLcode gskit_status(struct SessionHandle *data, int rc, + const char *procname, CURLcode defcode) +{ + /* Process GSKit status and map it to a CURLcode. */ + switch (rc) { + case GSK_OK: + case GSK_OS400_ASYNCHRONOUS_SOC_INIT: + return CURLE_OK; + case GSK_KEYRING_OPEN_ERROR: + case GSK_OS400_ERROR_NO_ACCESS: + return CURLE_SSL_CACERT_BADFILE; + case GSK_INSUFFICIENT_STORAGE: + return CURLE_OUT_OF_MEMORY; + case GSK_ERROR_BAD_V2_CIPHER: + case GSK_ERROR_BAD_V3_CIPHER: + case GSK_ERROR_NO_CIPHERS: + return CURLE_SSL_CIPHER; + case GSK_OS400_ERROR_NOT_TRUSTED_ROOT: + case GSK_ERROR_CERT_VALIDATION: + return CURLE_PEER_FAILED_VERIFICATION; + case GSK_OS400_ERROR_TIMED_OUT: + return CURLE_OPERATION_TIMEDOUT; + case GSK_WOULD_BLOCK: + return CURLE_AGAIN; + case GSK_OS400_ERROR_NOT_REGISTERED: + break; + case GSK_ERROR_IO: + switch (errno) { + case ENOMEM: + return CURLE_OUT_OF_MEMORY; + default: + failf(data, "%s I/O error: %s", procname, strerror(errno)); + break; + } + break; + default: + failf(data, "%s: %s", procname, gsk_strerror(rc)); + break; + } + return defcode; +} + + +static CURLcode set_enum(struct SessionHandle *data, gsk_handle h, + GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok) +{ + int rc = gsk_attribute_set_enum(h, id, value); + + switch (rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); + break; + case GSK_ATTRIBUTE_INVALID_ID: + if(unsupported_ok) + return CURLE_UNSUPPORTED_PROTOCOL; + default: + failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_buffer(struct SessionHandle *data, gsk_handle h, + GSK_BUF_ID id, const char *buffer, bool unsupported_ok) +{ + int rc = gsk_attribute_set_buffer(h, id, buffer, 0); + + switch (rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); + break; + case GSK_ATTRIBUTE_INVALID_ID: + if(unsupported_ok) + return CURLE_UNSUPPORTED_PROTOCOL; + default: + failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_numeric(struct SessionHandle *data, + gsk_handle h, GSK_NUM_ID id, int value) +{ + int rc = gsk_attribute_set_numeric_value(h, id, value); + + switch (rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_numeric_value() I/O error: %s", + strerror(errno)); + break; + default: + failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_callback(struct SessionHandle *data, + gsk_handle h, GSK_CALLBACK_ID id, void *info) +{ + int rc = gsk_attribute_set_callback(h, id, info); + + switch (rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno)); + break; + default: + failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_ciphers(struct SessionHandle *data, + gsk_handle h, unsigned int *protoflags) +{ + const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST]; + const char *clp; + const gskit_cipher *ctp; + int i; + int l; + bool unsupported; + CURLcode result; + struct { + char *buf; + char *ptr; + } ciphers[CURL_GSKPROTO_LAST]; + + /* Compile cipher list into GSKit-compatible cipher lists. */ + + if(!cipherlist) + return CURLE_OK; + while(is_separator(*cipherlist)) /* Skip initial separators. */ + cipherlist++; + if(!*cipherlist) + return CURLE_OK; + + /* We allocate GSKit buffers of the same size as the input string: since + GSKit tokens are always shorter than their cipher names, allocated buffers + will always be large enough to accomodate the result. */ + l = strlen(cipherlist) + 1; + memset((char *) ciphers, 0, sizeof ciphers); + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + ciphers[i].buf = malloc(l); + if(!ciphers[i].buf) { + while(i--) + free(ciphers[i].buf); + return CURLE_OUT_OF_MEMORY; + } + ciphers[i].ptr = ciphers[i].buf; + *ciphers[i].ptr = '\0'; + } + + /* Process each cipher in input string. */ + unsupported = FALSE; + result = CURLE_OK; + for(;;) { + for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);) + cipherlist++; + l = cipherlist - clp; + if(!l) + break; + /* Search the cipher in our table. */ + for(ctp = ciphertable; ctp->name; ctp++) + if(strnequal(ctp->name, clp, l) && !ctp->name[l]) + break; + if(!ctp->name) { + failf(data, "Unknown cipher %.*s", l, clp); + result = CURLE_SSL_CIPHER; + } + else { + unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK | + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK)); + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + if(ctp->versions & (1 << i)) { + strcpy(ciphers[i].ptr, ctp->gsktoken); + ciphers[i].ptr += strlen(ctp->gsktoken); + } + } + } + + /* Advance to next cipher name or end of string. */ + while(is_separator(*cipherlist)) + cipherlist++; + } + + /* Disable protocols with empty cipher lists. */ + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) { + *protoflags &= ~(1 << i); + ciphers[i].buf[0] = '\0'; + } + } + + /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */ + if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) { + result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(unsupported) { + failf(data, "TLSv1.1-only ciphers are not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) { + result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(unsupported) { + failf(data, "TLSv1.2-only ciphers are not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + + /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to + the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */ + if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) { + result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr, + ciphers[CURL_GSKPROTO_TLSV10].ptr); + } + } + + /* Set-up other ciphers. */ + if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK)) + result = set_buffer(data, h, GSK_V3_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE); + if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK)) + result = set_buffer(data, h, GSK_V2_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE); + + /* Clean-up. */ + for(i = 0; i < CURL_GSKPROTO_LAST; i++) + free(ciphers[i].buf); + + return result; +} + + +CURL_STATIC int Curl_gskit_init(void) +{ + /* No initialisation needed. */ + + return 1; +} + + +CURL_STATIC void Curl_gskit_cleanup(void) +{ + /* Nothing to do. */ +} + + +static CURLcode init_environment(struct SessionHandle *data, + gsk_handle *envir, const char *appid, + const char *file, const char *label, + const char *password) +{ + int rc; + CURLcode result; + gsk_handle h; + + /* Creates the GSKit environment. */ + + rc = gsk_environment_open(&h); + switch (rc) { + case GSK_OK: + break; + case GSK_INSUFFICIENT_STORAGE: + return CURLE_OUT_OF_MEMORY; + default: + failf(data, "gsk_environment_open(): %s", gsk_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + + result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE); + if(!result && appid) + result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE); + if(!result && file) + result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE); + if(!result && label) + result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE); + if(!result && password) + result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE); + + if(!result) { + /* Locate CAs, Client certificate and key according to our settings. + Note: this call may be blocking for some tenths of seconds. */ + result = gskit_status(data, gsk_environment_init(h), + "gsk_environment_init()", CURLE_SSL_CERTPROBLEM); + if(!result) { + *envir = h; + return result; + } + } + /* Error: rollback. */ + gsk_environment_close(&h); + return result; +} + + +static void cancel_async_handshake(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + Qso_OverlappedIO_t cstat; + + if(QsoCancelOperation(conn->sock[sockindex], 0) > 0) + QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL); +} + + +static void close_async_handshake(struct ssl_connect_data *connssl) +{ + QsoDestroyIOCompletionPort(connssl->iocport); + connssl->iocport = -1; +} + + +static void close_one(struct ssl_connect_data *conn, + struct SessionHandle *data) +{ + if(conn->handle) { + gskit_status(data, gsk_secure_soc_close(&conn->handle), + "gsk_secure_soc_close()", 0); + conn->handle = (gsk_handle) NULL; + } + if(conn->iocport >= 0) + close_async_handshake(conn); +} + + +static ssize_t gskit_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *curlcode) +{ + struct SessionHandle *data = conn->data; + CURLcode cc; + int written; + + cc = gskit_status(data, + gsk_secure_soc_write(conn->ssl[sockindex].handle, + (char *) mem, (int) len, &written), + "gsk_secure_soc_write()", CURLE_SEND_ERROR); + if(cc != CURLE_OK) { + *curlcode = cc; + written = -1; + } + return (ssize_t) written; /* number of bytes */ +} + + +static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, + size_t buffersize, CURLcode *curlcode) +{ + struct SessionHandle *data = conn->data; + int buffsize; + int nread; + CURLcode cc; + + buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; + cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle, + buf, buffsize, &nread), + "gsk_secure_soc_read()", CURLE_RECV_ERROR); + if(cc != CURLE_OK) { + *curlcode = cc; + nread = -1; + } + return (ssize_t) nread; +} + + +static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + gsk_handle envir; + CURLcode result; + int rc; + char *keyringfile; + char *keyringpwd; + char *keyringlabel; + char *sni; + unsigned int protoflags; + long timeout; + Qso_OverlappedIO_t commarea; + + /* Create SSL environment, start (preferably asynchronous) handshake. */ + + connssl->handle = (gsk_handle) NULL; + connssl->iocport = -1; + + /* GSKit supports two ways of specifying an SSL context: either by + * application identifier (that should have been defined at the system + * level) or by keyring file, password and certificate label. + * Local certificate name (CURLOPT_SSLCERT) is used to hold either the + * application identifier of the certificate label. + * Key password (CURLOPT_KEYPASSWD) holds the keyring password. + * It is not possible to have different keyrings for the CAs and the + * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify + * the keyring file. + * If no key password is given and the keyring is the system keyring, + * application identifier mode is tried first, as recommended in IBM doc. + */ + + keyringfile = data->set.str[STRING_SSL_CAFILE]; + keyringpwd = data->set.str[STRING_KEY_PASSWD]; + keyringlabel = data->set.str[STRING_CERT]; + envir = (gsk_handle) NULL; + + if(keyringlabel && *keyringlabel && !keyringpwd && + !strcmp(keyringfile, CURL_CA_BUNDLE)) { + /* Try application identifier mode. */ + init_environment(data, &envir, keyringlabel, (const char *) NULL, + (const char *) NULL, (const char *) NULL); + } + + if(!envir) { + /* Use keyring mode. */ + result = init_environment(data, &envir, (const char *) NULL, + keyringfile, keyringlabel, keyringpwd); + if(result) + return result; + } + + /* Create secure session. */ + result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle), + "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR); + gsk_environment_close(&envir); + if(result) + return result; + + /* Determine which SSL/TLS version should be enabled. */ + protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK; + sni = conn->host.name; + switch (data->set.ssl.version) { + case CURL_SSLVERSION_SSLv2: + protoflags = CURL_GSKPROTO_SSLV2_MASK; + sni = (char *) NULL; + break; + case CURL_SSLVERSION_SSLv3: + protoflags = CURL_GSKPROTO_SSLV3_MASK; + sni = (char *) NULL; + break; + case CURL_SSLVERSION_TLSv1: + protoflags = CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; + break; + case CURL_SSLVERSION_TLSv1_0: + protoflags = CURL_GSKPROTO_TLSV10_MASK; + break; + case CURL_SSLVERSION_TLSv1_1: + protoflags = CURL_GSKPROTO_TLSV11_MASK; + break; + case CURL_SSLVERSION_TLSv1_2: + protoflags = CURL_GSKPROTO_TLSV12_MASK; + break; + } + + /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ + if(sni) { + result = set_buffer(data, connssl->handle, + GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) + result = CURLE_OK; + } + + /* Set session parameters. */ + if(!result) { + /* Compute the handshake timeout. Since GSKit granularity is 1 second, + we round up the required value. */ + timeout = Curl_timeleft(data, NULL, TRUE); + if(timeout < 0) + result = CURLE_OPERATION_TIMEDOUT; + else + result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT, + (timeout + 999) / 1000); + } + if(!result) + result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]); + if(!result) + result = set_ciphers(data, connssl->handle, &protoflags); + if(!protoflags) { + failf(data, "No SSL protocol/cipher combination enabled"); + result = CURLE_SSL_CIPHER; + } + if(!result) + result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2, + (protoflags & CURL_GSKPROTO_SSLV2_MASK)? + GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); + if(!result) + result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3, + (protoflags & CURL_GSKPROTO_SSLV3_MASK)? + GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); + if(!result) + result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1, + (protoflags & CURL_GSKPROTO_TLSV10_MASK)? + GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); + if(!result) { + result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11, + (protoflags & CURL_GSKPROTO_TLSV11_MASK)? + GSK_TRUE: GSK_FALSE, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { + failf(data, "TLS 1.1 not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result) { + result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12, + (protoflags & CURL_GSKPROTO_TLSV12_MASK)? + GSK_TRUE: GSK_FALSE, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { + failf(data, "TLS 1.2 not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result) + result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE, + data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL: + GSK_SERVER_AUTH_PASSTHRU, FALSE); + + if(!result) { + /* Start handshake. Try asynchronous first. */ + memset(&commarea, 0, sizeof commarea); + connssl->iocport = QsoCreateIOCompletionPort(); + if(connssl->iocport != -1) { + result = gskit_status(data, + gsk_secure_soc_startInit(connssl->handle, + connssl->iocport, + &commarea), + "gsk_secure_soc_startInit()", + CURLE_SSL_CONNECT_ERROR); + if(!result) { + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; + } + else + close_async_handshake(connssl); + } + else if(errno != ENOBUFS) + result = gskit_status(data, GSK_ERROR_IO, + "QsoCreateIOCompletionPort()", 0); + else { + /* No more completion port available. Use synchronous IO. */ + result = gskit_status(data, gsk_secure_soc_init(connssl->handle), + "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); + if(!result) { + connssl->connecting_state = ssl_connect_3; + return CURLE_OK; + } + } + } + + /* Error: rollback. */ + close_one(connssl, data); + return result; +} + + +static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, + bool nonblocking) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + Qso_OverlappedIO_t cstat; + long timeout_ms; + struct timeval stmv; + CURLcode result; + + /* Poll or wait for end of SSL asynchronous handshake. */ + + for(;;) { + timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE); + if(timeout_ms < 0) + timeout_ms = 0; + stmv.tv_sec = timeout_ms / 1000; + stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000; + switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) { + case 1: /* Operation complete. */ + break; + case -1: /* An error occurred: handshake still in progress. */ + if(errno == EINTR) { + if(nonblocking) + return CURLE_OK; + continue; /* Retry. */ + } + if(errno != ETIME) { + failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno)); + cancel_async_handshake(conn, sockindex); + close_async_handshake(connssl); + return CURLE_SSL_CONNECT_ERROR; + } + /* FALL INTO... */ + case 0: /* Handshake in progress, timeout occurred. */ + if(nonblocking) + return CURLE_OK; + cancel_async_handshake(conn, sockindex); + close_async_handshake(connssl); + return CURLE_OPERATION_TIMEDOUT; + } + break; + } + result = gskit_status(data, cstat.returnValue, "SSL handshake", + CURLE_SSL_CONNECT_ERROR); + if(!result) + connssl->connecting_state = ssl_connect_3; + close_async_handshake(connssl); + return result; +} + + +static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const gsk_cert_data_elem *cdev; + int cdec; + const gsk_cert_data_elem *p; + const char *cert = (const char *) NULL; + const char *certend; + const char *ptr; + int i; + CURLcode result; + + /* SSL handshake done: gather certificate info and verify host. */ + + if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle, + GSK_PARTNER_CERT_INFO, + &cdev, &cdec), + "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) == + CURLE_OK) { + infof(data, "Server certificate:\n"); + p = cdev; + for(i = 0; i++ < cdec; p++) + switch (p->cert_data_id) { + case CERT_BODY_DER: + cert = p->cert_data_p; + certend = cert + cdev->cert_data_l; + break; + case CERT_DN_PRINTABLE: + infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_ISSUER_DN_PRINTABLE: + infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_VALID_FROM: + infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_VALID_TO: + infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + } + } + + /* Verify host. */ + result = Curl_verifyhost(conn, cert, certend); + if(result) + return result; + + /* The only place GSKit can get the whole CA chain is a validation + callback where no user data pointer is available. Therefore it's not + possible to copy this chain into our structures for CAINFO. + However the server certificate may be available, thus we can return + info about it. */ + if(data->set.ssl.certinfo) { + result = Curl_ssl_init_certinfo(data, 1); + if(result) + return result; + + if(cert) { + result = Curl_extract_certinfo(conn, 0, cert, certend); + if(result) + return result; + } + } + + /* Check pinned public key. */ + ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + if(!result && ptr) { + curl_X509certificate x509; + curl_asn1Element *p; + + if(!cert) + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + Curl_parseX509(&x509, cert, certend); + p = &x509.subjectPublicKeyInfo; + result = Curl_pin_peer_pubkey(ptr, p->header, p->end - p->header); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } + + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; +} + + +static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long timeout_ms; + Qso_OverlappedIO_t cstat; + CURLcode result = CURLE_OK; + + *done = connssl->state == ssl_connection_complete; + if(*done) + return CURLE_OK; + + /* Step 1: create session, start handshake. */ + if(connssl->connecting_state == ssl_connect_1) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + result = CURLE_OPERATION_TIMEDOUT; + } + else + result = gskit_connect_step1(conn, sockindex); + } + + /* Step 2: check if handshake is over. */ + if(!result && connssl->connecting_state == ssl_connect_2) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + result = CURLE_OPERATION_TIMEDOUT; + } + else + result = gskit_connect_step2(conn, sockindex, nonblocking); + } + + /* Step 3: gather certificate info, verify host. */ + if(!result && connssl->connecting_state == ssl_connect_3) + result = gskit_connect_step3(conn, sockindex); + + if(result) + close_one(connssl, data); + else if(connssl->connecting_state == ssl_connect_done) { + connssl->state = ssl_connection_complete; + connssl->connecting_state = ssl_connect_1; + conn->recv[sockindex] = gskit_recv; + conn->send[sockindex] = gskit_send; + *done = TRUE; + } + + return result; +} + + +CURL_STATIC CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + CURLcode result; + + result = gskit_connect_common(conn, sockindex, TRUE, done); + if(*done || result) + conn->ssl[sockindex].connecting_state = ssl_connect_1; + return result; +} + + +CURL_STATIC CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done; + + conn->ssl[sockindex].connecting_state = ssl_connect_1; + result = gskit_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + + +CURL_STATIC void Curl_gskit_close(struct connectdata *conn, int sockindex) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->use) + close_one(connssl, data); +} + + +CURL_STATIC int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; + ssize_t nread; + int what; + int rc; + char buf[120]; + + if(!connssl->handle) + return 0; + + if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) + return 0; + + close_one(connssl, data); + rc = 0; + what = Curl_socket_ready(conn->sock[sockindex], + CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); + + for(;;) { + if(what < 0) { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + rc = -1; + break; + } + + if(!what) { /* timeout */ + failf(data, "SSL shutdown timeout"); + break; + } + + /* Something to read, let's do it and hope that it is the close + notify alert from the server. No way to gsk_secure_soc_read() now, so + use read(). */ + + nread = read(conn->sock[sockindex], buf, sizeof(buf)); + + if(nread < 0) { + failf(data, "read: %s", strerror(errno)); + rc = -1; + } + + if(nread <= 0) + break; + + what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0); + } + + return rc; +} + + +CURL_STATIC size_t Curl_gskit_version(char *buffer, size_t size) +{ + strncpy(buffer, "GSKit", size); + return strlen(buffer); +} + + +CURL_STATIC int Curl_gskit_check_cxn(struct connectdata *cxn) +{ + int err; + int errlen; + + /* The only thing that can be tested here is at the socket level. */ + + if(!cxn->ssl[FIRSTSOCKET].handle) + return 0; /* connection has been closed */ + + err = 0; + errlen = sizeof err; + + if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR, + (unsigned char *) &err, &errlen) || + errlen != sizeof err || err) + return 0; /* connection has been closed */ + + return -1; /* connection status unknown */ +} + +#endif /* USE_GSKIT */ diff --git a/libcurl/src/lib/vtls/gskit.h b/libcurl/src/lib/vtls/gskit.h new file mode 100644 index 0000000..58e15b6 --- /dev/null +++ b/libcurl/src/lib/vtls/gskit.h @@ -0,0 +1,71 @@ +#ifndef HEADER_CURL_GSKIT_H +#define HEADER_CURL_GSKIT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "../curl_setup.h" + +/* + * This header should only be needed to get included by vtls.c and gskit.c + */ + +#include "../urldata.h" + +#ifdef USE_GSKIT +CURL_STATIC int Curl_gskit_init(void); +CURL_STATIC void Curl_gskit_cleanup(void); +CURL_STATIC CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex); +CURL_STATIC CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done); +CURL_STATIC void Curl_gskit_close(struct connectdata *conn, int sockindex); +CURL_STATIC int Curl_gskit_shutdown(struct connectdata *conn, int sockindex); + +CURL_STATIC size_t Curl_gskit_version(char *buffer, size_t size); +CURL_STATIC int Curl_gskit_check_cxn(struct connectdata *cxn); + +/* Set the API backend definition to GSKit */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT + +/* this backend supports CURLOPT_CERTINFO */ +#define have_curlssl_certinfo 1 + +/* API setup for GSKit */ +#define curlssl_init Curl_gskit_init +#define curlssl_cleanup Curl_gskit_cleanup +#define curlssl_connect Curl_gskit_connect +#define curlssl_connect_nonblocking Curl_gskit_connect_nonblocking + +/* No session handling for GSKit */ +#define curlssl_session_free(x) Curl_nop_stmt +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_gskit_close +#define curlssl_shutdown(x,y) Curl_gskit_shutdown(x,y) +#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN +#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN +#define curlssl_engines_list(x) NULL +#define curlssl_version Curl_gskit_version +#define curlssl_check_cxn(x) Curl_gskit_check_cxn(x) +#define curlssl_data_pending(x,y) 0 +#define curlssl_random(x,y,z) -1 + +#endif /* USE_GSKIT */ + +#endif /* HEADER_CURL_GSKIT_H */ diff --git a/libcurl/src/lib/vtls/gtls.c b/libcurl/src/lib/vtls/gtls.c new file mode 100644 index 0000000..483c837 --- /dev/null +++ b/libcurl/src/lib/vtls/gtls.c @@ -0,0 +1,1480 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + * Note: don't use the GnuTLS' *_t variable type names in this source code, + * since they were not present in 1.0.X. + */ + +#include "../curl_setup.h" + +#ifdef USE_GNUTLS + +#include +#include +#include + +#ifdef USE_GNUTLS_NETTLE +#include +#include +#else +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "gtls.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "rawstr.h" +#include "warnless.h" +#include "x509asn1.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + Some hackish cast macros based on: + http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html +*/ +#ifndef GNUTLS_POINTER_TO_INT_CAST +#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p)) +#endif +#ifndef GNUTLS_INT_TO_POINTER_CAST +#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i)) +#endif + +/* Enable GnuTLS debugging by defining GTLSDEBUG */ +/*#define GTLSDEBUG */ + +#ifdef GTLSDEBUG +static void tls_log_func(int level, const char *str) +{ + fprintf(stderr, "|<%d>| %s", level, str); +} +#endif +static bool gtls_inited = FALSE; + +#if defined(GNUTLS_VERSION_NUMBER) +# if (GNUTLS_VERSION_NUMBER >= 0x020c00) +# undef gnutls_transport_set_lowat +# define gnutls_transport_set_lowat(A,B) Curl_nop_stmt +# define USE_GNUTLS_PRIORITY_SET_DIRECT 1 +# endif +# if (GNUTLS_VERSION_NUMBER >= 0x020c03) +# define GNUTLS_MAPS_WINSOCK_ERRORS 1 +# endif + +# if (GNUTLS_VERSION_NUMBER >= 0x030200) +# define HAS_ALPN +# endif + +# if (GNUTLS_VERSION_NUMBER >= 0x03020d) +# define HAS_OCSP +# endif + +# if (GNUTLS_VERSION_NUMBER >= 0x030306) +# define HAS_CAPATH +# endif +#endif + +#ifdef HAS_OCSP +# include +#endif + +/* + * Custom push and pull callback functions used by GNU TLS to read and write + * to the socket. These functions are simple wrappers to send() and recv() + * (although here using the sread/swrite macros as defined by + * curl_setup_once.h). + * We use custom functions rather than the GNU TLS defaults because it allows + * us to get specific about the fourth "flags" argument, and to use arbitrary + * private data with gnutls_transport_set_ptr if we wish. + * + * When these custom push and pull callbacks fail, GNU TLS checks its own + * session-specific error variable, and when not set also its own global + * errno variable, in order to take appropriate action. GNU TLS does not + * require that the transport is actually a socket. This implies that for + * Windows builds these callbacks should ideally set the session-specific + * error variable using function gnutls_transport_set_errno or as a last + * resort global errno variable using gnutls_transport_set_global_errno, + * with a transport agnostic error value. This implies that some winsock + * error translation must take place in these callbacks. + * + * Paragraph above applies to GNU TLS versions older than 2.12.3, since + * this version GNU TLS does its own internal winsock error translation + * using system_errno() function. + */ + +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) +# define gtls_EINTR 4 +# define gtls_EIO 5 +# define gtls_EAGAIN 11 +static int gtls_mapped_sockerrno(void) +{ + switch(SOCKERRNO) { + case WSAEWOULDBLOCK: + return gtls_EAGAIN; + case WSAEINTR: + return gtls_EINTR; + default: + break; + } + return gtls_EIO; +} +#endif + +static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len) +{ + ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) + if(ret < 0) + gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); +#endif + return ret; +} + +static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) +{ + ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) + if(ret < 0) + gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); +#endif + return ret; +} + +/* Curl_gtls_init() + * + * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that + * are not thread-safe and thus this function itself is not thread-safe and + * must only be called from within curl_global_init() to keep the thread + * situation under control! + */ +CURL_STATIC int Curl_gtls_init(void) +{ + int ret = 1; + if(!gtls_inited) { + ret = gnutls_global_init()?0:1; +#ifdef GTLSDEBUG + gnutls_global_set_log_function(tls_log_func); + gnutls_global_set_log_level(2); +#endif + gtls_inited = TRUE; + } + return ret; +} + +CURL_STATIC int Curl_gtls_cleanup(void) +{ + if(gtls_inited) { + gnutls_global_deinit(); + gtls_inited = FALSE; + } + return 1; +} + +static void showtime(struct SessionHandle *data, + const char *text, + time_t stamp) +{ + struct tm buffer; + const struct tm *tm = &buffer; + CURLcode result = Curl_gmtime(stamp, &buffer); + if(result) + return; + + snprintf(data->state.buffer, + BUFSIZE, + "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT", + text, + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + infof(data, "%s\n", data->state.buffer); +} + +static gnutls_datum_t load_file (const char *file) +{ + FILE *f; + gnutls_datum_t loaded_file = { NULL, 0 }; + long filelen; + void *ptr; + + if(!(f = fopen(file, "r"))) + return loaded_file; + if(fseek(f, 0, SEEK_END) != 0 + || (filelen = ftell(f)) < 0 + || fseek(f, 0, SEEK_SET) != 0 + || !(ptr = malloc((size_t)filelen))) + goto out; + if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) { + free(ptr); + goto out; + } + + loaded_file.data = ptr; + loaded_file.size = (unsigned int)filelen; +out: + fclose(f); + return loaded_file; +} + +static void unload_file(gnutls_datum_t data) { + free(data.data); +} + + +/* this function does a SSL/TLS (re-)handshake */ +static CURLcode handshake(struct connectdata *conn, + int sockindex, + bool duringconnect, + bool nonblocking) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + gnutls_session_t session = conn->ssl[sockindex].session; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int rc; + int what; + + for(;;) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, duringconnect); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_ready(readfd, writefd, + nonblocking?0: + timeout_ms?timeout_ms:1000); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) + return CURLE_OK; + else if(timeout_ms) { + /* timeout */ + failf(data, "SSL connection timeout at %ld", timeout_ms); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + rc = gnutls_handshake(session); + + if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) { + connssl->connecting_state = + gnutls_record_get_direction(session)? + ssl_connect_2_writing:ssl_connect_2_reading; + continue; + } + else if((rc < 0) && !gnutls_error_is_fatal(rc)) { + const char *strerr = NULL; + + if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { + int alert = gnutls_alert_get(session); + strerr = gnutls_alert_get_name(alert); + } + + if(strerr == NULL) + strerr = gnutls_strerror(rc); + + failf(data, "gnutls_handshake() warning: %s", strerr); + } + else if(rc < 0) { + const char *strerr = NULL; + + if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { + int alert = gnutls_alert_get(session); + strerr = gnutls_alert_get_name(alert); + } + + if(strerr == NULL) + strerr = gnutls_strerror(rc); + + failf(data, "gnutls_handshake() failed: %s", strerr); + return CURLE_SSL_CONNECT_ERROR; + } + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + return CURLE_OK; + } +} + +static gnutls_x509_crt_fmt_t do_file_type(const char *type) +{ + if(!type || !type[0]) + return GNUTLS_X509_FMT_PEM; + if(Curl_raw_equal(type, "PEM")) + return GNUTLS_X509_FMT_PEM; + if(Curl_raw_equal(type, "DER")) + return GNUTLS_X509_FMT_DER; + return -1; +} + +static CURLcode +gtls_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct SessionHandle *data = conn->data; + gnutls_session_t session; + int rc; + void *ssl_sessionid; + size_t ssl_idsize; + bool sni = TRUE; /* default is SNI enabled */ +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT + static const int cipher_priority[] = { + /* These two ciphers were added to GnuTLS as late as ver. 3.0.1, + but this code path is only ever used for ver. < 2.12.0. + GNUTLS_CIPHER_AES_128_GCM, + GNUTLS_CIPHER_AES_256_GCM, + */ + GNUTLS_CIPHER_AES_128_CBC, + GNUTLS_CIPHER_AES_256_CBC, + GNUTLS_CIPHER_CAMELLIA_128_CBC, + GNUTLS_CIPHER_CAMELLIA_256_CBC, + GNUTLS_CIPHER_3DES_CBC, + }; + static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; + static int protocol_priority[] = { 0, 0, 0, 0 }; +#else +#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" +/* If GnuTLS was compiled without support for SRP it will error out if SRP is + requested in the priority string, so treat it specially + */ +#define GNUTLS_SRP "+SRP" + const char* prioritylist; + const char *err = NULL; +#endif + + if(conn->ssl[sockindex].state == ssl_connection_complete) + /* to make us tolerant against being called more than once for the + same connection */ + return CURLE_OK; + + if(!gtls_inited) + Curl_gtls_init(); + + /* GnuTLS only supports SSLv3 and TLSv1 */ + if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) + sni = FALSE; /* SSLv3 has no SNI */ + + /* allocate a cred struct */ + rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); + + rc = gnutls_srp_allocate_client_credentials( + &conn->ssl[sockindex].srp_client_cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_srp_allocate_client_cred() failed: %s", + gnutls_strerror(rc)); + return CURLE_OUT_OF_MEMORY; + } + + rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. + srp_client_cred, + data->set.ssl.username, + data->set.ssl.password); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_srp_set_client_cred() failed: %s", + gnutls_strerror(rc)); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } +#endif + + if(data->set.ssl.CAfile) { + /* set the trusted CA cert bundle file */ + gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); + + rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, + data->set.ssl.CAfile, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)\n", + data->set.ssl.CAfile, gnutls_strerror(rc)); + if(data->set.ssl.verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + else + infof(data, "found %d certificates in %s\n", + rc, data->set.ssl.CAfile); + } + +#ifdef HAS_CAPATH + if(data->set.ssl.CApath) { + /* set the trusted CA cert directory */ + rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred, + data->set.ssl.CApath, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)\n", + data->set.ssl.CAfile, gnutls_strerror(rc)); + if(data->set.ssl.verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + else + infof(data, "found %d certificates in %s\n", + rc, data->set.ssl.CApath); + } +#endif + + if(data->set.ssl.CRLfile) { + /* set the CRL list file */ + rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, + data->set.ssl.CRLfile, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + failf(data, "error reading crl file %s (%s)", + data->set.ssl.CRLfile, gnutls_strerror(rc)); + return CURLE_SSL_CRL_BADFILE; + } + else + infof(data, "found %d CRL in %s\n", + rc, data->set.ssl.CRLfile); + } + + /* Initialize TLS session as a client */ + rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_init() failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + + /* convenient assign */ + session = conn->ssl[sockindex].session; + + if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && +#endif + sni && + (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, + strlen(conn->host.name)) < 0)) + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + + /* Use default priorities */ + rc = gnutls_set_default_priority(session); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT + rc = gnutls_cipher_set_priority(session, cipher_priority); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + + /* Sets the priority on the certificate types supported by gnutls. Priority + is higher for types specified before others. After specifying the types + you want, you must append a 0. */ + rc = gnutls_certificate_type_set_priority(session, cert_type_priority); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + + if(data->set.ssl.cipher_list != NULL) { + failf(data, "can't pass a custom cipher list to older GnuTLS" + " versions"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch (data->set.ssl.version) { + case CURL_SSLVERSION_SSLv3: + protocol_priority[0] = GNUTLS_SSL3; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + protocol_priority[0] = GNUTLS_TLS1_0; + protocol_priority[1] = GNUTLS_TLS1_1; + protocol_priority[2] = GNUTLS_TLS1_2; + break; + case CURL_SSLVERSION_TLSv1_0: + protocol_priority[0] = GNUTLS_TLS1_0; + break; + case CURL_SSLVERSION_TLSv1_1: + protocol_priority[0] = GNUTLS_TLS1_1; + break; + case CURL_SSLVERSION_TLSv1_2: + protocol_priority[0] = GNUTLS_TLS1_2; + break; + case CURL_SSLVERSION_SSLv2: + default: + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + break; + } + rc = gnutls_protocol_set_priority(session, protocol_priority); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "Did you pass a valid GnuTLS cipher list?"); + return CURLE_SSL_CONNECT_ERROR; + } + +#else + /* Ensure +SRP comes at the *end* of all relevant strings so that it can be + * removed if a run-time error indicates that SRP is not supported by this + * GnuTLS version */ + switch (data->set.ssl.version) { + case CURL_SSLVERSION_SSLv3: + prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; + sni = false; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP; + break; + case CURL_SSLVERSION_TLSv1_0: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:" GNUTLS_SRP; + break; + case CURL_SSLVERSION_TLSv1_1: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:" GNUTLS_SRP; + break; + case CURL_SSLVERSION_TLSv1_2: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2:" GNUTLS_SRP; + break; + case CURL_SSLVERSION_SSLv2: + default: + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + break; + } + rc = gnutls_priority_set_direct(session, prioritylist, &err); + if((rc == GNUTLS_E_INVALID_REQUEST) && err) { + if(!strcmp(err, GNUTLS_SRP)) { + /* This GnuTLS was probably compiled without support for SRP. + * Note that fact and try again without it. */ + int validprioritylen = curlx_uztosi(err - prioritylist); + char *prioritycopy = strdup(prioritylist); + if(!prioritycopy) + return CURLE_OUT_OF_MEMORY; + + infof(data, "This GnuTLS does not support SRP\n"); + if(validprioritylen) + /* Remove the :+SRP */ + prioritycopy[validprioritylen - 1] = 0; + rc = gnutls_priority_set_direct(session, prioritycopy, &err); + free(prioritycopy); + } + } + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "Error %d setting GnuTLS cipher list starting with %s", + rc, err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + +#ifdef HAS_ALPN + if(data->set.ssl_enable_alpn) { + int cur = 0; + gnutls_datum_t protocols[2]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; + protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; + cur++; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1; + protocols[cur].size = ALPN_HTTP_1_1_LENGTH; + cur++; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + gnutls_alpn_set_protocols(session, protocols, cur, 0); + } +#endif + + if(data->set.str[STRING_CERT]) { + if(gnutls_certificate_set_x509_key_file( + conn->ssl[sockindex].cred, + data->set.str[STRING_CERT], + data->set.str[STRING_KEY] ? + data->set.str[STRING_KEY] : data->set.str[STRING_CERT], + do_file_type(data->set.str[STRING_CERT_TYPE]) ) != + GNUTLS_E_SUCCESS) { + failf(data, "error reading X.509 key or certificate file"); + return CURLE_SSL_CONNECT_ERROR; + } + } + +#ifdef USE_TLS_SRP + /* put the credentials to the current session */ + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, + conn->ssl[sockindex].srp_client_cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + } + else +#endif + { + rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, + conn->ssl[sockindex].cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* set the connection handle (file descriptor for the socket) */ + gnutls_transport_set_ptr(session, + GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); + + /* register callback functions to send and receive data. */ + gnutls_transport_set_push_function(session, Curl_gtls_push); + gnutls_transport_set_pull_function(session, Curl_gtls_pull); + + /* lowat must be set to zero when using custom push and pull functions. */ + gnutls_transport_set_lowat(session, 0); + +#ifdef HAS_OCSP + if(data->set.ssl.verifystatus) { + rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif + + /* This might be a reconnect, so we check for a session ID in the cache + to speed up things */ + + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { + /* we got a session id, use it! */ + gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); + + /* Informational message */ + infof (data, "SSL re-using session ID\n"); + } + + return CURLE_OK; +} + +static CURLcode pkp_pin_peer_pubkey(gnutls_x509_crt_t cert, + const char *pinnedpubkey) +{ + /* Scratch */ + size_t len1 = 0, len2 = 0; + unsigned char *buff1 = NULL; + + gnutls_pubkey_t key = NULL; + + /* Result is returned to caller */ + int ret = 0; + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(NULL == pinnedpubkey) + return CURLE_OK; + + if(NULL == cert) + return result; + + do { + /* Begin Gyrations to get the public key */ + gnutls_pubkey_init(&key); + + ret = gnutls_pubkey_import_x509(key, cert, 0); + if(ret < 0) + break; /* failed */ + + ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1); + if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0) + break; /* failed */ + + buff1 = malloc(len1); + if(NULL == buff1) + break; /* failed */ + + len2 = len1; + + ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2); + if(ret < 0 || len1 != len2) + break; /* failed */ + + /* End Gyrations */ + + /* The one good exit point */ + result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1); + } while(0); + + if(NULL != key) + gnutls_pubkey_deinit(key); + + Curl_safefree(buff1); + + return result; +} + +static Curl_recv gtls_recv; +static Curl_send gtls_send; + +static CURLcode +gtls_connect_step3(struct connectdata *conn, + int sockindex) +{ + unsigned int cert_list_size; + const gnutls_datum_t *chainp; + unsigned int verify_status = 0; + gnutls_x509_crt_t x509_cert, x509_issuer; + gnutls_datum_t issuerp; + char certbuf[256] = ""; /* big enough? */ + size_t size; + unsigned int algo; + unsigned int bits; + time_t certclock; + const char *ptr; + struct SessionHandle *data = conn->data; + gnutls_session_t session = conn->ssl[sockindex].session; + int rc; + bool incache; + void *ssl_sessionid; +#ifdef HAS_ALPN + gnutls_datum_t proto; +#endif + CURLcode result = CURLE_OK; + + gnutls_protocol_t version = gnutls_protocol_get_version(session); + + /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */ + ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session), + gnutls_cipher_get(session), + gnutls_mac_get(session)); + + infof(data, "SSL connection using %s / %s\n", + gnutls_protocol_get_name(version), ptr); + + /* This function will return the peer's raw certificate (chain) as sent by + the peer. These certificates are in raw format (DER encoded for + X.509). In case of a X.509 then a certificate list may be present. The + first certificate in the list is the peer's certificate, following the + issuer's certificate, then the issuer's issuer etc. */ + + chainp = gnutls_certificate_get_peers(session, &cert_list_size); + if(!chainp) { + if(data->set.ssl.verifypeer || + data->set.ssl.verifyhost || + data->set.ssl.issuercert) { +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP + && data->set.ssl.username != NULL + && !data->set.ssl.verifypeer + && gnutls_cipher_get(session)) { + /* no peer cert, but auth is ok if we have SRP user and cipher and no + peer verify */ + } + else { +#endif + failf(data, "failed to get server cert"); + return CURLE_PEER_FAILED_VERIFICATION; +#ifdef USE_TLS_SRP + } +#endif + } + infof(data, "\t common name: WARNING couldn't obtain\n"); + } + + if(data->set.ssl.certinfo && chainp) { + unsigned int i; + + result = Curl_ssl_init_certinfo(data, cert_list_size); + if(result) + return result; + + for(i = 0; i < cert_list_size; i++) { + const char *beg = (const char *) chainp[i].data; + const char *end = beg + chainp[i].size; + + result = Curl_extract_certinfo(conn, i, beg, end); + if(result) + return result; + } + } + + if(data->set.ssl.verifypeer) { + /* This function will try to verify the peer's certificate and return its + status (trusted, invalid etc.). The value of status should be one or + more of the gnutls_certificate_status_t enumerated elements bitwise + or'd. To avoid denial of service attacks some default upper limits + regarding the certificate key size and chain size are set. To override + them use gnutls_certificate_set_verify_limits(). */ + + rc = gnutls_certificate_verify_peers2(session, &verify_status); + if(rc < 0) { + failf(data, "server cert verify failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + + /* verify_status is a bitmask of gnutls_certificate_status bits */ + if(verify_status & GNUTLS_CERT_INVALID) { + if(data->set.ssl.verifypeer) { + failf(data, "server certificate verification failed. CAfile: %s " + "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none", + data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none"); + return CURLE_SSL_CACERT; + } + else + infof(data, "\t server certificate verification FAILED\n"); + } + else + infof(data, "\t server certificate verification OK\n"); + } + else + infof(data, "\t server certificate verification SKIPPED\n"); + +#ifdef HAS_OCSP + if(data->set.ssl.verifystatus) { + if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { + if(verify_status & GNUTLS_CERT_REVOKED) + infof(data, "\t server certificate was REVOKED\n"); + else + infof(data, "\t server certificate status verification FAILED\n"); + + return CURLE_SSL_INVALIDCERTSTATUS; + } + else + infof(data, "\t server certificate status verification OK\n"); + } + else + infof(data, "\t server certificate status verification SKIPPED\n"); +#endif + + /* initialize an X.509 certificate structure. */ + gnutls_x509_crt_init(&x509_cert); + + if(chainp) + /* convert the given DER or PEM encoded Certificate to the native + gnutls_x509_crt_t format */ + gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); + + if(data->set.ssl.issuercert) { + gnutls_x509_crt_init(&x509_issuer); + issuerp = load_file(data->set.ssl.issuercert); + gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); + rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer); + gnutls_x509_crt_deinit(x509_issuer); + unload_file(issuerp); + if(rc <= 0) { + failf(data, "server certificate issuer check failed (IssuerCert: %s)", + data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_ISSUER_ERROR; + } + infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n", + data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); + } + + size=sizeof(certbuf); + rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME, + 0, /* the first and only one */ + FALSE, + certbuf, + &size); + if(rc) { + infof(data, "error fetching CN from cert:%s\n", + gnutls_strerror(rc)); + } + + /* This function will check if the given certificate's subject matches the + given hostname. This is a basic implementation of the matching described + in RFC2818 (HTTPS), which takes into account wildcards, and the subject + alternative name PKIX extension. Returns non zero on success, and zero on + failure. */ + rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name); +#if GNUTLS_VERSION_NUMBER < 0x030306 + /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP + addresses. */ + if(!rc) { +#ifdef ENABLE_IPV6 + #define use_addr in6_addr +#else + #define use_addr in_addr +#endif + unsigned char addrbuf[sizeof(struct use_addr)]; + unsigned char certaddr[sizeof(struct use_addr)]; + size_t addrlen = 0, certaddrlen; + int i; + int ret = 0; + + if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0) + addrlen = 4; +#ifdef ENABLE_IPV6 + else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0) + addrlen = 16; +#endif + + if(addrlen) { + for(i=0; ; i++) { + certaddrlen = sizeof(certaddr); + ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr, + &certaddrlen, NULL); + /* If this happens, it wasn't an IP address. */ + if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) + continue; + if(ret < 0) + break; + if(ret != GNUTLS_SAN_IPADDRESS) + continue; + if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) { + rc = 1; + break; + } + } + } + } +#endif + if(!rc) { + if(data->set.ssl.verifyhost) { + failf(data, "SSL: certificate subject name (%s) does not match " + "target host name '%s'", certbuf, conn->host.dispname); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t common name: %s (does not match '%s')\n", + certbuf, conn->host.dispname); + } + else + infof(data, "\t common name: %s (matched)\n", certbuf); + + /* Check for time-based validity */ + certclock = gnutls_x509_crt_get_expiration_time(x509_cert); + + if(certclock == (time_t)-1) { + if(data->set.ssl.verifypeer) { + failf(data, "server cert expiration date verify failed"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_CONNECT_ERROR; + } + else + infof(data, "\t server certificate expiration date verify FAILED\n"); + } + else { + if(certclock < time(NULL)) { + if(data->set.ssl.verifypeer) { + failf(data, "server certificate expiration date has passed."); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t server certificate expiration date FAILED\n"); + } + else + infof(data, "\t server certificate expiration date OK\n"); + } + + certclock = gnutls_x509_crt_get_activation_time(x509_cert); + + if(certclock == (time_t)-1) { + if(data->set.ssl.verifypeer) { + failf(data, "server cert activation date verify failed"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_CONNECT_ERROR; + } + else + infof(data, "\t server certificate activation date verify FAILED\n"); + } + else { + if(certclock > time(NULL)) { + if(data->set.ssl.verifypeer) { + failf(data, "server certificate not activated yet."); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t server certificate activation date FAILED\n"); + } + else + infof(data, "\t server certificate activation date OK\n"); + } + + ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + if(ptr) { + result = pkp_pin_peer_pubkey(x509_cert, ptr); + if(result != CURLE_OK) { + failf(data, "SSL: public key does not match pinned public key!"); + gnutls_x509_crt_deinit(x509_cert); + return result; + } + } + + /* Show: + + - subject + - start date + - expire date + - common name + - issuer + + */ + + /* public key algorithm's parameters */ + algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); + infof(data, "\t certificate public key: %s\n", + gnutls_pk_algorithm_get_name(algo)); + + /* version of the X.509 certificate. */ + infof(data, "\t certificate version: #%d\n", + gnutls_x509_crt_get_version(x509_cert)); + + + size = sizeof(certbuf); + gnutls_x509_crt_get_dn(x509_cert, certbuf, &size); + infof(data, "\t subject: %s\n", certbuf); + + certclock = gnutls_x509_crt_get_activation_time(x509_cert); + showtime(data, "start date", certclock); + + certclock = gnutls_x509_crt_get_expiration_time(x509_cert); + showtime(data, "expire date", certclock); + + size = sizeof(certbuf); + gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); + infof(data, "\t issuer: %s\n", certbuf); + + gnutls_x509_crt_deinit(x509_cert); + + /* compression algorithm (if any) */ + ptr = gnutls_compression_get_name(gnutls_compression_get(session)); + /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ + infof(data, "\t compression: %s\n", ptr); + +#ifdef HAS_ALPN + if(data->set.ssl_enable_alpn) { + rc = gnutls_alpn_get_selected_protocol(session, &proto); + if(rc == 0) { + infof(data, "ALPN, server accepted to use %.*s\n", proto.size, + proto.data); + +#ifdef USE_NGHTTP2 + if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2_0; + } + else +#endif + if(proto.size == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + } +#endif + + conn->ssl[sockindex].state = ssl_connection_complete; + conn->recv[sockindex] = gtls_recv; + conn->send[sockindex] = gtls_send; + + { + /* we always unconditionally get the session id here, as even if we + already got it from the cache and asked to use it in the connection, it + might've been rejected and then a new one is in use now and we need to + detect that. */ + void *connect_sessionid; + size_t connect_idsize = 0; + + /* get the session ID data size */ + gnutls_session_get_data(session, NULL, &connect_idsize); + connect_sessionid = malloc(connect_idsize); /* get a buffer for it */ + + if(connect_sessionid) { + /* extract session ID to the allocated buffer */ + gnutls_session_get_data(session, connect_sessionid, &connect_idsize); + + incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)); + if(incache) { + /* there was one before in the cache, so instead of risking that the + previous one was rejected, we just kill that and store the new */ + Curl_ssl_delsessionid(conn, ssl_sessionid); + } + + /* store this session id */ + result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize); + if(result) { + free(connect_sessionid); + result = CURLE_OUT_OF_MEMORY; + } + } + else + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + + +/* + * This function is called after the TCP connect has completed. Setup the TLS + * layer and do all necessary magic. + */ +/* We use connssl->connecting_state to keep track of the connection status; + there are three states: 'ssl_connect_1' (not started yet or complete), + 'ssl_connect_2_reading' (waiting for data from server), and + 'ssl_connect_2_writing' (waiting to be able to write). + */ +static CURLcode +gtls_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + int rc; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + /* Initiate the connection, if not already done */ + if(ssl_connect_1==connssl->connecting_state) { + rc = gtls_connect_step1 (conn, sockindex); + if(rc) + return rc; + } + + rc = handshake(conn, sockindex, TRUE, nonblocking); + if(rc) + /* handshake() sets its own error message with failf() */ + return rc; + + /* Finish connecting once the handshake is done */ + if(ssl_connect_1==connssl->connecting_state) { + rc = gtls_connect_step3(conn, sockindex); + if(rc) + return rc; + } + + *done = ssl_connect_1==connssl->connecting_state; + + return CURLE_OK; +} + +CURL_STATIC CURLcode +Curl_gtls_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return gtls_connect_common(conn, sockindex, TRUE, done); +} + +CURL_STATIC CURLcode +Curl_gtls_connect(struct connectdata *conn, + int sockindex) + +{ + CURLcode result; + bool done = FALSE; + + result = gtls_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static ssize_t gtls_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len); + + if(rc < 0 ) { + *curlcode = (rc == GNUTLS_E_AGAIN) + ? CURLE_AGAIN + : CURLE_SEND_ERROR; + + rc = -1; + } + + return rc; +} + +static void close_one(struct connectdata *conn, + int idx) +{ + if(conn->ssl[idx].session) { + gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR); + gnutls_deinit(conn->ssl[idx].session); + conn->ssl[idx].session = NULL; + } + if(conn->ssl[idx].cred) { + gnutls_certificate_free_credentials(conn->ssl[idx].cred); + conn->ssl[idx].cred = NULL; + } +#ifdef USE_TLS_SRP + if(conn->ssl[idx].srp_client_cred) { + gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred); + conn->ssl[idx].srp_client_cred = NULL; + } +#endif +} + +CURL_STATIC void Curl_gtls_close(struct connectdata *conn, int sockindex) +{ + close_one(conn, sockindex); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +CURL_STATIC int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) +{ + ssize_t result; + int retval = 0; + struct SessionHandle *data = conn->data; + int done = 0; + char buf[120]; + + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR); + + if(conn->ssl[sockindex].session) { + while(!done) { + int what = Curl_socket_ready(conn->sock[sockindex], + CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); + if(what > 0) { + /* Something to read, let's do it and hope that it is the close + notify alert from the server */ + result = gnutls_record_recv(conn->ssl[sockindex].session, + buf, sizeof(buf)); + switch(result) { + case 0: + /* This is the expected response. There was no data but only + the close notify alert */ + done = 1; + break; + case GNUTLS_E_AGAIN: + case GNUTLS_E_INTERRUPTED: + infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n"); + break; + default: + retval = -1; + done = 1; + break; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + done = 1; + break; + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + done = 1; + } + } + gnutls_deinit(conn->ssl[sockindex].session); + } + gnutls_certificate_free_credentials(conn->ssl[sockindex].cred); + +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP + && data->set.ssl.username != NULL) + gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred); +#endif + + conn->ssl[sockindex].cred = NULL; + conn->ssl[sockindex].session = NULL; + + return retval; +} + +static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + ssize_t ret; + + ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize); + if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { + *curlcode = CURLE_AGAIN; + return -1; + } + + if(ret == GNUTLS_E_REHANDSHAKE) { + /* BLOCKING call, this is bad but a work-around for now. Fixing this "the + proper way" takes a whole lot of work. */ + CURLcode result = handshake(conn, num, FALSE, FALSE); + if(result) + /* handshake() writes error message on its own */ + *curlcode = result; + else + *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */ + return -1; + } + + if(ret < 0) { + failf(conn->data, "GnuTLS recv error (%d): %s", + (int)ret, gnutls_strerror((int)ret)); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + + return ret; +} + +CURL_STATIC void Curl_gtls_session_free(void *ptr) +{ + free(ptr); +} + +CURL_STATIC size_t Curl_gtls_version(char *buffer, size_t size) +{ + return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); +} + +#ifndef USE_GNUTLS_NETTLE +static int Curl_gtls_seed(struct SessionHandle *data) +{ + /* we have the "SSL is seeded" boolean static to prevent multiple + time-consuming seedings in vain */ + static bool ssl_seeded = FALSE; + + /* Quickly add a bit of entropy */ + gcry_fast_random_poll(); + + if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || + data->set.str[STRING_SSL_EGDSOCKET]) { + + /* TODO: to a good job seeding the RNG + This may involve the gcry_control function and these options: + GCRYCTL_SET_RANDOM_SEED_FILE + GCRYCTL_SET_RNDEGD_SOCKET + */ + ssl_seeded = TRUE; + } + return 0; +} +#endif + +/* data might be NULL! */ +CURL_STATIC int Curl_gtls_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length) +{ +#if defined(USE_GNUTLS_NETTLE) + (void)data; + gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length); +#elif defined(USE_GNUTLS) + if(data) + Curl_gtls_seed(data); /* Initiate the seed if not already done */ + gcry_randomize(entropy, length, GCRY_STRONG_RANDOM); +#endif + return 0; +} + +CURL_STATIC void Curl_gtls_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ +#if defined(USE_GNUTLS_NETTLE) + struct md5_ctx MD5pw; + md5_init(&MD5pw); + md5_update(&MD5pw, (unsigned int)tmplen, tmp); + md5_digest(&MD5pw, (unsigned int)md5len, md5sum); +#elif defined(USE_GNUTLS) + gcry_md_hd_t MD5pw; + gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); + gcry_md_write(MD5pw, tmp, tmplen); + memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len); + gcry_md_close(MD5pw); +#endif +} + +bool Curl_gtls_cert_status_request(void) +{ +#ifdef HAS_OCSP + return TRUE; +#else + return FALSE; +#endif +} + +#endif /* USE_GNUTLS */ diff --git a/libcurl/src/lib/vtls/gtls.h b/libcurl/src/lib/vtls/gtls.h new file mode 100644 index 0000000..dc98f79 --- /dev/null +++ b/libcurl/src/lib/vtls/gtls.h @@ -0,0 +1,83 @@ +#ifndef HEADER_CURL_GTLS_H +#define HEADER_CURL_GTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "../curl_setup.h" + +#ifdef USE_GNUTLS + +#include "urldata.h" + +CURL_STATIC int Curl_gtls_init(void); +CURL_STATIC int Curl_gtls_cleanup(void); +CURL_STATIC CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex); +CURL_STATIC CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); + + /* close a SSL connection */ +CURL_STATIC void Curl_gtls_close(struct connectdata *conn, int sockindex); + +CURL_STATIC void Curl_gtls_session_free(void *ptr); +CURL_STATIC size_t Curl_gtls_version(char *buffer, size_t size); +CURL_STATIC int Curl_gtls_shutdown(struct connectdata *conn, int sockindex); +CURL_STATIC int Curl_gtls_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length); +CURL_STATIC void Curl_gtls_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); + +bool Curl_gtls_cert_status_request(void); + +/* Set the API backend definition to GnuTLS */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS + +/* this backend supports the CAPATH option */ +#define have_curlssl_ca_path 1 + +/* this backend supports CURLOPT_CERTINFO */ +#define have_curlssl_certinfo 1 + +/* API setup for GnuTLS */ +#define curlssl_init Curl_gtls_init +#define curlssl_cleanup Curl_gtls_cleanup +#define curlssl_connect Curl_gtls_connect +#define curlssl_connect_nonblocking Curl_gtls_connect_nonblocking +#define curlssl_session_free(x) Curl_gtls_session_free(x) +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_gtls_close +#define curlssl_shutdown(x,y) Curl_gtls_shutdown(x,y) +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_gtls_version +#define curlssl_check_cxn(x) ((void)x, -1) +#define curlssl_data_pending(x,y) ((void)x, (void)y, 0) +#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z) +#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d) +#define curlssl_cert_status_request() Curl_gtls_cert_status_request() + +#endif /* USE_GNUTLS */ +#endif /* HEADER_CURL_GTLS_H */ diff --git a/libcurl/src/lib/vtls/nss.c b/libcurl/src/lib/vtls/nss.c new file mode 100644 index 0000000..1c17612 --- /dev/null +++ b/libcurl/src/lib/vtls/nss.c @@ -0,0 +1,2006 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all NSS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +#include "../curl_setup.h" + +#ifdef USE_NSS + +#include "urldata.h" +#include "sendf.h" +#include "formdata.h" /* for the boundary function */ +#include "url.h" /* for the ssl config check function */ +#include "connect.h" +#include "strequal.h" +#include "select.h" +#include "vtls.h" +#include "llist.h" +#include "curl_printf.h" +#include "nssg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH) + +#if NSSVERNUM >= 0x030f00 /* 3.15.0 */ +#include +#endif + +#include "rawstr.h" +#include "warnless.h" +#include "x509asn1.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define SSL_DIR "/etc/pki/nssdb" + +/* enough to fit the string "PEM Token #[0|1]" */ +#define SLOTSIZE 13 + +PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd); + +PRLock * nss_initlock = NULL; +PRLock * nss_crllock = NULL; +struct curl_llist *nss_crl_list = NULL; +NSSInitContext * nss_context = NULL; + +volatile int initialized = 0; + +typedef struct { + const char *name; + int num; +} cipher_s; + +#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \ + CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \ + ptr->type = (_type); \ + ptr->pValue = (_val); \ + ptr->ulValueLen = (_len); \ +} WHILE_FALSE + +#define CERT_NewTempCertificate __CERT_NewTempCertificate + +#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0]) +static const cipher_s cipherlist[] = { + /* SSL2 cipher suites */ + {"rc4", SSL_EN_RC4_128_WITH_MD5}, + {"rc4-md5", SSL_EN_RC4_128_WITH_MD5}, + {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5}, + {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5}, + {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5}, + {"des", SSL_EN_DES_64_CBC_WITH_MD5}, + {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5}, + /* SSL3/TLS cipher suites */ + {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5}, + {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA}, + {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA}, + {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA}, + {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5}, + {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5}, + {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, + {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, + {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA}, + {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, + {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA}, + {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA}, + {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA}, + /* TLS 1.0: Exportable 56-bit Cipher Suites. */ + {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, + {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, + /* AES ciphers. */ + {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, + {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, + {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, + {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, + {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, + {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, + /* ECC ciphers. */ + {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA}, + {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA}, + {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA}, + {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA}, + {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA}, + {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA}, + {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}, + {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, + {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA}, + {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA}, + {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA}, + {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA}, + {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA}, + {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA}, + {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, + {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, + {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA}, + {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA}, + {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA}, + {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA}, +#ifdef TLS_RSA_WITH_NULL_SHA256 + /* new HMAC-SHA256 cipher suites specified in RFC */ + {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256}, + {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256}, + {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256}, + {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256}, + {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256}, + {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, + {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, +#endif +#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256 + /* AES GCM cipher suites in RFC 5288 and RFC 5289 */ + {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256}, + {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, + {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256}, + {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256}, + {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256}, +#endif +}; + +static const char* pem_library = "libnsspem.so"; +SECMODModule* mod = NULL; + +/* NSPR I/O layer we use to detect blocking direction during SSL handshake */ +static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER; +static PRIOMethods nspr_io_methods; + +static const char* nss_error_to_name(PRErrorCode code) +{ + const char *name = PR_ErrorToName(code); + if(name) + return name; + + return "unknown error"; +} + +static void nss_print_error_message(struct SessionHandle *data, PRUint32 err) +{ + failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); +} + +static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model, + char *cipher_list) +{ + unsigned int i; + PRBool cipher_state[NUM_OF_CIPHERS]; + PRBool found; + char *cipher; + + /* First disable all ciphers. This uses a different max value in case + * NSS adds more ciphers later we don't want them available by + * accident + */ + for(i=0; iset.str[cert_kind]; + const char *n; + + if(!is_file(str)) + /* no such file exists, use the string as nickname */ + return strdup(str); + + /* search the last slash; we require at least one slash in a file name */ + n = strrchr(str, '/'); + if(!n) { + infof(data, "warning: certificate file name \"%s\" handled as nickname; " + "please use \"./%s\" to force file name\n", str, str); + return strdup(str); + } + + /* we'll use the PEM reader to read the certificate from file */ + return NULL; +} + +/* Call PK11_CreateGenericObject() with the given obj_class and filename. If + * the call succeeds, append the object handle to the list of objects so that + * the object can be destroyed in Curl_nss_close(). */ +static CURLcode nss_create_object(struct ssl_connect_data *ssl, + CK_OBJECT_CLASS obj_class, + const char *filename, bool cacert) +{ + PK11SlotInfo *slot; + PK11GenericObject *obj; + CK_BBOOL cktrue = CK_TRUE; + CK_BBOOL ckfalse = CK_FALSE; + CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; + int attr_cnt = 0; + CURLcode result = (cacert) + ? CURLE_SSL_CACERT_BADFILE + : CURLE_SSL_CERTPROBLEM; + + const int slot_id = (cacert) ? 0 : 1; + char *slot_name = aprintf("PEM Token #%d", slot_id); + if(!slot_name) + return CURLE_OUT_OF_MEMORY; + + slot = PK11_FindSlotByName(slot_name); + free(slot_name); + if(!slot) + return result; + + PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); + PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); + PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename, + strlen(filename) + 1); + + if(CKO_CERTIFICATE == obj_class) { + CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse); + PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval)); + } + + obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE); + PK11_FreeSlot(slot); + if(!obj) + return result; + + if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) { + PK11_DestroyGenericObject(obj); + return CURLE_OUT_OF_MEMORY; + } + + if(!cacert && CKO_CERTIFICATE == obj_class) + /* store reference to a client certificate */ + ssl->obj_clicert = obj; + + return CURLE_OK; +} + +/* Destroy the NSS object whose handle is given by ptr. This function is + * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy + * NSS objects in Curl_nss_close() */ +static void nss_destroy_object(void *user, void *ptr) +{ + PK11GenericObject *obj = (PK11GenericObject *)ptr; + (void) user; + PK11_DestroyGenericObject(obj); +} + +/* same as nss_destroy_object() but for CRL items */ +static void nss_destroy_crl_item(void *user, void *ptr) +{ + SECItem *crl_der = (SECItem *)ptr; + (void) user; + SECITEM_FreeItem(crl_der, PR_TRUE); +} + +static CURLcode nss_load_cert(struct ssl_connect_data *ssl, + const char *filename, PRBool cacert) +{ + CURLcode result = (cacert) + ? CURLE_SSL_CACERT_BADFILE + : CURLE_SSL_CERTPROBLEM; + + /* libnsspem.so leaks memory if the requested file does not exist. For more + * details, go to . */ + if(is_file(filename)) + result = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert); + + if(!result && !cacert) { + /* we have successfully loaded a client certificate */ + CERTCertificate *cert; + char *nickname = NULL; + char *n = strrchr(filename, '/'); + if(n) + n++; + + /* The following undocumented magic helps to avoid a SIGSEGV on call + * of PK11_ReadRawAttribute() from SelectClientCert() when using an + * immature version of libnsspem.so. For more details, go to + * . */ + nickname = aprintf("PEM Token #1:%s", n); + if(nickname) { + cert = PK11_FindCertFromNickname(nickname, NULL); + if(cert) + CERT_DestroyCertificate(cert); + + free(nickname); + } + } + + return result; +} + +/* add given CRL to cache if it is not already there */ +static CURLcode nss_cache_crl(SECItem *crl_der) +{ + CERTCertDBHandle *db = CERT_GetDefaultCertDB(); + CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0); + if(crl) { + /* CRL already cached */ + SEC_DestroyCrl(crl); + SECITEM_FreeItem(crl_der, PR_TRUE); + return CURLE_OK; + } + + /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */ + PR_Lock(nss_crllock); + + /* store the CRL item so that we can free it in Curl_nss_cleanup() */ + if(!Curl_llist_insert_next(nss_crl_list, nss_crl_list->tail, crl_der)) { + SECITEM_FreeItem(crl_der, PR_TRUE); + PR_Unlock(nss_crllock); + return CURLE_OUT_OF_MEMORY; + } + + if(SECSuccess != CERT_CacheCRL(db, crl_der)) { + /* unable to cache CRL */ + PR_Unlock(nss_crllock); + return CURLE_SSL_CRL_BADFILE; + } + + /* we need to clear session cache, so that the CRL could take effect */ + SSL_ClearSessionCache(); + PR_Unlock(nss_crllock); + return CURLE_OK; +} + +static CURLcode nss_load_crl(const char* crlfilename) +{ + PRFileDesc *infile; + PRFileInfo info; + SECItem filedata = { 0, NULL, 0 }; + SECItem *crl_der = NULL; + char *body; + + infile = PR_Open(crlfilename, PR_RDONLY, 0); + if(!infile) + return CURLE_SSL_CRL_BADFILE; + + if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info)) + goto fail; + + if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1)) + goto fail; + + if(info.size != PR_Read(infile, filedata.data, info.size)) + goto fail; + + crl_der = SECITEM_AllocItem(NULL, NULL, 0U); + if(!crl_der) + goto fail; + + /* place a trailing zero right after the visible data */ + body = (char*)filedata.data; + body[--filedata.len] = '\0'; + + body = strstr(body, "-----BEGIN"); + if(body) { + /* assume ASCII */ + char *trailer; + char *begin = PORT_Strchr(body, '\n'); + if(!begin) + begin = PORT_Strchr(body, '\r'); + if(!begin) + goto fail; + + trailer = strstr(++begin, "-----END"); + if(!trailer) + goto fail; + + /* retrieve DER from ASCII */ + *trailer = '\0'; + if(ATOB_ConvertAsciiToItem(crl_der, begin)) + goto fail; + + SECITEM_FreeItem(&filedata, PR_FALSE); + } + else + /* assume DER */ + *crl_der = filedata; + + PR_Close(infile); + return nss_cache_crl(crl_der); + +fail: + PR_Close(infile); + SECITEM_FreeItem(crl_der, PR_TRUE); + SECITEM_FreeItem(&filedata, PR_FALSE); + return CURLE_SSL_CRL_BADFILE; +} + +static CURLcode nss_load_key(struct connectdata *conn, int sockindex, + char *key_file) +{ + PK11SlotInfo *slot; + SECStatus status; + CURLcode result; + struct ssl_connect_data *ssl = conn->ssl; + + (void)sockindex; /* unused */ + + result = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); + if(result) { + PR_SetError(SEC_ERROR_BAD_KEY, 0); + return result; + } + + slot = PK11_FindSlotByName("PEM Token #1"); + if(!slot) + return CURLE_SSL_CERTPROBLEM; + + /* This will force the token to be seen as re-inserted */ + SECMOD_WaitForAnyTokenEvent(mod, 0, 0); + PK11_IsPresent(slot); + + status = PK11_Authenticate(slot, PR_TRUE, + conn->data->set.str[STRING_KEY_PASSWD]); + PK11_FreeSlot(slot); + + return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; +} + +static int display_error(struct connectdata *conn, PRInt32 err, + const char *filename) +{ + switch(err) { + case SEC_ERROR_BAD_PASSWORD: + failf(conn->data, "Unable to load client key: Incorrect password"); + return 1; + case SEC_ERROR_UNKNOWN_CERT: + failf(conn->data, "Unable to load certificate %s", filename); + return 1; + default: + break; + } + return 0; /* The caller will print a generic error */ +} + +static CURLcode cert_stuff(struct connectdata *conn, int sockindex, + char *cert_file, char *key_file) +{ + struct SessionHandle *data = conn->data; + CURLcode result; + + if(cert_file) { + result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE); + if(result) { + const PRErrorCode err = PR_GetError(); + if(!display_error(conn, err, cert_file)) { + const char *err_name = nss_error_to_name(err); + failf(data, "unable to load client cert: %d (%s)", err, err_name); + } + + return result; + } + } + + if(key_file || (is_file(cert_file))) { + if(key_file) + result = nss_load_key(conn, sockindex, key_file); + else + /* In case the cert file also has the key */ + result = nss_load_key(conn, sockindex, cert_file); + if(result) { + const PRErrorCode err = PR_GetError(); + if(!display_error(conn, err, key_file)) { + const char *err_name = nss_error_to_name(err); + failf(data, "unable to load client key: %d (%s)", err, err_name); + } + + return result; + } + } + + return CURLE_OK; +} + +static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg) +{ + (void)slot; /* unused */ + + if(retry || NULL == arg) + return NULL; + else + return (char *)PORT_Strdup((char *)arg); +} + +/* bypass the default SSL_AuthCertificate() hook in case we do not want to + * verify peer */ +static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, + PRBool isServer) +{ + struct connectdata *conn = (struct connectdata *)arg; + +#ifdef SSL_ENABLE_OCSP_STAPLING + if(conn->data->set.ssl.verifystatus) { + SECStatus cacheResult; + + const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd); + if(!csa) { + failf(conn->data, "Invalid OCSP response"); + return SECFailure; + } + + if(csa->len == 0) { + failf(conn->data, "No OCSP response received"); + return SECFailure; + } + + cacheResult = CERT_CacheOCSPResponseFromSideChannel( + CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd), + PR_Now(), &csa->items[0], arg + ); + + if(cacheResult != SECSuccess) { + failf(conn->data, "Invalid OCSP response"); + return cacheResult; + } + } +#endif + + if(!conn->data->set.ssl.verifypeer) { + infof(conn->data, "skipping SSL peer certificate verification\n"); + return SECSuccess; + } + + return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer); +} + +/** + * Inform the application that the handshake is complete. + */ +static void HandshakeCallback(PRFileDesc *sock, void *arg) +{ + struct connectdata *conn = (struct connectdata*) arg; + unsigned int buflenmax = 50; + unsigned char buf[50]; + unsigned int buflen; + SSLNextProtoState state; + + if(!conn->data->set.ssl_enable_npn && !conn->data->set.ssl_enable_alpn) { + return; + } + + if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) { + + switch(state) { + case SSL_NEXT_PROTO_NO_SUPPORT: + case SSL_NEXT_PROTO_NO_OVERLAP: + infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n"); + return; +#ifdef SSL_ENABLE_ALPN + case SSL_NEXT_PROTO_SELECTED: + infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf); + break; +#endif + case SSL_NEXT_PROTO_NEGOTIATED: + infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf); + break; + } + +#ifdef USE_NGHTTP2 + if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2_0; + } + else +#endif + if(buflen == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } +} + +static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data, + PRBool *canFalseStart) +{ + struct connectdata *conn = client_data; + struct SessionHandle *data = conn->data; + + SSLChannelInfo channelInfo; + SSLCipherSuiteInfo cipherInfo; + + SECStatus rv; + PRBool negotiatedExtension; + + *canFalseStart = PR_FALSE; + + if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess) + return SECFailure; + + if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, + sizeof(cipherInfo)) != SECSuccess) + return SECFailure; + + /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for + * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310 + */ + if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2) + goto end; + + /* Only allow ECDHE key exchange algorithm. + * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */ + if(cipherInfo.keaType != ssl_kea_ecdh) + goto end; + + /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC + * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt + * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */ + if(cipherInfo.symCipher != ssl_calg_aes_gcm) + goto end; + + /* Enforce ALPN or NPN to do False Start, as an indicator of server + * compatibility. */ + rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn, + &negotiatedExtension); + if(rv != SECSuccess || !negotiatedExtension) { + rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn, + &negotiatedExtension); + } + + if(rv != SECSuccess || !negotiatedExtension) + goto end; + + *canFalseStart = PR_TRUE; + + infof(data, "Trying TLS False Start\n"); + +end: + return SECSuccess; +} + +static void display_cert_info(struct SessionHandle *data, + CERTCertificate *cert) +{ + char *subject, *issuer, *common_name; + PRExplodedTime printableTime; + char timeString[256]; + PRTime notBefore, notAfter; + + subject = CERT_NameToAscii(&cert->subject); + issuer = CERT_NameToAscii(&cert->issuer); + common_name = CERT_GetCommonName(&cert->subject); + infof(data, "\tsubject: %s\n", subject); + + CERT_GetCertTimes(cert, ¬Before, ¬After); + PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime); + PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); + infof(data, "\tstart date: %s\n", timeString); + PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime); + PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); + infof(data, "\texpire date: %s\n", timeString); + infof(data, "\tcommon name: %s\n", common_name); + infof(data, "\tissuer: %s\n", issuer); + + PR_Free(subject); + PR_Free(issuer); + PR_Free(common_name); +} + +static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock) +{ + CURLcode result = CURLE_OK; + SSLChannelInfo channel; + SSLCipherSuiteInfo suite; + CERTCertificate *cert; + CERTCertificate *cert2; + CERTCertificate *cert3; + PRTime now; + int i; + + if(SSL_GetChannelInfo(sock, &channel, sizeof channel) == + SECSuccess && channel.length == sizeof channel && + channel.cipherSuite) { + if(SSL_GetCipherSuiteInfo(channel.cipherSuite, + &suite, sizeof suite) == SECSuccess) { + infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName); + } + } + + cert = SSL_PeerCertificate(sock); + if(cert) { + infof(conn->data, "Server certificate:\n"); + + if(!conn->data->set.ssl.certinfo) { + display_cert_info(conn->data, cert); + CERT_DestroyCertificate(cert); + } + else { + /* Count certificates in chain. */ + now = PR_Now(); + i = 1; + if(!cert->isRoot) { + cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); + while(cert2) { + i++; + if(cert2->isRoot) { + CERT_DestroyCertificate(cert2); + break; + } + cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA); + CERT_DestroyCertificate(cert2); + cert2 = cert3; + } + } + + result = Curl_ssl_init_certinfo(conn->data, i); + if(!result) { + for(i = 0; cert; cert = cert2) { + result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data, + (char *)cert->derCert.data + + cert->derCert.len); + if(result) + break; + + if(cert->isRoot) { + CERT_DestroyCertificate(cert); + break; + } + + cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); + CERT_DestroyCertificate(cert); + } + } + } + } + + return result; +} + +static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) +{ + struct connectdata *conn = (struct connectdata *)arg; + struct SessionHandle *data = conn->data; + PRErrorCode err = PR_GetError(); + CERTCertificate *cert; + + /* remember the cert verification result */ + data->set.ssl.certverifyresult = err; + + if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost) + /* we are asked not to verify the host name */ + return SECSuccess; + + /* print only info about the cert, the error is printed off the callback */ + cert = SSL_PeerCertificate(sock); + if(cert) { + infof(data, "Server certificate:\n"); + display_cert_info(data, cert); + CERT_DestroyCertificate(cert); + } + + return SECFailure; +} + +/** + * + * Check that the Peer certificate's issuer certificate matches the one found + * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the + * issuer check, so we provide comments that mimic the OpenSSL + * X509_check_issued function (in x509v3/v3_purp.c) + */ +static SECStatus check_issuer_cert(PRFileDesc *sock, + char *issuer_nickname) +{ + CERTCertificate *cert, *cert_issuer, *issuer; + SECStatus res=SECSuccess; + void *proto_win = NULL; + + /* + PRArenaPool *tmpArena = NULL; + CERTAuthKeyID *authorityKeyID = NULL; + SECITEM *caname = NULL; + */ + + cert = SSL_PeerCertificate(sock); + cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner); + + proto_win = SSL_RevealPinArg(sock); + issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); + + if((!cert_issuer) || (!issuer)) + res = SECFailure; + else if(SECITEM_CompareItem(&cert_issuer->derCert, + &issuer->derCert)!=SECEqual) + res = SECFailure; + + CERT_DestroyCertificate(cert); + CERT_DestroyCertificate(issuer); + CERT_DestroyCertificate(cert_issuer); + return res; +} + +/** + * + * Callback to pick the SSL client certificate. + */ +static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, + struct CERTDistNamesStr *caNames, + struct CERTCertificateStr **pRetCert, + struct SECKEYPrivateKeyStr **pRetKey) +{ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; + struct SessionHandle *data = connssl->data; + const char *nickname = connssl->client_nickname; + + if(connssl->obj_clicert) { + /* use the cert/key provided by PEM reader */ + static const char pem_slotname[] = "PEM Token #1"; + SECItem cert_der = { 0, NULL, 0 }; + void *proto_win = SSL_RevealPinArg(sock); + struct CERTCertificateStr *cert; + struct SECKEYPrivateKeyStr *key; + + PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname); + if(NULL == slot) { + failf(data, "NSS: PK11 slot not found: %s", pem_slotname); + return SECFailure; + } + + if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE, + &cert_der) != SECSuccess) { + failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); + PK11_FreeSlot(slot); + return SECFailure; + } + + cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win); + SECITEM_FreeItem(&cert_der, PR_FALSE); + if(NULL == cert) { + failf(data, "NSS: client certificate from file not found"); + PK11_FreeSlot(slot); + return SECFailure; + } + + key = PK11_FindPrivateKeyFromCert(slot, cert, NULL); + PK11_FreeSlot(slot); + if(NULL == key) { + failf(data, "NSS: private key from file not found"); + CERT_DestroyCertificate(cert); + return SECFailure; + } + + infof(data, "NSS: client certificate from file\n"); + display_cert_info(data, cert); + + *pRetCert = cert; + *pRetKey = key; + return SECSuccess; + } + + /* use the default NSS hook */ + if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, + pRetCert, pRetKey) + || NULL == *pRetCert) { + + if(NULL == nickname) + failf(data, "NSS: client certificate not found (nickname not " + "specified)"); + else + failf(data, "NSS: client certificate not found: %s", nickname); + + return SECFailure; + } + + /* get certificate nickname if any */ + nickname = (*pRetCert)->nickname; + if(NULL == nickname) + nickname = "[unknown]"; + + if(NULL == *pRetKey) { + failf(data, "NSS: private key not found for certificate: %s", nickname); + return SECFailure; + } + + infof(data, "NSS: using client certificate: %s\n", nickname); + display_cert_info(data, *pRetCert); + return SECSuccess; +} + +/* update blocking direction in case of PR_WOULD_BLOCK_ERROR */ +static void nss_update_connecting_state(ssl_connect_state state, void *secret) +{ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret; + if(PR_GetError() != PR_WOULD_BLOCK_ERROR) + /* an unrelated error is passing by */ + return; + + switch(connssl->connecting_state) { + case ssl_connect_2: + case ssl_connect_2_reading: + case ssl_connect_2_writing: + break; + default: + /* we are not called from an SSL handshake */ + return; + } + + /* update the state accordingly */ + connssl->connecting_state = state; +} + +/* recv() wrapper we use to detect blocking direction during SSL handshake */ +static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, + PRIntn flags, PRIntervalTime timeout) +{ + const PRRecvFN recv_fn = fd->lower->methods->recv; + const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout); + if(rv < 0) + /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ + nss_update_connecting_state(ssl_connect_2_reading, fd->secret); + return rv; +} + +/* send() wrapper we use to detect blocking direction during SSL handshake */ +static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, + PRIntn flags, PRIntervalTime timeout) +{ + const PRSendFN send_fn = fd->lower->methods->send; + const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout); + if(rv < 0) + /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ + nss_update_connecting_state(ssl_connect_2_writing, fd->secret); + return rv; +} + +/* close() wrapper to avoid assertion failure due to fd->secret != NULL */ +static PRStatus nspr_io_close(PRFileDesc *fd) +{ + const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close; + fd->secret = NULL; + return close_fn(fd); +} + +/* data might be NULL */ +static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) +{ + NSSInitParameters initparams; + + if(nss_context != NULL) + return CURLE_OK; + + memset((void *) &initparams, '\0', sizeof(initparams)); + initparams.length = sizeof(initparams); + + if(cert_dir) { + char *certpath = aprintf("sql:%s", cert_dir); + if(!certpath) + return CURLE_OUT_OF_MEMORY; + + infof(data, "Initializing NSS with certpath: %s\n", certpath); + nss_context = NSS_InitContext(certpath, "", "", "", &initparams, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); + free(certpath); + + if(nss_context != NULL) + return CURLE_OK; + + infof(data, "Unable to initialize NSS database\n"); + } + + infof(data, "Initializing NSS with certpath: none\n"); + nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY + | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN + | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); + if(nss_context != NULL) + return CURLE_OK; + + infof(data, "Unable to initialize NSS\n"); + return CURLE_SSL_CACERT_BADFILE; +} + +/* data might be NULL */ +static CURLcode nss_init(struct SessionHandle *data) +{ + char *cert_dir; + struct_stat st; + CURLcode result; + + if(initialized) + return CURLE_OK; + + /* list of all CRL items we need to destroy in Curl_nss_cleanup() */ + nss_crl_list = Curl_llist_alloc(nss_destroy_crl_item); + if(!nss_crl_list) + return CURLE_OUT_OF_MEMORY; + + /* First we check if $SSL_DIR points to a valid dir */ + cert_dir = getenv("SSL_DIR"); + if(cert_dir) { + if((stat(cert_dir, &st) != 0) || + (!S_ISDIR(st.st_mode))) { + cert_dir = NULL; + } + } + + /* Now we check if the default location is a valid dir */ + if(!cert_dir) { + if((stat(SSL_DIR, &st) == 0) && + (S_ISDIR(st.st_mode))) { + cert_dir = (char *)SSL_DIR; + } + } + + if(nspr_io_identity == PR_INVALID_IO_LAYER) { + /* allocate an identity for our own NSPR I/O layer */ + nspr_io_identity = PR_GetUniqueIdentity("libcurl"); + if(nspr_io_identity == PR_INVALID_IO_LAYER) + return CURLE_OUT_OF_MEMORY; + + /* the default methods just call down to the lower I/O layer */ + memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods); + + /* override certain methods in the table by our wrappers */ + nspr_io_methods.recv = nspr_io_recv; + nspr_io_methods.send = nspr_io_send; + nspr_io_methods.close = nspr_io_close; + } + + result = nss_init_core(data, cert_dir); + if(result) + return result; + + if(num_enabled_ciphers() == 0) + NSS_SetDomesticPolicy(); + + initialized = 1; + + return CURLE_OK; +} + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +CURL_STATIC int Curl_nss_init(void) +{ + /* curl_global_init() is not thread-safe so this test is ok */ + if(nss_initlock == NULL) { + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256); + nss_initlock = PR_NewLock(); + nss_crllock = PR_NewLock(); + } + + /* We will actually initialize NSS later */ + + return 1; +} + +/* data might be NULL */ +CURL_STATIC CURLcode Curl_nss_force_init(struct SessionHandle *data) +{ + CURLcode result; + if(!nss_initlock) { + if(data) + failf(data, "unable to initialize NSS, curl_global_init() should have " + "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); + return CURLE_FAILED_INIT; + } + + PR_Lock(nss_initlock); + result = nss_init(data); + PR_Unlock(nss_initlock); + + return result; +} + +/* Global cleanup */ +CURL_STATIC void Curl_nss_cleanup(void) +{ + /* This function isn't required to be threadsafe and this is only done + * as a safety feature. + */ + PR_Lock(nss_initlock); + if(initialized) { + /* Free references to client certificates held in the SSL session cache. + * Omitting this hampers destruction of the security module owning + * the certificates. */ + SSL_ClearSessionCache(); + + if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) { + SECMOD_DestroyModule(mod); + mod = NULL; + } + NSS_ShutdownContext(nss_context); + nss_context = NULL; + } + + /* destroy all CRL items */ + Curl_llist_destroy(nss_crl_list, NULL); + nss_crl_list = NULL; + + PR_Unlock(nss_initlock); + + PR_DestroyLock(nss_initlock); + PR_DestroyLock(nss_crllock); + nss_initlock = NULL; + + initialized = 0; +} + +/* + * This function uses SSL_peek to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +CURL_STATIC int +Curl_nss_check_cxn(struct connectdata *conn) +{ + int rc; + char buf; + + rc = + PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK, + PR_SecondsToInterval(1)); + if(rc > 0) + return 1; /* connection still in place */ + + if(rc == 0) + return 0; /* connection has been closed */ + + return -1; /* connection status unknown */ +} + +/* + * This function is called when an SSL connection is closed. + */ +CURL_STATIC void Curl_nss_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->handle) { + /* NSS closes the socket we previously handed to it, so we must mark it + as closed to avoid double close */ + fake_sclose(conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + + if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL)) + /* A server might require different authentication based on the + * particular path being requested by the client. To support this + * scenario, we must ensure that a connection will never reuse the + * authentication data from a previous connection. */ + SSL_InvalidateSession(connssl->handle); + + free(connssl->client_nickname); + connssl->client_nickname = NULL; + /* destroy all NSS objects in order to avoid failure of NSS shutdown */ + Curl_llist_destroy(connssl->obj_list, NULL); + connssl->obj_list = NULL; + connssl->obj_clicert = NULL; + + PR_Close(connssl->handle); + connssl->handle = NULL; + } +} + +/* return true if NSS can provide error code (and possibly msg) for the + error */ +static bool is_nss_error(CURLcode err) +{ + switch(err) { + case CURLE_PEER_FAILED_VERIFICATION: + case CURLE_SSL_CACERT: + case CURLE_SSL_CERTPROBLEM: + case CURLE_SSL_CONNECT_ERROR: + case CURLE_SSL_ISSUER_ERROR: + return true; + + default: + return false; + } +} + +/* return true if the given error code is related to a client certificate */ +static bool is_cc_error(PRInt32 err) +{ + switch(err) { + case SSL_ERROR_BAD_CERT_ALERT: + case SSL_ERROR_EXPIRED_CERT_ALERT: + case SSL_ERROR_REVOKED_CERT_ALERT: + return true; + + default: + return false; + } +} + +static Curl_recv nss_recv; +static Curl_send nss_send; + +static CURLcode nss_load_ca_certificates(struct connectdata *conn, + int sockindex) +{ + struct SessionHandle *data = conn->data; + const char *cafile = data->set.ssl.CAfile; + const char *capath = data->set.ssl.CApath; + + if(cafile) { + CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); + if(result) + return result; + } + + if(capath) { + struct_stat st; + if(stat(capath, &st) == -1) + return CURLE_SSL_CACERT_BADFILE; + + if(S_ISDIR(st.st_mode)) { + PRDirEntry *entry; + PRDir *dir = PR_OpenDir(capath); + if(!dir) + return CURLE_SSL_CACERT_BADFILE; + + while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) { + char *fullpath = aprintf("%s/%s", capath, entry->name); + if(!fullpath) { + PR_CloseDir(dir); + return CURLE_OUT_OF_MEMORY; + } + + if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) + /* This is purposefully tolerant of errors so non-PEM files can + * be in the same directory */ + infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath); + + free(fullpath); + } + + PR_CloseDir(dir); + } + else + infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath); + } + + infof(data, " CAfile: %s\n CApath: %s\n", + cafile ? cafile : "none", + capath ? capath : "none"); + + return CURLE_OK; +} + +static CURLcode nss_init_sslver(SSLVersionRange *sslver, + struct SessionHandle *data) +{ + switch(data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; +#ifdef SSL_LIBRARY_VERSION_TLS_1_2 + sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; +#elif defined SSL_LIBRARY_VERSION_TLS_1_1 + sslver->max = SSL_LIBRARY_VERSION_TLS_1_1; +#else + sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; +#endif + return CURLE_OK; + + case CURL_SSLVERSION_SSLv2: + sslver->min = SSL_LIBRARY_VERSION_2; + sslver->max = SSL_LIBRARY_VERSION_2; + return CURLE_OK; + + case CURL_SSLVERSION_SSLv3: + sslver->min = SSL_LIBRARY_VERSION_3_0; + sslver->max = SSL_LIBRARY_VERSION_3_0; + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1_0: + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1_1: +#ifdef SSL_LIBRARY_VERSION_TLS_1_1 + sslver->min = SSL_LIBRARY_VERSION_TLS_1_1; + sslver->max = SSL_LIBRARY_VERSION_TLS_1_1; + return CURLE_OK; +#endif + break; + + case CURL_SSLVERSION_TLSv1_2: +#ifdef SSL_LIBRARY_VERSION_TLS_1_2 + sslver->min = SSL_LIBRARY_VERSION_TLS_1_2; + sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; + return CURLE_OK; +#endif + break; + } + + failf(data, "TLS minor version cannot be set"); + return CURLE_SSL_CONNECT_ERROR; +} + +static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, + struct SessionHandle *data, + CURLcode curlerr) +{ + PRErrorCode err = 0; + + if(is_nss_error(curlerr)) { + /* read NSPR error code */ + err = PR_GetError(); + if(is_cc_error(err)) + curlerr = CURLE_SSL_CERTPROBLEM; + + /* print the error number and error string */ + infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(data, err); + } + + /* cleanup on connection failure */ + Curl_llist_destroy(connssl->obj_list, NULL); + connssl->obj_list = NULL; + + return curlerr; +} + +/* Switch the SSL socket into non-blocking mode. */ +static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl, + struct SessionHandle *data) +{ + static PRSocketOptionData sock_opt; + sock_opt.option = PR_SockOpt_Nonblocking; + sock_opt.value.non_blocking = PR_TRUE; + + if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS) + return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); + + return CURLE_OK; +} + +static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) +{ + PRFileDesc *model = NULL; + PRFileDesc *nspr_io = NULL; + PRFileDesc *nspr_io_stub = NULL; + PRBool ssl_no_cache; + PRBool ssl_cbc_random_iv; + struct SessionHandle *data = conn->data; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CURLcode result; + + SSLVersionRange sslver = { + SSL_LIBRARY_VERSION_TLS_1_0, /* min */ + SSL_LIBRARY_VERSION_TLS_1_0 /* max */ + }; + + connssl->data = data; + + /* list of all NSS objects we need to destroy in Curl_nss_close() */ + connssl->obj_list = Curl_llist_alloc(nss_destroy_object); + if(!connssl->obj_list) + return CURLE_OUT_OF_MEMORY; + + /* FIXME. NSS doesn't support multiple databases open at the same time. */ + PR_Lock(nss_initlock); + result = nss_init(conn->data); + if(result) { + PR_Unlock(nss_initlock); + goto error; + } + + result = CURLE_SSL_CONNECT_ERROR; + + if(!mod) { + char *configstring = aprintf("library=%s name=PEM", pem_library); + if(!configstring) { + PR_Unlock(nss_initlock); + goto error; + } + mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE); + free(configstring); + + if(!mod || !mod->loaded) { + if(mod) { + SECMOD_DestroyModule(mod); + mod = NULL; + } + infof(data, "WARNING: failed to load NSS PEM library %s. Using " + "OpenSSL PEM certificates will not work.\n", pem_library); + } + } + + PK11_SetPasswordFunc(nss_get_password); + PR_Unlock(nss_initlock); + + model = PR_NewTCPSocket(); + if(!model) + goto error; + model = SSL_ImportFD(NULL, model); + + if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess) + goto error; + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess) + goto error; + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess) + goto error; + + /* do not use SSL cache if disabled or we are not going to verify peer */ + ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ? + PR_FALSE : PR_TRUE; + if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) + goto error; + + /* enable/disable the requested SSL version(s) */ + if(nss_init_sslver(&sslver, data) != CURLE_OK) + goto error; + if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) + goto error; + + ssl_cbc_random_iv = !data->set.ssl_enable_beast; +#ifdef SSL_CBC_RANDOM_IV + /* unless the user explicitly asks to allow the protocol vulnerability, we + use the work-around */ + if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess) + infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n", + ssl_cbc_random_iv); +#else + if(ssl_cbc_random_iv) + infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n"); +#endif + + if(data->set.ssl.cipher_list) { + if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) { + result = CURLE_SSL_CIPHER; + goto error; + } + } + + if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost) + infof(data, "warning: ignoring value of ssl.verifyhost\n"); + + /* bypass the default SSL_AuthCertificate() hook in case we do not want to + * verify peer */ + if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess) + goto error; + + data->set.ssl.certverifyresult=0; /* not checked yet */ + if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess) + goto error; + + if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess) + goto error; + + if(data->set.ssl.verifypeer) { + const CURLcode rv = nss_load_ca_certificates(conn, sockindex); + if(rv) { + result = rv; + goto error; + } + } + + if(data->set.ssl.CRLfile) { + const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile); + if(rv) { + result = rv; + goto error; + } + infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile); + } + + if(data->set.str[STRING_CERT]) { + char *nickname = dup_nickname(data, STRING_CERT); + if(nickname) { + /* we are not going to use libnsspem.so to read the client cert */ + connssl->obj_clicert = NULL; + } + else { + CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT], + data->set.str[STRING_KEY]); + if(rv) { + /* failf() is already done in cert_stuff() */ + result = rv; + goto error; + } + } + + /* store the nickname for SelectClientCert() called during handshake */ + connssl->client_nickname = nickname; + } + else + connssl->client_nickname = NULL; + + if(SSL_GetClientAuthDataHook(model, SelectClientCert, + (void *)connssl) != SECSuccess) { + result = CURLE_SSL_CERTPROBLEM; + goto error; + } + + /* wrap OS file descriptor by NSPR's file descriptor abstraction */ + nspr_io = PR_ImportTCPSocket(sockfd); + if(!nspr_io) + goto error; + + /* create our own NSPR I/O layer */ + nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods); + if(!nspr_io_stub) { + PR_Close(nspr_io); + goto error; + } + + /* make the per-connection data accessible from NSPR I/O callbacks */ + nspr_io_stub->secret = (void *)connssl; + + /* push our new layer to the NSPR I/O stack */ + if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) { + PR_Close(nspr_io); + PR_Close(nspr_io_stub); + goto error; + } + + /* import our model socket onto the current I/O stack */ + connssl->handle = SSL_ImportFD(model, nspr_io); + if(!connssl->handle) { + PR_Close(nspr_io); + goto error; + } + + PR_Close(model); /* We don't need this any more */ + model = NULL; + + /* This is the password associated with the cert that we're using */ + if(data->set.str[STRING_KEY_PASSWD]) { + SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]); + } + +#ifdef SSL_ENABLE_OCSP_STAPLING + if(data->set.ssl.verifystatus) { + if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) + != SECSuccess) + goto error; + } +#endif + +#ifdef SSL_ENABLE_NPN + if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, data->set.ssl_enable_npn + ? PR_TRUE : PR_FALSE) != SECSuccess) + goto error; +#endif + +#ifdef SSL_ENABLE_ALPN + if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, data->set.ssl_enable_alpn + ? PR_TRUE : PR_FALSE) != SECSuccess) + goto error; +#endif + +#ifdef SSL_ENABLE_FALSE_START + if(data->set.ssl.falsestart) { + if(SSL_OptionSet(connssl->handle, SSL_ENABLE_FALSE_START, PR_TRUE) + != SECSuccess) + goto error; + + if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback, + conn) != SECSuccess) + goto error; + } +#endif + +#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) + if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) { + int cur = 0; + unsigned char protocols[128]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN); + cur += NGHTTP2_PROTO_VERSION_ID_LEN; + } +#endif + protocols[cur++] = ALPN_HTTP_1_1_LENGTH; + memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + cur += ALPN_HTTP_1_1_LENGTH; + + if(SSL_SetNextProtoNego(connssl->handle, protocols, cur) != SECSuccess) + goto error; + } +#endif + + + /* Force handshake on next I/O */ + SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE); + + SSL_SetURL(connssl->handle, conn->host.name); + + return CURLE_OK; + +error: + if(model) + PR_Close(model); + + return nss_fail_connect(connssl, data, result); +} + +static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; + CURLcode result = CURLE_SSL_CONNECT_ERROR; + PRUint32 timeout; + + /* check timeout situation */ + const long time_left = Curl_timeleft(data, NULL, TRUE); + if(time_left < 0L) { + failf(data, "timed out before SSL handshake"); + result = CURLE_OPERATION_TIMEDOUT; + goto error; + } + + /* Force the handshake now */ + timeout = PR_MillisecondsToInterval((PRUint32) time_left); + if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) { + if(PR_GetError() == PR_WOULD_BLOCK_ERROR) + /* blocking direction is updated by nss_update_connecting_state() */ + return CURLE_AGAIN; + else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) + result = CURLE_PEER_FAILED_VERIFICATION; + else if(conn->data->set.ssl.certverifyresult!=0) + result = CURLE_SSL_CACERT; + goto error; + } + + result = display_conn_info(conn, connssl->handle); + if(result) + goto error; + + if(data->set.str[STRING_SSL_ISSUERCERT]) { + SECStatus ret = SECFailure; + char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT); + if(nickname) { + /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */ + ret = check_issuer_cert(connssl->handle, nickname); + free(nickname); + } + + if(SECFailure == ret) { + infof(data, "SSL certificate issuer check failed\n"); + result = CURLE_SSL_ISSUER_ERROR; + goto error; + } + else { + infof(data, "SSL certificate issuer check ok\n"); + } + } + + return CURLE_OK; + +error: + return nss_fail_connect(connssl, data, result); +} + +static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, + bool *done) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; + const bool blocking = (done == NULL); + CURLcode result; + + if(connssl->state == ssl_connection_complete) + return CURLE_OK; + + if(connssl->connecting_state == ssl_connect_1) { + result = nss_setup_connect(conn, sockindex); + if(result) + /* we do not expect CURLE_AGAIN from nss_setup_connect() */ + return result; + + if(!blocking) { + /* in non-blocking mode, set NSS non-blocking mode before handshake */ + result = nss_set_nonblock(connssl, data); + if(result) + return result; + } + + connssl->connecting_state = ssl_connect_2; + } + + result = nss_do_connect(conn, sockindex); + switch(result) { + case CURLE_OK: + break; + case CURLE_AGAIN: + if(!blocking) + /* CURLE_AGAIN in non-blocking mode is not an error */ + return CURLE_OK; + /* fall through */ + default: + return result; + } + + if(blocking) { + /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */ + result = nss_set_nonblock(connssl, data); + if(result) + return result; + } + else + /* signal completed SSL handshake */ + *done = TRUE; + + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = nss_recv; + conn->send[sockindex] = nss_send; + + /* ssl_connect_done is never used outside, go back to the initial state */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) +{ + return nss_connect_common(conn, sockindex, /* blocking */ NULL); +} + +CURL_STATIC CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return nss_connect_common(conn, sockindex, done); +} + +static ssize_t nss_send(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + const void *mem, /* send this data */ + size_t len, /* amount to write */ + CURLcode *curlcode) +{ + ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, + PR_INTERVAL_NO_WAIT); + if(rc < 0) { + PRInt32 err = PR_GetError(); + if(err == PR_WOULD_BLOCK_ERROR) + *curlcode = CURLE_AGAIN; + else { + /* print the error number and error string */ + const char *err_name = nss_error_to_name(err); + infof(conn->data, "SSL write: error %d (%s)\n", err, err_name); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(conn->data, err); + + *curlcode = (is_cc_error(err)) + ? CURLE_SSL_CERTPROBLEM + : CURLE_SEND_ERROR; + } + + return -1; + } + + return rc; /* number of bytes */ +} + +static ssize_t nss_recv(struct connectdata * conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, + PR_INTERVAL_NO_WAIT); + if(nread < 0) { + /* failed SSL read */ + PRInt32 err = PR_GetError(); + + if(err == PR_WOULD_BLOCK_ERROR) + *curlcode = CURLE_AGAIN; + else { + /* print the error number and error string */ + const char *err_name = nss_error_to_name(err); + infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(conn->data, err); + + *curlcode = (is_cc_error(err)) + ? CURLE_SSL_CERTPROBLEM + : CURLE_RECV_ERROR; + } + + return -1; + } + + return nread; +} + +CURL_STATIC size_t Curl_nss_version(char *buffer, size_t size) +{ + return snprintf(buffer, size, "NSS/%s", NSS_VERSION); +} + +/* data might be NULL */ +CURL_STATIC int Curl_nss_seed(struct SessionHandle *data) +{ + /* make sure that NSS is initialized */ + return !!Curl_nss_force_init(data); +} + +/* data might be NULL */ +CURL_STATIC int Curl_nss_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length) +{ + Curl_nss_seed(data); /* Initiate the seed if not already done */ + + if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) + /* signal a failure */ + return -1; + + return 0; +} + +CURL_STATIC void Curl_nss_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); + unsigned int MD5out; + + PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen)); + PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len)); + PK11_DestroyContext(MD5pw, PR_TRUE); +} + +CURL_STATIC bool Curl_nss_cert_status_request(void) +{ +#ifdef SSL_ENABLE_OCSP_STAPLING + return TRUE; +#else + return FALSE; +#endif +} + +CURL_STATIC bool Curl_nss_false_start(void) { +#ifdef SSL_ENABLE_FALSE_START + return TRUE; +#else + return FALSE; +#endif +} + +#endif /* USE_NSS */ diff --git a/libcurl/src/lib/vtls/nssg.h b/libcurl/src/lib/vtls/nssg.h new file mode 100644 index 0000000..7eba897 --- /dev/null +++ b/libcurl/src/lib/vtls/nssg.h @@ -0,0 +1,96 @@ +#ifndef HEADER_CURL_NSSG_H +#define HEADER_CURL_NSSG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "../curl_setup.h" + +#ifdef USE_NSS +/* + * This header should only be needed to get included by vtls.c and nss.c + */ + +#include "urldata.h" + +CURL_STATIC CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex); +CURL_STATIC CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +/* close a SSL connection */ +CURL_STATIC void Curl_nss_close(struct connectdata *conn, int sockindex); + +CURL_STATIC int Curl_nss_init(void); +CURL_STATIC void Curl_nss_cleanup(void); + +CURL_STATIC size_t Curl_nss_version(char *buffer, size_t size); +CURL_STATIC int Curl_nss_check_cxn(struct connectdata *cxn); +CURL_STATIC int Curl_nss_seed(struct SessionHandle *data); + +/* initialize NSS library if not already */ +CURL_STATIC CURLcode Curl_nss_force_init(struct SessionHandle *data); + +CURL_STATIC int Curl_nss_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length); + +CURL_STATIC void Curl_nss_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); + +CURL_STATIC bool Curl_nss_cert_status_request(void); + +CURL_STATIC bool Curl_nss_false_start(void); + +/* Set the API backend definition to NSS */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS + +/* this backend supports the CAPATH option */ +#define have_curlssl_ca_path 1 + +/* this backend supports CURLOPT_CERTINFO */ +#define have_curlssl_certinfo 1 + +/* API setup for NSS */ +#define curlssl_init Curl_nss_init +#define curlssl_cleanup Curl_nss_cleanup +#define curlssl_connect Curl_nss_connect +#define curlssl_connect_nonblocking Curl_nss_connect_nonblocking + +/* NSS has its own session ID cache */ +#define curlssl_session_free(x) Curl_nop_stmt +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_nss_close +/* NSS has no shutdown function provided and thus always fail */ +#define curlssl_shutdown(x,y) ((void)x, (void)y, 1) +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_nss_version +#define curlssl_check_cxn(x) Curl_nss_check_cxn(x) +#define curlssl_data_pending(x,y) ((void)x, (void)y, 0) +#define curlssl_random(x,y,z) Curl_nss_random(x,y,z) +#define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d) +#define curlssl_cert_status_request() Curl_nss_cert_status_request() +#define curlssl_false_start() Curl_nss_false_start() + +#endif /* USE_NSS */ +#endif /* HEADER_CURL_NSSG_H */ diff --git a/libcurl/src/lib/vtls/openssl.c b/libcurl/src/lib/vtls/openssl.c new file mode 100644 index 0000000..a5e6b98 --- /dev/null +++ b/libcurl/src/lib/vtls/openssl.c @@ -0,0 +1,3226 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +/* + * The original SSLeay-using code for curl was written by Linas Vepstas and + * Sampo Kellomaki 1998. + */ + +#include "../curl_setup.h" + +#ifdef USE_OPENSSL + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include "../urldata.h" +#include "../sendf.h" +#include "../formdata.h" /* for the boundary function */ +#include "../url.h" /* for the ssl config check function */ +#include "../inet_pton.h" +#include "openssl.h" +#include "../connect.h" +#include "../slist.h" +#include "../strequal.h" +#include "../select.h" +#include "vtls.h" +#include "../rawstr.h" +#include "../hostcheck.h" +#include "../curl_printf.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_OPENSSL_PKCS12_H +#include +#endif + +#ifndef HAVE_BORINGSSL +#include +#endif + +#include "warnless.h" +#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */ + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef OPENSSL_VERSION_NUMBER +#error "OPENSSL_VERSION_NUMBER not defined" +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x0090581fL +#define HAVE_SSL_GET1_SESSION 1 +#else +#undef HAVE_SSL_GET1_SESSION +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00904100L +#define HAVE_USERDATA_IN_PWD_CALLBACK 1 +#else +#undef HAVE_USERDATA_IN_PWD_CALLBACK +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00907001L && !defined(OPENSSL_IS_BORINGSSL) +/* ENGINE_load_private_key() takes four arguments */ +#define HAVE_ENGINE_LOAD_FOUR_ARGS +#include +#else +/* ENGINE_load_private_key() takes three arguments */ +#undef HAVE_ENGINE_LOAD_FOUR_ARGS +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x00903001L) && \ + defined(HAVE_OPENSSL_PKCS12_H) && \ + !defined(OPENSSL_IS_BORINGSSL) +/* OpenSSL has PKCS 12 support, BoringSSL does not */ +#define HAVE_PKCS12_SUPPORT +#else +/* OpenSSL does not have PKCS12 support */ +#undef HAVE_PKCS12_SUPPORT +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00906001L +#define HAVE_ERR_ERROR_STRING_N 1 +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00909000L +#define SSL_METHOD_QUAL const +#else +#define SSL_METHOD_QUAL +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00907000L +/* 0.9.6 didn't have X509_STORE_set_flags() */ +#define HAVE_X509_STORE_SET_FLAGS 1 +#else +#define X509_STORE_set_flags(x,y) Curl_nop_stmt +#endif + +#ifdef OPENSSL_IS_BORINGSSL +/* BoringSSL has no ERR_remove_state() */ +#define ERR_remove_state(x) +#elif (OPENSSL_VERSION_NUMBER >= 0x10000000L) +#define HAVE_ERR_REMOVE_THREAD_STATE 1 +#endif + +#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \ + OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0+ has no SSLv2 */ +#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */ +#define OPENSSL_NO_SSL2 +#endif + +#if defined(OPENSSL_IS_BORINGSSL) +#define NO_RAND_SEED 1 +/* In BoringSSL OpenSSL_add_all_algorithms does nothing */ +#define OpenSSL_add_all_algorithms() +/* BoringSSL does not have CONF_modules_load_file */ +#define CONF_modules_load_file(a,b,c) +#endif + +/* + * Number of bytes to read from the random number seed file. This must be + * a finite value (because some entropy "files" like /dev/urandom have + * an infinite length), but must be large enough to provide enough + * entopy to properly seed OpenSSL's PRNG. + */ +#define RAND_LOAD_LENGTH 1024 + +#ifndef HAVE_USERDATA_IN_PWD_CALLBACK +static char global_passwd[64]; +#endif + +static int passwd_callback(char *buf, int num, int encrypting +#ifdef HAVE_USERDATA_IN_PWD_CALLBACK + /* This was introduced in 0.9.4, we can set this + using SSL_CTX_set_default_passwd_cb_userdata() + */ + , void *global_passwd +#endif + ) +{ + DEBUGASSERT(0 == encrypting); + + if(!encrypting) { + int klen = curlx_uztosi(strlen((char *)global_passwd)); + if(num > klen) { + memcpy(buf, global_passwd, klen+1); + return klen; + } + } + return 0; +} + +/* + * rand_enough() is a function that returns TRUE if we have seeded the random + * engine properly. We use some preprocessor magic to provide a seed_enough() + * macro to use, just to prevent a compiler warning on this function if we + * pass in an argument that is never used. + */ + +#ifndef NO_RAND_SEED +#ifdef HAVE_RAND_STATUS +#define seed_enough(x) rand_enough() +static bool rand_enough(void) +{ + return (0 != RAND_status()) ? TRUE : FALSE; +} +#else +#define seed_enough(x) rand_enough(x) +static bool rand_enough(int nread) +{ + /* this is a very silly decision to make */ + return (nread > 500) ? TRUE : FALSE; +} +#endif + +static int ossl_seed(struct SessionHandle *data) +{ + char *buf = data->state.buffer; /* point to the big buffer */ + int nread=0; + + /* Q: should we add support for a random file name as a libcurl option? + A: Yes, it is here */ + +#ifndef RANDOM_FILE + /* if RANDOM_FILE isn't defined, we only perform this if an option tells + us to! */ + if(data->set.ssl.random_file) +#define RANDOM_FILE "" /* doesn't matter won't be used */ +#endif + { + /* let the option override the define */ + nread += RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]? + data->set.str[STRING_SSL_RANDOM_FILE]: + RANDOM_FILE), + RAND_LOAD_LENGTH); + if(seed_enough(nread)) + return nread; + } + +#if defined(HAVE_RAND_EGD) + /* only available in OpenSSL 0.9.5 and later */ + /* EGD_SOCKET is set at configure time or not at all */ +#ifndef EGD_SOCKET + /* If we don't have the define set, we only do this if the egd-option + is set */ + if(data->set.str[STRING_SSL_EGDSOCKET]) +#define EGD_SOCKET "" /* doesn't matter won't be used */ +#endif + { + /* If there's an option and a define, the option overrides the + define */ + int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]? + data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET); + if(-1 != ret) { + nread += ret; + if(seed_enough(nread)) + return nread; + } + } +#endif + + /* If we get here, it means we need to seed the PRNG using a "silly" + approach! */ + do { + unsigned char randb[64]; + int len = sizeof(randb); + RAND_bytes(randb, len); + RAND_add(randb, len, (len >> 1)); + } while(!RAND_status()); + + /* generates a default path for the random seed file */ + buf[0]=0; /* blank it first */ + RAND_file_name(buf, BUFSIZE); + if(buf[0]) { + /* we got a file name to try */ + nread += RAND_load_file(buf, RAND_LOAD_LENGTH); + if(seed_enough(nread)) + return nread; + } + + infof(data, "libcurl is now using a weak random seed!\n"); + return nread; +} + +static void Curl_ossl_seed(struct SessionHandle *data) +{ + /* we have the "SSL is seeded" boolean static to prevent multiple + time-consuming seedings in vain */ + static bool ssl_seeded = FALSE; + + if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || + data->set.str[STRING_SSL_EGDSOCKET]) { + ossl_seed(data); + ssl_seeded = TRUE; + } +} +#else +/* BoringSSL needs no seeding */ +#define Curl_ossl_seed(x) +#endif + + +#ifndef SSL_FILETYPE_ENGINE +#define SSL_FILETYPE_ENGINE 42 +#endif +#ifndef SSL_FILETYPE_PKCS12 +#define SSL_FILETYPE_PKCS12 43 +#endif +static int do_file_type(const char *type) +{ + if(!type || !type[0]) + return SSL_FILETYPE_PEM; + if(Curl_raw_equal(type, "PEM")) + return SSL_FILETYPE_PEM; + if(Curl_raw_equal(type, "DER")) + return SSL_FILETYPE_ASN1; + if(Curl_raw_equal(type, "ENG")) + return SSL_FILETYPE_ENGINE; + if(Curl_raw_equal(type, "P12")) + return SSL_FILETYPE_PKCS12; + return -1; +} + +#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_LOAD_FOUR_ARGS) +/* + * Supply default password to the engine user interface conversation. + * The password is passed by OpenSSL engine from ENGINE_load_private_key() + * last argument to the ui and can be obtained by UI_get0_user_data(ui) here. + */ +static int ssl_ui_reader(UI *ui, UI_STRING *uis) +{ + const char *password; + switch(UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + password = (const char*)UI_get0_user_data(ui); + if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { + UI_set_result(ui, uis, password); + return 1; + } + default: + break; + } + return (UI_method_get_reader(UI_OpenSSL()))(ui, uis); +} + +/* + * Suppress interactive request for a default password if available. + */ +static int ssl_ui_writer(UI *ui, UI_STRING *uis) +{ + switch(UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + if(UI_get0_user_data(ui) && + (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { + return 1; + } + default: + break; + } + return (UI_method_get_writer(UI_OpenSSL()))(ui, uis); +} +#endif + +static +int cert_stuff(struct connectdata *conn, + SSL_CTX* ctx, + char *cert_file, + const char *cert_type, + char *key_file, + const char *key_type) +{ + struct SessionHandle *data = conn->data; + + int file_type = do_file_type(cert_type); + + if(cert_file || (file_type == SSL_FILETYPE_ENGINE)) { + SSL *ssl; + X509 *x509; + int cert_done = 0; + + if(data->set.str[STRING_KEY_PASSWD]) { +#ifndef HAVE_USERDATA_IN_PWD_CALLBACK + /* + * If password has been given, we store that in the global + * area (*shudder*) for a while: + */ + size_t len = strlen(data->set.str[STRING_KEY_PASSWD]); + if(len < sizeof(global_passwd)) + memcpy(global_passwd, data->set.str[STRING_KEY_PASSWD], len+1); + else + global_passwd[0] = '\0'; +#else + /* + * We set the password in the callback userdata + */ + SSL_CTX_set_default_passwd_cb_userdata(ctx, + data->set.str[STRING_KEY_PASSWD]); +#endif + /* Set passwd callback: */ + SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); + } + + + switch(file_type) { + case SSL_FILETYPE_PEM: + /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ + if(SSL_CTX_use_certificate_chain_file(ctx, + cert_file) != 1) { + failf(data, + "could not load PEM client certificate, OpenSSL error %s, " + "(no key found, wrong pass phrase, or wrong file format?)", + ERR_error_string(ERR_get_error(), NULL) ); + return 0; + } + break; + + case SSL_FILETYPE_ASN1: + /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but + we use the case above for PEM so this can only be performed with + ASN1 files. */ + if(SSL_CTX_use_certificate_file(ctx, + cert_file, + file_type) != 1) { + failf(data, + "could not load ASN1 client certificate, OpenSSL error %s, " + "(no key found, wrong pass phrase, or wrong file format?)", + ERR_error_string(ERR_get_error(), NULL) ); + return 0; + } + break; + case SSL_FILETYPE_ENGINE: +#if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME) + { + if(data->state.engine) { + const char *cmd_name = "LOAD_CERT_CTRL"; + struct { + const char *cert_id; + X509 *cert; + } params; + + params.cert_id = cert_file; + params.cert = NULL; + + /* Does the engine supports LOAD_CERT_CTRL ? */ + if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME, + 0, (void *)cmd_name, NULL)) { + failf(data, "ssl engine does not support loading certificates"); + return 0; + } + + /* Load the certificate from the engine */ + if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name, + 0, ¶ms, NULL, 1)) { + failf(data, "ssl engine cannot load client cert with id" + " '%s' [%s]", cert_file, + ERR_error_string(ERR_get_error(), NULL)); + return 0; + } + + if(!params.cert) { + failf(data, "ssl engine didn't initialized the certificate " + "properly."); + return 0; + } + + if(SSL_CTX_use_certificate(ctx, params.cert) != 1) { + failf(data, "unable to set client certificate"); + X509_free(params.cert); + return 0; + } + X509_free(params.cert); /* we don't need the handle any more... */ + } + else { + failf(data, "crypto engine not set, can't load certificate"); + return 0; + } + } + break; +#else + failf(data, "file type ENG for certificate not implemented"); + return 0; +#endif + + case SSL_FILETYPE_PKCS12: + { +#ifdef HAVE_PKCS12_SUPPORT + FILE *f; + PKCS12 *p12; + EVP_PKEY *pri; + STACK_OF(X509) *ca = NULL; + int i; + + f = fopen(cert_file, "rb"); + if(!f) { + failf(data, "could not open PKCS12 file '%s'", cert_file); + return 0; + } + p12 = d2i_PKCS12_fp(f, NULL); + fclose(f); + + if(!p12) { + failf(data, "error reading PKCS12 file '%s'", cert_file); + return 0; + } + + PKCS12_PBE_add(); + + if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509, + &ca)) { + failf(data, + "could not parse PKCS12 file, check password, OpenSSL error %s", + ERR_error_string(ERR_get_error(), NULL) ); + PKCS12_free(p12); + return 0; + } + + PKCS12_free(p12); + + if(SSL_CTX_use_certificate(ctx, x509) != 1) { + failf(data, + "could not load PKCS12 client certificate, OpenSSL error %s", + ERR_error_string(ERR_get_error(), NULL) ); + goto fail; + } + + if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { + failf(data, "unable to use private key from PKCS12 file '%s'", + cert_file); + goto fail; + } + + if(!SSL_CTX_check_private_key (ctx)) { + failf(data, "private key from PKCS12 file '%s' " + "does not match certificate in same file", cert_file); + goto fail; + } + /* Set Certificate Verification chain */ + if(ca && sk_X509_num(ca)) { + for(i = 0; i < sk_X509_num(ca); i++) { + /* + * Note that sk_X509_pop() is used below to make sure the cert is + * removed from the stack properly before getting passed to + * SSL_CTX_add_extra_chain_cert(). Previously we used + * sk_X509_value() instead, but then we'd clean it in the subsequent + * sk_X509_pop_free() call. + */ + X509 *x = sk_X509_pop(ca); + if(!SSL_CTX_add_extra_chain_cert(ctx, x)) { + failf(data, "cannot add certificate to certificate chain"); + goto fail; + } + /* SSL_CTX_add_client_CA() seems to work with either sk_* function, + * presumably because it duplicates what we pass to it. + */ + if(!SSL_CTX_add_client_CA(ctx, x)) { + failf(data, "cannot add certificate to client CA list"); + goto fail; + } + } + } + + cert_done = 1; + fail: + EVP_PKEY_free(pri); + X509_free(x509); + sk_X509_pop_free(ca, X509_free); + + if(!cert_done) + return 0; /* failure! */ + break; +#else + failf(data, "file type P12 for certificate not supported"); + return 0; +#endif + } + default: + failf(data, "not supported file type '%s' for certificate", cert_type); + return 0; + } + + file_type = do_file_type(key_type); + + switch(file_type) { + case SSL_FILETYPE_PEM: + if(cert_done) + break; + if(!key_file) + /* cert & key can only be in PEM case in the same file */ + key_file=cert_file; + case SSL_FILETYPE_ASN1: + if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { + failf(data, "unable to set private key file: '%s' type %s", + key_file, key_type?key_type:"PEM"); + return 0; + } + break; + case SSL_FILETYPE_ENGINE: +#ifdef HAVE_OPENSSL_ENGINE_H + { /* XXXX still needs some work */ + EVP_PKEY *priv_key = NULL; + if(data->state.engine) { +#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS + UI_METHOD *ui_method = + UI_create_method((char *)"cURL user interface"); + if(!ui_method) { + failf(data, "unable do create OpenSSL user-interface method"); + return 0; + } + UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL())); + UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL())); + UI_method_set_reader(ui_method, ssl_ui_reader); + UI_method_set_writer(ui_method, ssl_ui_writer); +#endif + /* the typecast below was added to please mingw32 */ + priv_key = (EVP_PKEY *) + ENGINE_load_private_key(data->state.engine, key_file, +#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS + ui_method, +#endif + data->set.str[STRING_KEY_PASSWD]); +#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS + UI_destroy_method(ui_method); +#endif + if(!priv_key) { + failf(data, "failed to load private key from crypto engine"); + return 0; + } + if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { + failf(data, "unable to set private key"); + EVP_PKEY_free(priv_key); + return 0; + } + EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ + } + else { + failf(data, "crypto engine not set, can't load private key"); + return 0; + } + } + break; +#else + failf(data, "file type ENG for private key not supported"); + return 0; +#endif + case SSL_FILETYPE_PKCS12: + if(!cert_done) { + failf(data, "file type P12 for private key not supported"); + return 0; + } + break; + default: + failf(data, "not supported file type for private key"); + return 0; + } + + ssl=SSL_new(ctx); + if(!ssl) { + failf(data, "unable to create an SSL structure"); + return 0; + } + + x509=SSL_get_certificate(ssl); + + /* This version was provided by Evan Jordan and is supposed to not + leak memory as the previous version: */ + if(x509) { + EVP_PKEY *pktmp = X509_get_pubkey(x509); + EVP_PKEY_copy_parameters(pktmp, SSL_get_privatekey(ssl)); + EVP_PKEY_free(pktmp); + } + + SSL_free(ssl); + + /* If we are using DSA, we can copy the parameters from + * the private key */ + + + /* Now we know that a key and cert have been set against + * the SSL context */ + if(!SSL_CTX_check_private_key(ctx)) { + failf(data, "Private key does not match the certificate public key"); + return 0; + } +#ifndef HAVE_USERDATA_IN_PWD_CALLBACK + /* erase it now */ + memset(global_passwd, 0, sizeof(global_passwd)); +#endif + } + return 1; +} + +/* returns non-zero on failure */ +static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) +{ +#if 0 + return X509_NAME_oneline(a, buf, size); +#else + BIO *bio_out = BIO_new(BIO_s_mem()); + BUF_MEM *biomem; + int rc; + + if(!bio_out) + return 1; /* alloc failed! */ + + rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC); + BIO_get_mem_ptr(bio_out, &biomem); + + if((size_t)biomem->length < size) + size = biomem->length; + else + size--; /* don't overwrite the buffer end */ + + memcpy(buf, biomem->data, size); + buf[size]=0; + + BIO_free(bio_out); + + return !rc; +#endif +} + +static +int cert_verify_callback(int ok, X509_STORE_CTX *ctx) +{ + X509 *err_cert; + char buf[256]; + + err_cert=X509_STORE_CTX_get_current_cert(ctx); + (void)x509_name_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); + return ok; +} + +/* Return error string for last OpenSSL error + */ +static char *SSL_strerror(unsigned long error, char *buf, size_t size) +{ +#ifdef HAVE_ERR_ERROR_STRING_N + /* OpenSSL 0.9.6 and later has a function named + ERRO_error_string_n() that takes the size of the buffer as a + third argument */ + ERR_error_string_n(error, buf, size); +#else + (void) size; + ERR_error_string(error, buf); +#endif + return buf; +} + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +CURL_STATIC int Curl_ossl_init(void) +{ +#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES + ENGINE_load_builtin_engines(); +#endif + + /* Lets get nice error messages */ + SSL_load_error_strings(); + + /* Init the global ciphers and digests */ + if(!SSLeay_add_ssl_algorithms()) + return 0; + + OpenSSL_add_all_algorithms(); + + + /* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately + that function makes an exit() call on wrongly formatted config files + which makes it hard to use in some situations. OPENSSL_config() itself + calls CONF_modules_load_file() and we use that instead and we ignore + its return code! */ + + /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and + 0.9.8e */ +#ifndef CONF_MFLAGS_DEFAULT_SECTION +#define CONF_MFLAGS_DEFAULT_SECTION 0x0 +#endif + + CONF_modules_load_file(NULL, NULL, + CONF_MFLAGS_DEFAULT_SECTION| + CONF_MFLAGS_IGNORE_MISSING_FILE); + + return 1; +} + +/* Global cleanup */ +CURL_STATIC void Curl_ossl_cleanup(void) +{ + /* Free ciphers and digests lists */ + EVP_cleanup(); + +#ifdef HAVE_ENGINE_CLEANUP + /* Free engine list */ + ENGINE_cleanup(); +#endif + +#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA + /* Free OpenSSL ex_data table */ + CRYPTO_cleanup_all_ex_data(); +#endif + + /* Free OpenSSL error strings */ + ERR_free_strings(); + + /* Free thread local error state, destroying hash upon zero refcount */ +#ifdef HAVE_ERR_REMOVE_THREAD_STATE + ERR_remove_thread_state(NULL); +#else + ERR_remove_state(0); +#endif +} + +/* + * This function uses SSL_peek to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +CURL_STATIC int Curl_ossl_check_cxn(struct connectdata *conn) +{ + int rc; + char buf; + + rc = SSL_peek(conn->ssl[FIRSTSOCKET].handle, (void*)&buf, 1); + if(rc > 0) + return 1; /* connection still in place */ + + if(rc == 0) + return 0; /* connection has been closed */ + + return -1; /* connection status unknown */ +} + +/* Selects an OpenSSL crypto engine + */ +CURL_STATIC CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine) +{ +#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H) + ENGINE *e; + +#if OPENSSL_VERSION_NUMBER >= 0x00909000L + e = ENGINE_by_id(engine); +#else + /* avoid memory leak */ + for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { + const char *e_id = ENGINE_get_id(e); + if(!strcmp(engine, e_id)) + break; + } +#endif + + if(!e) { + failf(data, "SSL Engine '%s' not found", engine); + return CURLE_SSL_ENGINE_NOTFOUND; + } + + if(data->state.engine) { + ENGINE_finish(data->state.engine); + ENGINE_free(data->state.engine); + data->state.engine = NULL; + } + if(!ENGINE_init(e)) { + char buf[256]; + + ENGINE_free(e); + failf(data, "Failed to initialise SSL Engine '%s':\n%s", + engine, SSL_strerror(ERR_get_error(), buf, sizeof(buf))); + return CURLE_SSL_ENGINE_INITFAILED; + } + data->state.engine = e; + return CURLE_OK; +#else + (void)engine; + failf(data, "SSL Engine not supported"); + return CURLE_SSL_ENGINE_NOTFOUND; +#endif +} + +/* Sets engine as default for all SSL operations + */ +CURL_STATIC CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data) +{ +#ifdef HAVE_OPENSSL_ENGINE_H + if(data->state.engine) { + if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) { + infof(data, "set default crypto engine '%s'\n", + ENGINE_get_id(data->state.engine)); + } + else { + failf(data, "set default crypto engine '%s' failed", + ENGINE_get_id(data->state.engine)); + return CURLE_SSL_ENGINE_SETFAILED; + } + } +#else + (void) data; +#endif + return CURLE_OK; +} + +/* Return list of OpenSSL crypto engine names. + */ +CURL_STATIC struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data) +{ + struct curl_slist *list = NULL; +#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H) + struct curl_slist *beg; + ENGINE *e; + + for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { + beg = curl_slist_append(list, ENGINE_get_id(e)); + if(!beg) { + curl_slist_free_all(list); + return NULL; + } + list = beg; + } +#endif + (void) data; + return list; +} + + +/* + * This function is called when an SSL connection is closed. + */ +CURL_STATIC void Curl_ossl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->handle) { + (void)SSL_shutdown(connssl->handle); + SSL_set_connect_state(connssl->handle); + + SSL_free (connssl->handle); + connssl->handle = NULL; + } + if(connssl->ctx) { + SSL_CTX_free (connssl->ctx); + connssl->ctx = NULL; + } +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +CURL_STATIC int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; + char buf[120]; /* We will use this for the OpenSSL error buffer, so it has + to be at least 120 bytes long. */ + unsigned long sslerror; + ssize_t nread; + int buffsize; + int err; + int done = 0; + + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + (void)SSL_shutdown(connssl->handle); + + if(connssl->handle) { + buffsize = (int)sizeof(buf); + while(!done) { + int what = Curl_socket_ready(conn->sock[sockindex], + CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); + if(what > 0) { + ERR_clear_error(); + + /* Something to read, let's do it and hope that it is the close + notify alert from the server */ + nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf, + buffsize); + err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread); + + switch(err) { + case SSL_ERROR_NONE: /* this is not an error */ + case SSL_ERROR_ZERO_RETURN: /* no more data */ + /* This is the expected response. There was no data but only + the close notify alert */ + done = 1; + break; + case SSL_ERROR_WANT_READ: + /* there's data pending, re-invoke SSL_read() */ + infof(data, "SSL_ERROR_WANT_READ\n"); + break; + case SSL_ERROR_WANT_WRITE: + /* SSL wants a write. Really odd. Let's bail out. */ + infof(data, "SSL_ERROR_WANT_WRITE\n"); + done = 1; + break; + default: + /* openssl/ssl.h says "look at error stack/return value/errno" */ + sslerror = ERR_get_error(); + failf(conn->data, "SSL read: %s, errno %d", + ERR_error_string(sslerror, buf), + SOCKERRNO); + done = 1; + break; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + done = 1; + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + done = 1; + } + } /* while()-loop for the select() */ + + if(data->set.verbose) { +#ifdef HAVE_SSL_GET_SHUTDOWN + switch(SSL_get_shutdown(connssl->handle)) { + case SSL_SENT_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n"); + break; + case SSL_RECEIVED_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n"); + break; + case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|" + "SSL_RECEIVED__SHUTDOWN\n"); + break; + } +#endif + } + + SSL_free (connssl->handle); + connssl->handle = NULL; + } + return retval; +} + +CURL_STATIC void Curl_ossl_session_free(void *ptr) +{ + /* free the ID */ + SSL_SESSION_free(ptr); +} + +/* + * This function is called when the 'data' struct is going away. Close + * down everything and free all resources! + */ +CURL_STATIC void Curl_ossl_close_all(struct SessionHandle *data) +{ +#ifdef HAVE_OPENSSL_ENGINE_H + if(data->state.engine) { + ENGINE_finish(data->state.engine); + ENGINE_free(data->state.engine); + data->state.engine = NULL; + } +#else + (void)data; +#endif +} + +static int asn1_output(const ASN1_UTCTIME *tm, + char *buf, + size_t sizeofbuf) +{ + const char *asn1_string; + int gmt=FALSE; + int i; + int year=0, month=0, day=0, hour=0, minute=0, second=0; + + i=tm->length; + asn1_string=(const char *)tm->data; + + if(i < 10) + return 1; + if(asn1_string[i-1] == 'Z') + gmt=TRUE; + for(i=0; i<10; i++) + if((asn1_string[i] > '9') || (asn1_string[i] < '0')) + return 2; + + year= (asn1_string[0]-'0')*10+(asn1_string[1]-'0'); + if(year < 50) + year+=100; + + month= (asn1_string[2]-'0')*10+(asn1_string[3]-'0'); + if((month > 12) || (month < 1)) + return 3; + + day= (asn1_string[4]-'0')*10+(asn1_string[5]-'0'); + hour= (asn1_string[6]-'0')*10+(asn1_string[7]-'0'); + minute= (asn1_string[8]-'0')*10+(asn1_string[9]-'0'); + + if((asn1_string[10] >= '0') && (asn1_string[10] <= '9') && + (asn1_string[11] >= '0') && (asn1_string[11] <= '9')) + second= (asn1_string[10]-'0')*10+(asn1_string[11]-'0'); + + snprintf(buf, sizeofbuf, + "%04d-%02d-%02d %02d:%02d:%02d %s", + year+1900, month, day, hour, minute, second, (gmt?"GMT":"")); + + return 0; +} + +/* ====================================================== */ + + +/* Quote from RFC2818 section 3.1 "Server Identity" + + If a subjectAltName extension of type dNSName is present, that MUST + be used as the identity. Otherwise, the (most specific) Common Name + field in the Subject field of the certificate MUST be used. Although + the use of the Common Name is existing practice, it is deprecated and + Certification Authorities are encouraged to use the dNSName instead. + + Matching is performed using the matching rules specified by + [RFC2459]. If more than one identity of a given type is present in + the certificate (e.g., more than one dNSName name, a match in any one + of the set is considered acceptable.) Names may contain the wildcard + character * which is considered to match any single domain name + component or component fragment. E.g., *.a.com matches foo.a.com but + not bar.foo.a.com. f*.com matches foo.com but not bar.com. + + In some cases, the URI is specified as an IP address rather than a + hostname. In this case, the iPAddress subjectAltName must be present + in the certificate and must exactly match the IP in the URI. + +*/ +static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) +{ + int matched = -1; /* -1 is no alternative match yet, 1 means match and 0 + means mismatch */ + int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */ + size_t addrlen = 0; + struct SessionHandle *data = conn->data; + STACK_OF(GENERAL_NAME) *altnames; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + CURLcode result = CURLE_OK; + +#ifdef ENABLE_IPV6 + if(conn->bits.ipv6_ip && + Curl_inet_pton(AF_INET6, conn->host.name, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in6_addr); + } + else +#endif + if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in_addr); + } + + /* get a "list" of alternative names */ + altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL); + + if(altnames) { + int numalts; + int i; + + /* get amount of alternatives, RFC2459 claims there MUST be at least + one, but we don't depend on it... */ + numalts = sk_GENERAL_NAME_num(altnames); + + /* loop through all alternatives while none has matched */ + for(i=0; (itype == target) { + /* get data and length */ + const char *altptr = (char *)ASN1_STRING_data(check->d.ia5); + size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5); + + switch(target) { + case GEN_DNS: /* name/pattern comparison */ + /* The OpenSSL man page explicitly says: "In general it cannot be + assumed that the data returned by ASN1_STRING_data() is null + terminated or does not contain embedded nulls." But also that + "The actual format of the data will depend on the actual string + type itself: for example for and IA5String the data will be ASCII" + + Gisle researched the OpenSSL sources: + "I checked the 0.9.6 and 0.9.8 sources before my patch and + it always 0-terminates an IA5String." + */ + if((altlen == strlen(altptr)) && + /* if this isn't true, there was an embedded zero in the name + string and we cannot match it. */ + Curl_cert_hostcheck(altptr, conn->host.name)) + matched = 1; + else + matched = 0; + break; + + case GEN_IPADD: /* IP address comparison */ + /* compare alternative IP address if the data chunk is the same size + our server IP address is */ + if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) + matched = 1; + else + matched = 0; + break; + } + } + } + GENERAL_NAMES_free(altnames); + } + + if(matched == 1) + /* an alternative name matched the server hostname */ + infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname); + else if(matched == 0) { + /* an alternative name field existed, but didn't match and then + we MUST fail */ + infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname); + failf(data, "SSL: no alternative certificate subject name matches " + "target host name '%s'", conn->host.dispname); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else { + /* we have to look to the last occurrence of a commonName in the + distinguished one to get the most significant one. */ + int j, i=-1; + +/* The following is done because of a bug in 0.9.6b */ + + unsigned char *nulstr = (unsigned char *)""; + unsigned char *peer_CN = nulstr; + + X509_NAME *name = X509_get_subject_name(server_cert); + if(name) + while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i))>=0) + i=j; + + /* we have the name entry and we will now convert this to a string + that we can use for comparison. Doing this we support BMPstring, + UTF8 etc. */ + + if(i>=0) { + ASN1_STRING *tmp = + X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + + /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input + is already UTF-8 encoded. We check for this case and copy the raw + string manually to avoid the problem. This code can be made + conditional in the future when OpenSSL has been fixed. Work-around + brought by Alexis S. L. Carvalho. */ + if(tmp) { + if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) { + j = ASN1_STRING_length(tmp); + if(j >= 0) { + peer_CN = OPENSSL_malloc(j+1); + if(peer_CN) { + memcpy(peer_CN, ASN1_STRING_data(tmp), j); + peer_CN[j] = '\0'; + } + } + } + else /* not a UTF8 name */ + j = ASN1_STRING_to_UTF8(&peer_CN, tmp); + + if(peer_CN && (curlx_uztosi(strlen((char *)peer_CN)) != j)) { + /* there was a terminating zero before the end of string, this + cannot match and we return failure! */ + failf(data, "SSL: illegal cert name field"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + } + } + + if(peer_CN == nulstr) + peer_CN = NULL; + else { + /* convert peer_CN from UTF8 */ + CURLcode rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN)); + /* Curl_convert_from_utf8 calls failf if unsuccessful */ + if(rc) { + OPENSSL_free(peer_CN); + return rc; + } + } + + if(result) + /* error already detected, pass through */ + ; + else if(!peer_CN) { + failf(data, + "SSL: unable to obtain common name from peer certificate"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { + failf(data, "SSL: certificate subject name '%s' does not match " + "target host name '%s'", peer_CN, conn->host.dispname); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, "\t common name: %s (matched)\n", peer_CN); + } + if(peer_CN) + OPENSSL_free(peer_CN); + } + + return result; +} + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_IS_BORINGSSL) +static CURLcode verifystatus(struct connectdata *conn, + struct ssl_connect_data *connssl) +{ + int i, ocsp_status; + const unsigned char *p; + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + OCSP_RESPONSE *rsp = NULL; + OCSP_BASICRESP *br = NULL; + X509_STORE *st = NULL; + STACK_OF(X509) *ch = NULL; + + long len = SSL_get_tlsext_status_ocsp_resp(connssl->handle, &p); + + if(!p) { + failf(data, "No OCSP response received"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + rsp = d2i_OCSP_RESPONSE(NULL, &p, len); + if(!rsp) { + failf(data, "Invalid OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + ocsp_status = OCSP_response_status(rsp); + if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + failf(data, "Invalid OCSP response status: %s (%d)", + OCSP_response_status_str(ocsp_status), ocsp_status); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + br = OCSP_response_get1_basic(rsp); + if(!br) { + failf(data, "Invalid OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + ch = SSL_get_peer_cert_chain(connssl->handle); + st = SSL_CTX_get_cert_store(connssl->ctx); + +#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ + defined(LIBRESSL_VERSION_NUMBER)) + /* The authorized responder cert in the OCSP response MUST be signed by the + peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert, + no problem, but if it's an intermediate cert OpenSSL has a bug where it + expects this issuer to be present in the chain embedded in the OCSP + response. So we add it if necessary. */ + + /* First make sure the peer cert chain includes both a peer and an issuer, + and the OCSP response contains a responder cert. */ + if(sk_X509_num(ch) >= 2 && sk_X509_num(br->certs) >= 1) { + X509 *responder = sk_X509_value(br->certs, sk_X509_num(br->certs) - 1); + + /* Find issuer of responder cert and add it to the OCSP response chain */ + for(i = 0; i < sk_X509_num(ch); i++) { + X509 *issuer = sk_X509_value(ch, i); + if(X509_check_issued(issuer, responder) == X509_V_OK) { + if(!OCSP_basic_add1_cert(br, issuer)) { + failf(data, "Could not add issuer cert to OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + } + } + } +#endif + + if(OCSP_basic_verify(br, ch, st, 0) <= 0) { + failf(data, "OCSP response verification failed"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + for(i = 0; i < OCSP_resp_count(br); i++) { + int cert_status, crl_reason; + OCSP_SINGLERESP *single = NULL; + + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + + if(!(single = OCSP_resp_get0(br, i))) + continue; + + cert_status = OCSP_single_get0_status(single, &crl_reason, &rev, + &thisupd, &nextupd); + + if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { + failf(data, "OCSP response has expired"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + infof(data, "SSL certificate status: %s (%d)\n", + OCSP_cert_status_str(cert_status), cert_status); + + switch(cert_status) { + case V_OCSP_CERTSTATUS_GOOD: + break; + + case V_OCSP_CERTSTATUS_REVOKED: + result = CURLE_SSL_INVALIDCERTSTATUS; + + failf(data, "SSL certificate revocation reason: %s (%d)", + OCSP_crl_reason_str(crl_reason), crl_reason); + goto end; + + case V_OCSP_CERTSTATUS_UNKNOWN: + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + } + +end: + if(br) OCSP_BASICRESP_free(br); + OCSP_RESPONSE_free(rsp); + + return result; +} +#endif + +#endif /* USE_OPENSSL */ + +/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions + and thus this cannot be done there. */ +#ifdef SSL_CTRL_SET_MSG_CALLBACK + +static const char *ssl_msg_type(int ssl_ver, int msg) +{ +#ifdef SSL2_VERSION_MAJOR + if(ssl_ver == SSL2_VERSION_MAJOR) { + switch (msg) { + case SSL2_MT_ERROR: + return "Error"; + case SSL2_MT_CLIENT_HELLO: + return "Client hello"; + case SSL2_MT_CLIENT_MASTER_KEY: + return "Client key"; + case SSL2_MT_CLIENT_FINISHED: + return "Client finished"; + case SSL2_MT_SERVER_HELLO: + return "Server hello"; + case SSL2_MT_SERVER_VERIFY: + return "Server verify"; + case SSL2_MT_SERVER_FINISHED: + return "Server finished"; + case SSL2_MT_REQUEST_CERTIFICATE: + return "Request CERT"; + case SSL2_MT_CLIENT_CERTIFICATE: + return "Client CERT"; + } + } + else +#endif + if(ssl_ver == SSL3_VERSION_MAJOR) { + switch (msg) { + case SSL3_MT_HELLO_REQUEST: + return "Hello request"; + case SSL3_MT_CLIENT_HELLO: + return "Client hello"; + case SSL3_MT_SERVER_HELLO: + return "Server hello"; + case SSL3_MT_CERTIFICATE: + return "CERT"; + case SSL3_MT_SERVER_KEY_EXCHANGE: + return "Server key exchange"; + case SSL3_MT_CLIENT_KEY_EXCHANGE: + return "Client key exchange"; + case SSL3_MT_CERTIFICATE_REQUEST: + return "Request CERT"; + case SSL3_MT_SERVER_DONE: + return "Server finished"; + case SSL3_MT_CERTIFICATE_VERIFY: + return "CERT verify"; + case SSL3_MT_FINISHED: + return "Finished"; + } + } + return "Unknown"; +} + +static const char *tls_rt_type(int type) +{ + return ( + type == SSL3_RT_CHANGE_CIPHER_SPEC ? "TLS change cipher, " : + type == SSL3_RT_ALERT ? "TLS alert, " : + type == SSL3_RT_HANDSHAKE ? "TLS handshake, " : + type == SSL3_RT_APPLICATION_DATA ? "TLS app data, " : + "TLS Unknown, "); +} + + +/* + * Our callback from the SSL/TLS layers. + */ +static void ssl_tls_trace(int direction, int ssl_ver, int content_type, + const void *buf, size_t len, const SSL *ssl, + struct connectdata *conn) +{ + struct SessionHandle *data; + const char *msg_name, *tls_rt_name; + char ssl_buf[1024]; + char unknown[32]; + int msg_type, txt_len; + const char *verstr; + + if(!conn || !conn->data || !conn->data->set.fdebug || + (direction != 0 && direction != 1)) + return; + + data = conn->data; + + switch(ssl_ver) { +#ifdef SSL2_VERSION_MAJOR /* removed in recent versions */ + case SSL2_VERSION_MAJOR: + verstr = "SSLv2"; + break; +#endif +#ifdef SSL3_VERSION + case SSL3_VERSION: + verstr = "SSLv3"; + break; +#endif + case TLS1_VERSION: + verstr = "TLSv1.0"; + break; +#ifdef TLS1_1_VERSION + case TLS1_1_VERSION: + verstr = "TLSv1.1"; + break; +#endif +#ifdef TLS1_2_VERSION + case TLS1_2_VERSION: + verstr = "TLSv1.2"; + break; +#endif + default: + snprintf(unknown, sizeof(unknown), "(%x)", ssl_ver); + verstr = unknown; + break; + } + + ssl_ver >>= 8; /* check the upper 8 bits only below */ + + /* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL + * always pass-up content-type as 0. But the interesting message-type + * is at 'buf[0]'. + */ + if(ssl_ver == SSL3_VERSION_MAJOR && content_type != 0) + tls_rt_name = tls_rt_type(content_type); + else + tls_rt_name = ""; + + msg_type = *(char*)buf; + msg_name = ssl_msg_type(ssl_ver, msg_type); + + txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s, %s%s (%d):\n", + verstr, tls_rt_name, msg_name, msg_type); + Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL); + + Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT : + CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL); + (void) ssl; +} +#endif + +#ifdef USE_OPENSSL +/* ====================================================== */ + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME +# define use_sni(x) sni = (x) +#else +# define use_sni(x) Curl_nop_stmt +#endif + +/* Check for OpenSSL 1.0.2 which has ALPN support. */ +#undef HAS_ALPN +#if OPENSSL_VERSION_NUMBER >= 0x10002000L \ + && !defined(OPENSSL_NO_TLSEXT) +# define HAS_ALPN 1 +#endif + +/* Check for OpenSSL 1.0.1 which has NPN support. */ +#undef HAS_NPN +#if OPENSSL_VERSION_NUMBER >= 0x10001000L \ + && !defined(OPENSSL_NO_TLSEXT) \ + && !defined(OPENSSL_NO_NEXTPROTONEG) +# define HAS_NPN 1 +#endif + +#ifdef HAS_NPN + +/* + * in is a list of lenght prefixed strings. this function has to select + * the protocol we want to use from the list and write its string into out. + */ + +static int +select_next_protocol(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const char *key, unsigned int keylen) +{ + unsigned int i; + for(i = 0; i + keylen <= inlen; i += in[i] + 1) { + if(memcmp(&in[i + 1], key, keylen) == 0) { + *out = (unsigned char *) &in[i + 1]; + *outlen = in[i]; + return 0; + } + } + return -1; +} + +static int +select_next_proto_cb(SSL *ssl, + unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + void *arg) +{ + struct connectdata *conn = (struct connectdata*) arg; + + (void)ssl; + +#ifdef USE_NGHTTP2 + if(conn->data->set.httpversion == CURL_HTTP_VERSION_2_0 && + !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + infof(conn->data, "NPN, negotiated HTTP2 (%s)\n", + NGHTTP2_PROTO_VERSION_ID); + conn->negnpn = CURL_HTTP_VERSION_2_0; + return SSL_TLSEXT_ERR_OK; + } +#endif + + if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1, + ALPN_HTTP_1_1_LENGTH)) { + infof(conn->data, "NPN, negotiated HTTP1.1\n"); + conn->negnpn = CURL_HTTP_VERSION_1_1; + return SSL_TLSEXT_ERR_OK; + } + + infof(conn->data, "NPN, no overlap, use HTTP1.1\n"); + *out = (unsigned char *)ALPN_HTTP_1_1; + *outlen = ALPN_HTTP_1_1_LENGTH; + conn->negnpn = CURL_HTTP_VERSION_1_1; + + return SSL_TLSEXT_ERR_OK; +} +#endif /* HAS_NPN */ + +static const char * +get_ssl_version_txt(SSL *ssl) +{ + if(!ssl) + return ""; + + switch(SSL_version(ssl)) { +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + case TLS1_2_VERSION: + return "TLSv1.2"; + case TLS1_1_VERSION: + return "TLSv1.1"; +#endif + case TLS1_VERSION: + return "TLSv1.0"; + case SSL3_VERSION: + return "SSLv3"; + case SSL2_VERSION: + return "SSLv2"; + } + return "unknown"; +} + +static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + char *ciphers; + struct SessionHandle *data = conn->data; + SSL_METHOD_QUAL SSL_METHOD *req_method = NULL; + void *ssl_sessionid = NULL; + X509_LOOKUP *lookup = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long ctx_options; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + bool sni; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif +#endif + + DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); + + /* Make funny stuff to get random input */ + Curl_ossl_seed(data); + + data->set.ssl.certverifyresult = !X509_V_OK; + + /* check to see if we've been told to use an explicit SSL/TLS version */ + + switch(data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + /* it will be handled later with the context options */ + req_method = SSLv23_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_SSLv2: +#ifdef OPENSSL_NO_SSL2 + failf(data, "OpenSSL was built without SSLv2 support"); + return CURLE_NOT_BUILT_IN; +#else +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) + return CURLE_SSL_CONNECT_ERROR; +#endif + req_method = SSLv2_client_method(); + use_sni(FALSE); + break; +#endif + case CURL_SSLVERSION_SSLv3: +#ifdef OPENSSL_NO_SSL3_METHOD + failf(data, "OpenSSL was built without SSLv3 support"); + return CURLE_NOT_BUILT_IN; +#else +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) + return CURLE_SSL_CONNECT_ERROR; +#endif + req_method = SSLv3_client_method(); + use_sni(FALSE); + break; +#endif + } + + if(connssl->ctx) + SSL_CTX_free(connssl->ctx); + connssl->ctx = SSL_CTX_new(req_method); + + if(!connssl->ctx) { + failf(data, "SSL: couldn't create a context: %s", + ERR_error_string(ERR_peek_error(), NULL)); + return CURLE_OUT_OF_MEMORY; + } + +#ifdef SSL_MODE_RELEASE_BUFFERS + SSL_CTX_set_mode(connssl->ctx, SSL_MODE_RELEASE_BUFFERS); +#endif + +#ifdef SSL_CTRL_SET_MSG_CALLBACK + if(data->set.fdebug && data->set.verbose) { + /* the SSL trace callback is only used for verbose logging so we only + inform about failures of setting it */ + if(!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK, + (void (*)(void))ssl_tls_trace)) { + infof(data, "SSL: couldn't set callback!\n"); + } + else if(!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, + conn)) { + infof(data, "SSL: couldn't set callback argument!\n"); + } + } +#endif + + /* OpenSSL contains code to work-around lots of bugs and flaws in various + SSL-implementations. SSL_CTX_set_options() is used to enabled those + work-arounds. The man page for this option states that SSL_OP_ALL enables + all the work-arounds and that "It is usually safe to use SSL_OP_ALL to + enable the bug workaround options if compatibility with somewhat broken + implementations is desired." + + The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to + disable "rfc4507bis session ticket support". rfc4507bis was later turned + into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077 + + The enabled extension concerns the session management. I wonder how often + libcurl stops a connection and then resumes a TLS session. also, sending + the session data is some overhead. .I suggest that you just use your + proposed patch (which explicitly disables TICKET). + + If someone writes an application with libcurl and openssl who wants to + enable the feature, one can do this in the SSL callback. + + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper + interoperability with web server Netscape Enterprise Server 2.0.1 which + was released back in 1996. + + Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has + become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate + CVE-2010-4180 when using previous OpenSSL versions we no longer enable + this option regardless of OpenSSL version and SSL_OP_ALL definition. + + OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability + (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to + SSL_OP_ALL that _disables_ that work-around despite the fact that + SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to + keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit + must not be set. + */ + + ctx_options = SSL_OP_ALL; + +#ifdef SSL_OP_NO_TICKET + ctx_options |= SSL_OP_NO_TICKET; +#endif + +#ifdef SSL_OP_NO_COMPRESSION + ctx_options |= SSL_OP_NO_COMPRESSION; +#endif + +#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + /* mitigate CVE-2010-4180 */ + ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; +#endif + +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + /* unless the user explicitly ask to allow the protocol vulnerability we + use the work-around */ + if(!conn->data->set.ssl_enable_beast) + ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; +#endif + + switch(data->set.ssl.version) { + case CURL_SSLVERSION_SSLv3: +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + infof(data, "Set version TLSv1.x for SRP authorisation\n"); + } +#endif + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_TLSv1; +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + ctx_options |= SSL_OP_NO_TLSv1_1; + ctx_options |= SSL_OP_NO_TLSv1_2; +#endif + break; + + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_SSLv3; + break; + + case CURL_SSLVERSION_TLSv1_0: + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_SSLv3; +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + ctx_options |= SSL_OP_NO_TLSv1_1; + ctx_options |= SSL_OP_NO_TLSv1_2; +#endif + break; + +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + case CURL_SSLVERSION_TLSv1_1: + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_SSLv3; + ctx_options |= SSL_OP_NO_TLSv1; + ctx_options |= SSL_OP_NO_TLSv1_2; + break; + + case CURL_SSLVERSION_TLSv1_2: + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_SSLv3; + ctx_options |= SSL_OP_NO_TLSv1; + ctx_options |= SSL_OP_NO_TLSv1_1; + break; +#endif + +#ifndef OPENSSL_NO_SSL2 + case CURL_SSLVERSION_SSLv2: + ctx_options |= SSL_OP_NO_SSLv3; + ctx_options |= SSL_OP_NO_TLSv1; +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + ctx_options |= SSL_OP_NO_TLSv1_1; + ctx_options |= SSL_OP_NO_TLSv1_2; +#endif + break; +#endif + + default: + failf(data, "Unsupported SSL protocol version"); + return CURLE_SSL_CONNECT_ERROR; + } + + SSL_CTX_set_options(connssl->ctx, ctx_options); + +#ifdef HAS_NPN + if(data->set.ssl_enable_npn) + SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, conn); +#endif + +#ifdef HAS_ALPN + if(data->set.ssl_enable_alpn) { + int cur = 0; + unsigned char protocols[128]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + + memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN); + cur += NGHTTP2_PROTO_VERSION_ID_LEN; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur++] = ALPN_HTTP_1_1_LENGTH; + memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + cur += ALPN_HTTP_1_1_LENGTH; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + /* expects length prefixed preference ordered list of protocols in wire + * format + */ + SSL_CTX_set_alpn_protos(connssl->ctx, protocols, cur); + } +#endif + + if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) { + if(!cert_stuff(conn, + connssl->ctx, + data->set.str[STRING_CERT], + data->set.str[STRING_CERT_TYPE], + data->set.str[STRING_KEY], + data->set.str[STRING_KEY_TYPE])) { + /* failf() is already done in cert_stuff() */ + return CURLE_SSL_CERTPROBLEM; + } + } + + ciphers = data->set.str[STRING_SSL_CIPHER_LIST]; + if(!ciphers) + ciphers = (char *)DEFAULT_CIPHER_SELECTION; + if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s\n", ciphers); + +#ifdef USE_TLS_SRP + if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); + + if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) { + failf(data, "Unable to set SRP user name"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) { + failf(data, "failed setting SRP password"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + if(!data->set.str[STRING_SSL_CIPHER_LIST]) { + infof(data, "Setting cipher list SRP\n"); + + if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) { + failf(data, "failed setting SRP cipher list"); + return CURLE_SSL_CIPHER; + } + } + } +#endif + if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) { + /* tell SSL where to find CA certificates that are used to verify + the servers certificate. */ + if(!SSL_CTX_load_verify_locations(connssl->ctx, + data->set.str[STRING_SSL_CAFILE], + data->set.str[STRING_SSL_CAPATH])) { + if(data->set.ssl.verifypeer) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + data->set.str[STRING_SSL_CAFILE]? + data->set.str[STRING_SSL_CAFILE]: "none", + data->set.str[STRING_SSL_CAPATH]? + data->set.str[STRING_SSL_CAPATH] : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate verification + is required. */ + infof(data, "error setting certificate verify locations," + " continuing anyway:\n"); + } + } + else { + /* Everything is fine. */ + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: + "none", + data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: + "none"); + } + + if(data->set.str[STRING_SSL_CRLFILE]) { + /* tell SSL where to find CRL file that is used to check certificate + * revocation */ + lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx), + X509_LOOKUP_file()); + if(!lookup || + (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE], + X509_FILETYPE_PEM)) ) { + failf(data, "error loading CRL file: %s", + data->set.str[STRING_SSL_CRLFILE]); + return CURLE_SSL_CRL_BADFILE; + } + else { + /* Everything is fine. */ + infof(data, "successfully load CRL file:\n"); + X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), + X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); + } + infof(data, + " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ? + data->set.str[STRING_SSL_CRLFILE]: "none"); + } + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ + SSL_CTX_set_verify(connssl->ctx, + data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, + cert_verify_callback); + + /* give application a chance to interfere with SSL set up. */ + if(data->set.ssl.fsslctx) { + result = (*data->set.ssl.fsslctx)(data, connssl->ctx, + data->set.ssl.fsslctxp); + if(result) { + failf(data, "error signaled by ssl ctx callback"); + return result; + } + } + + /* Lets make an SSL structure */ + if(connssl->handle) + SSL_free(connssl->handle); + connssl->handle = SSL_new(connssl->ctx); + if(!connssl->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_IS_BORINGSSL) + if(data->set.ssl.verifystatus) + SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp); +#endif + + SSL_set_connect_state(connssl->handle); + + connssl->server_cert = 0x0; + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && +#endif + sni && + !SSL_set_tlsext_host_name(connssl->handle, conn->host.name)) + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); +#endif + + /* Check if there's a cached ID we can/should use here! */ + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { + /* we got a session id, use it! */ + if(!SSL_set_session(connssl->handle, ssl_sessionid)) { + failf(data, "SSL: SSL_set_session failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof (data, "SSL re-using session ID\n"); + } + + /* pass the raw socket into the SSL layers */ + if(!SSL_set_fd(connssl->handle, (int)sockfd)) { + failf(data, "SSL: SSL_set_fd failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) +{ + struct SessionHandle *data = conn->data; + int err; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + DEBUGASSERT(ssl_connect_2 == connssl->connecting_state + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); + + ERR_clear_error(); + + err = SSL_connect(connssl->handle); + + /* 1 is fine + 0 is "not successful but was shut down controlled" + <0 is "handshake was not successful, because a fatal error occurred" */ + if(1 != err) { + int detail = SSL_get_error(connssl->handle, err); + + if(SSL_ERROR_WANT_READ == detail) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else if(SSL_ERROR_WANT_WRITE == detail) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } + else { + /* untreated error */ + unsigned long errdetail; + char error_buffer[256]; /* OpenSSL documents that this must be at least + 256 bytes long. */ + CURLcode result; + const char *cert_problem = NULL; + long lerr; + + connssl->connecting_state = ssl_connect_2; /* the connection failed, + we're not waiting for + anything else. */ + + errdetail = ERR_get_error(); /* Gets the earliest error code from the + thread's error queue and removes the + entry. */ + + switch(errdetail) { + case 0x1407E086: + /* 1407E086: + SSL routines: + SSL2_SET_CERTIFICATE: + certificate verify failed */ + /* fall-through */ + case 0x14090086: + /* 14090086: + SSL routines: + SSL3_GET_SERVER_CERTIFICATE: + certificate verify failed */ + result = CURLE_SSL_CACERT; + + lerr = SSL_get_verify_result(connssl->handle); + if(lerr != X509_V_OK) { + snprintf(error_buffer, sizeof(error_buffer), + "SSL certificate problem: %s", + X509_verify_cert_error_string(lerr)); + } + else + cert_problem = "SSL certificate problem, verify that the CA cert is" + " OK."; + + break; + default: + result = CURLE_SSL_CONNECT_ERROR; + SSL_strerror(errdetail, error_buffer, sizeof(error_buffer)); + break; + } + + /* detail is already set to the SSL error above */ + + /* If we e.g. use SSLv2 request-method and the server doesn't like us + * (RST connection etc.), OpenSSL gives no explanation whatsoever and + * the SO_ERROR is also lost. + */ + if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { + failf(data, "Unknown SSL protocol error in connection to %s:%ld ", + conn->host.name, conn->remote_port); + return result; + } + + /* Could be a CERT problem */ + failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer); + + return result; + } + } + else { + /* we have been connected fine, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_3; + + /* Informational message */ + infof(data, "SSL connection using %s / %s\n", + get_ssl_version_txt(connssl->handle), + SSL_get_cipher(connssl->handle)); + +#ifdef HAS_ALPN + /* Sets data and len to negotiated protocol, len is 0 if no protocol was + * negotiated + */ + if(data->set.ssl_enable_alpn) { + const unsigned char* neg_protocol; + unsigned int len; + SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len); + if(len != 0) { + infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); + +#ifdef USE_NGHTTP2 + if(len == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) { + conn->negnpn = CURL_HTTP_VERSION_2_0; + } + else +#endif + if(len == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + } +#endif + + return CURLE_OK; + } +} + +static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len) +{ + int i, ilen; + + if((ilen = (int)len) < 0) + return 1; /* buffer too big */ + + i = i2t_ASN1_OBJECT(buf, ilen, a); + + if(i >= ilen) + return 1; /* buffer too small */ + + return 0; +} + +static void pubkey_show(struct SessionHandle *data, + int num, + const char *type, + const char *name, + unsigned char *raw, + int len) +{ + size_t left; + int i; + char namebuf[32]; + char *buffer; + + left = len*3 + 1; + buffer = malloc(left); + if(buffer) { + char *ptr=buffer; + snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name); + for(i=0; i< len; i++) { + snprintf(ptr, left, "%02x:", raw[i]); + ptr += 3; + left -= 3; + } + infof(data, " %s: %s\n", namebuf, buffer); + Curl_ssl_push_certinfo(data, num, namebuf, buffer); + free(buffer); + } +} + +#define print_pubkey_BN(_type, _name, _num) \ +do { \ + if(pubkey->pkey._type->_name) { \ + int len = BN_num_bytes(pubkey->pkey._type->_name); \ + if(len < CERTBUFFERSIZE) { \ + BN_bn2bin(pubkey->pkey._type->_name, (unsigned char*)bufp); \ + bufp[len] = 0; \ + pubkey_show(data, _num, #_type, #_name, (unsigned char*)bufp, len); \ + } \ + } \ +} WHILE_FALSE + +static int X509V3_ext(struct SessionHandle *data, + int certnum, + STACK_OF(X509_EXTENSION) *exts) +{ + int i; + size_t j; + + if(sk_X509_EXTENSION_num(exts) <= 0) + /* no extensions, bail out */ + return 1; + + for(i=0; ilength bytes at biomem->data, this little loop here is only + done for the infof() call, we send the "raw" data to the certinfo + function */ + for(j=0; j<(size_t)biomem->length; j++) { + const char *sep=""; + if(biomem->data[j] == '\n') { + sep=", "; + j++; /* skip the newline */ + }; + while((j<(size_t)biomem->length) && (biomem->data[j] == ' ')) + j++; + if(j<(size_t)biomem->length) + ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep, + biomem->data[j]); + } + infof(data, " %s\n", buf); + + Curl_ssl_push_certinfo(data, certnum, namebuf, buf); + + BIO_free(bio_out); + + } + return 0; /* all is fine */ +} + + +static void X509_signature(struct SessionHandle *data, + int numcert, + ASN1_STRING *sig) +{ + char buf[1024]; + char *ptr = buf; + int i; + + for(i=0; ilength; i++) + ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%02x:", sig->data[i]); + + infof(data, " Signature: %s\n", buf); + Curl_ssl_push_certinfo(data, numcert, "Signature", buf); +} + +static void dumpcert(struct SessionHandle *data, X509 *x, int numcert) +{ + BIO *bio_out = BIO_new(BIO_s_mem()); + BUF_MEM *biomem; + + /* this outputs the cert in this 64 column wide style with newlines and + -----BEGIN CERTIFICATE----- texts and more */ + PEM_write_bio_X509(bio_out, x); + + BIO_get_mem_ptr(bio_out, &biomem); + + Curl_ssl_push_certinfo_len(data, numcert, + "Cert", biomem->data, biomem->length); + + BIO_free(bio_out); +} + +/* + * This size was previously 512 which has been reported "too small" without + * any specifics, so it was enlarged to allow more data to get shown uncut. + * The "perfect" size is yet to figure out. + */ +#define CERTBUFFERSIZE 8192 + +static CURLcode get_cert_chain(struct connectdata *conn, + struct ssl_connect_data *connssl) + +{ + CURLcode result; + STACK_OF(X509) *sk; + int i; + char *bufp; + struct SessionHandle *data = conn->data; + int numcerts; + + bufp = malloc(CERTBUFFERSIZE); + if(!bufp) + return CURLE_OUT_OF_MEMORY; + + sk = SSL_get_peer_cert_chain(connssl->handle); + if(!sk) { + free(bufp); + return CURLE_OUT_OF_MEMORY; + } + + numcerts = sk_X509_num(sk); + + result = Curl_ssl_init_certinfo(data, numcerts); + if(result) { + free(bufp); + return result; + } + + infof(data, "--- Certificate chain\n"); + for(i=0; itype == V_ASN1_NEG_INTEGER) { + *ptr++='-'; + left--; + } + + for(j=0; (jlength) && (left>=3); j++) { + snprintf(ptr, left, "%02x", num->data[j]); + ptr += 2; + left -= 2; + } + if(num->length) + infof(data, " Serial Number: %s\n", bufp); + else + bufp[0]=0; + } + if(bufp[0]) + Curl_ssl_push_certinfo(data, i, "Serial Number", bufp); /* hex */ + + cinf = x->cert_info; + + j = asn1_object_dump(cinf->signature->algorithm, bufp, CERTBUFFERSIZE); + if(!j) { + infof(data, " Signature Algorithm: %s\n", bufp); + Curl_ssl_push_certinfo(data, i, "Signature Algorithm", bufp); + } + + certdate = X509_get_notBefore(x); + asn1_output(certdate, bufp, CERTBUFFERSIZE); + infof(data, " Start date: %s\n", bufp); + Curl_ssl_push_certinfo(data, i, "Start date", bufp); + + certdate = X509_get_notAfter(x); + asn1_output(certdate, bufp, CERTBUFFERSIZE); + infof(data, " Expire date: %s\n", bufp); + Curl_ssl_push_certinfo(data, i, "Expire date", bufp); + + j = asn1_object_dump(cinf->key->algor->algorithm, bufp, CERTBUFFERSIZE); + if(!j) { + infof(data, " Public Key Algorithm: %s\n", bufp); + Curl_ssl_push_certinfo(data, i, "Public Key Algorithm", bufp); + } + + pubkey = X509_get_pubkey(x); + if(!pubkey) + infof(data, " Unable to load public key\n"); + else { + switch(pubkey->type) { + case EVP_PKEY_RSA: + infof(data, " RSA Public Key (%d bits)\n", + BN_num_bits(pubkey->pkey.rsa->n)); + snprintf(bufp, CERTBUFFERSIZE, "%d", BN_num_bits(pubkey->pkey.rsa->n)); + Curl_ssl_push_certinfo(data, i, "RSA Public Key", bufp); + + print_pubkey_BN(rsa, n, i); + print_pubkey_BN(rsa, e, i); + print_pubkey_BN(rsa, d, i); + print_pubkey_BN(rsa, p, i); + print_pubkey_BN(rsa, q, i); + print_pubkey_BN(rsa, dmp1, i); + print_pubkey_BN(rsa, dmq1, i); + print_pubkey_BN(rsa, iqmp, i); + break; + case EVP_PKEY_DSA: + print_pubkey_BN(dsa, p, i); + print_pubkey_BN(dsa, q, i); + print_pubkey_BN(dsa, g, i); + print_pubkey_BN(dsa, priv_key, i); + print_pubkey_BN(dsa, pub_key, i); + break; + case EVP_PKEY_DH: + print_pubkey_BN(dh, p, i); + print_pubkey_BN(dh, g, i); + print_pubkey_BN(dh, priv_key, i); + print_pubkey_BN(dh, pub_key, i); + break; +#if 0 + case EVP_PKEY_EC: /* symbol not present in OpenSSL 0.9.6 */ + /* left TODO */ + break; +#endif + } + EVP_PKEY_free(pubkey); + } + + X509V3_ext(data, i, cinf->extensions); + + X509_signature(data, i, x->signature); + + dumpcert(data, x, i); + } + + free(bufp); + + return CURLE_OK; +} + +/* + * Heavily modified from: + * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL + */ +static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey) +{ + /* Scratch */ + int len1 = 0, len2 = 0; + unsigned char *buff1 = NULL, *temp = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + if(!cert) + return result; + + do { + /* Begin Gyrations to get the subjectPublicKeyInfo */ + /* Thanks to Viktor Dukhovni on the OpenSSL mailing list */ + + /* https://groups.google.com/group/mailing.openssl.users/browse_thread + /thread/d61858dae102c6c7 */ + len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL); + if(len1 < 1) + break; /* failed */ + + /* https://www.openssl.org/docs/crypto/buffer.html */ + buff1 = temp = OPENSSL_malloc(len1); + if(!buff1) + break; /* failed */ + + /* https://www.openssl.org/docs/crypto/d2i_X509.html */ + len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp); + + /* + * These checks are verifying we got back the same values as when we + * sized the buffer. It's pretty weak since they should always be the + * same. But it gives us something to test. + */ + if((len1 != len2) || !temp || ((temp - buff1) != len1)) + break; /* failed */ + + /* End Gyrations */ + + /* The one good exit point */ + result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1); + } while(0); + + /* https://www.openssl.org/docs/crypto/buffer.html */ + if(buff1) + OPENSSL_free(buff1); + + return result; +} + +/* + * Get the server cert, verify it and show it etc, only call failf() if the + * 'strict' argument is TRUE as otherwise all this is for informational + * purposes only! + * + * We check certificates to authenticate the server; otherwise we risk + * man-in-the-middle attack. + */ +static CURLcode servercert(struct connectdata *conn, + struct ssl_connect_data *connssl, + bool strict) +{ + CURLcode result = CURLE_OK; + int rc; + long lerr; + ASN1_TIME *certdate; + struct SessionHandle *data = conn->data; + X509 *issuer; + FILE *fp; + char *buffer = data->state.buffer; + const char *ptr; + + if(data->set.ssl.certinfo) + /* we've been asked to gather certificate info! */ + (void)get_cert_chain(conn, connssl); + + connssl->server_cert = SSL_get_peer_certificate(connssl->handle); + if(!connssl->server_cert) { + if(strict) + failf(data, "SSL: couldn't get peer certificate!"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + infof(data, "Server certificate:\n"); + + rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert), + buffer, BUFSIZE); + infof(data, "\t subject: %s\n", rc?"[NONE]":buffer); + + certdate = X509_get_notBefore(connssl->server_cert); + asn1_output(certdate, buffer, BUFSIZE); + infof(data, "\t start date: %s\n", buffer); + + certdate = X509_get_notAfter(connssl->server_cert); + asn1_output(certdate, buffer, BUFSIZE); + infof(data, "\t expire date: %s\n", buffer); + + if(data->set.ssl.verifyhost) { + result = verifyhost(conn, connssl->server_cert); + if(result) { + X509_free(connssl->server_cert); + connssl->server_cert = NULL; + return result; + } + } + + rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert), + buffer, BUFSIZE); + if(rc) { + if(strict) + failf(data, "SSL: couldn't get X509-issuer name!"); + result = CURLE_SSL_CONNECT_ERROR; + } + else { + infof(data, "\t issuer: %s\n", buffer); + + /* We could do all sorts of certificate verification stuff here before + deallocating the certificate. */ + + /* e.g. match issuer name with provided issuer certificate */ + if(data->set.str[STRING_SSL_ISSUERCERT]) { + fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], "r"); + if(!fp) { + if(strict) + failf(data, "SSL: Unable to open issuer cert (%s)", + data->set.str[STRING_SSL_ISSUERCERT]); + X509_free(connssl->server_cert); + connssl->server_cert = NULL; + return CURLE_SSL_ISSUER_ERROR; + } + + issuer = PEM_read_X509(fp, NULL, ZERO_NULL, NULL); + if(!issuer) { + if(strict) + failf(data, "SSL: Unable to read issuer cert (%s)", + data->set.str[STRING_SSL_ISSUERCERT]); + X509_free(connssl->server_cert); + X509_free(issuer); + fclose(fp); + return CURLE_SSL_ISSUER_ERROR; + } + + fclose(fp); + + if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) { + if(strict) + failf(data, "SSL: Certificate issuer check failed (%s)", + data->set.str[STRING_SSL_ISSUERCERT]); + X509_free(connssl->server_cert); + X509_free(issuer); + connssl->server_cert = NULL; + return CURLE_SSL_ISSUER_ERROR; + } + + infof(data, "\t SSL certificate issuer check ok (%s)\n", + data->set.str[STRING_SSL_ISSUERCERT]); + X509_free(issuer); + } + + lerr = data->set.ssl.certverifyresult = + SSL_get_verify_result(connssl->handle); + + if(data->set.ssl.certverifyresult != X509_V_OK) { + if(data->set.ssl.verifypeer) { + /* We probably never reach this, because SSL_connect() will fail + and we return earlier if verifypeer is set? */ + if(strict) + failf(data, "SSL certificate verify result: %s (%ld)", + X509_verify_cert_error_string(lerr), lerr); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t SSL certificate verify result: %s (%ld)," + " continuing anyway.\n", + X509_verify_cert_error_string(lerr), lerr); + } + else + infof(data, "\t SSL certificate verify ok.\n"); + } + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_IS_BORINGSSL) + if(data->set.ssl.verifystatus) { + result = verifystatus(conn, connssl); + if(result) { + X509_free(connssl->server_cert); + connssl->server_cert = NULL; + return result; + } + } +#endif + + if(!strict) + /* when not strict, we don't bother about the verify cert problems */ + result = CURLE_OK; + + ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + if(!result && ptr) { + result = pkp_pin_peer_pubkey(connssl->server_cert, ptr); + if(result) + failf(data, "SSL: public key does not match pinned public key!"); + } + + X509_free(connssl->server_cert); + connssl->server_cert = NULL; + connssl->connecting_state = ssl_connect_done; + + return result; +} + +static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + void *old_ssl_sessionid = NULL; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + bool incache; + SSL_SESSION *our_ssl_sessionid; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + +#ifdef HAVE_SSL_GET1_SESSION + our_ssl_sessionid = SSL_get1_session(connssl->handle); + + /* SSL_get1_session() will increment the reference + count and the session will stay in memory until explicitly freed with + SSL_SESSION_free(3), regardless of its state. + This function was introduced in openssl 0.9.5a. */ +#else + our_ssl_sessionid = SSL_get_session(connssl->handle); + + /* if SSL_get1_session() is unavailable, use SSL_get_session(). + This is an inferior option because the session can be flushed + at any time by openssl. It is included only so curl compiles + under versions of openssl < 0.9.5a. + + WARNING: How curl behaves if it's session is flushed is + untested. + */ +#endif + + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, + 0 /* unknown size */); + if(result) { + failf(data, "failed to store ssl session"); + return result; + } + } +#ifdef HAVE_SSL_GET1_SESSION + else { + /* Session was incache, so refcount already incremented earlier. + * Avoid further increments with each SSL_get1_session() call. + * This does not free the session as refcount remains > 0 + */ + SSL_SESSION_free(our_ssl_sessionid); + } +#endif + + /* + * We check certificates to authenticate the server; otherwise we risk + * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to + * verify the peer ignore faults and failures from the server cert + * operations. + */ + + result = servercert(conn, connssl, + (data->set.ssl.verifypeer || data->set.ssl.verifyhost)); + + if(!result) + connssl->connecting_state = ssl_connect_done; + + return result; +} + +static Curl_recv ossl_recv; +static Curl_send ossl_send; + +static CURLcode ossl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = ossl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if this + * connection is done nonblocking and this loop would execute again. This + * permits the owner of a multi handle to abort a connection attempt + * before step2 has completed while ensuring that a client using select() + * or epoll() will always have a valid fdset to wait on. + */ + result = ossl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = ossl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = ossl_recv; + conn->send[sockindex] = ossl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +CURL_STATIC CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return ossl_connect_common(conn, sockindex, TRUE, done); +} + +CURL_STATIC CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = ossl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +CURL_STATIC bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex) +{ + if(conn->ssl[connindex].handle) + /* SSL is in use */ + return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE; + else + return FALSE; +} + +static ssize_t ossl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + /* SSL_write() is said to return 'int' while write() and send() returns + 'size_t' */ + int err; + char error_buffer[120]; /* OpenSSL documents that this must be at least 120 + bytes long. */ + unsigned long sslerror; + int memlen; + int rc; + + ERR_clear_error(); + + memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen); + + if(rc <= 0) { + err = SSL_get_error(conn->ssl[sockindex].handle, rc); + + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* The operation did not complete; the same TLS/SSL I/O function + should be called again later. This is basically an EWOULDBLOCK + equivalent. */ + *curlcode = CURLE_AGAIN; + return -1; + case SSL_ERROR_SYSCALL: + failf(conn->data, "SSL_write() returned SYSCALL, errno = %d", + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + case SSL_ERROR_SSL: + /* A failure in the SSL library occurred, usually a protocol error. + The OpenSSL error queue contains more information on the error. */ + sslerror = ERR_get_error(); + failf(conn->data, "SSL_write() error: %s", + ERR_error_string(sslerror, error_buffer)); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + /* a true error */ + failf(conn->data, "SSL_write() return error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + *curlcode = CURLE_OK; + return (ssize_t)rc; /* number of bytes */ +} + +static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + char error_buffer[120]; /* OpenSSL documents that this must be at + least 120 bytes long. */ + unsigned long sslerror; + ssize_t nread; + int buffsize; + + ERR_clear_error(); + + buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize); + if(nread <= 0) { + /* failed SSL_read */ + int err = SSL_get_error(conn->ssl[num].handle, (int)nread); + + switch(err) { + case SSL_ERROR_NONE: /* this is not an error */ + case SSL_ERROR_ZERO_RETURN: /* no more data */ + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return + value/errno" */ + /* https://www.openssl.org/docs/crypto/ERR_get_error.html */ + sslerror = ERR_get_error(); + if((nread < 0) || sslerror) { + /* If the return code was negative or there actually is an error in the + queue */ + failf(conn->data, "SSL read: %s, errno %d", + ERR_error_string(sslerror, error_buffer), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + } + return nread; +} + +CURL_STATIC size_t Curl_ossl_version(char *buffer, size_t size) +{ +#ifdef YASSL_VERSION + /* yassl provides an OpenSSL API compatibility layer so it looks identical + to OpenSSL in all other aspects */ + return snprintf(buffer, size, "yassl/%s", YASSL_VERSION); +#else /* YASSL_VERSION */ +#ifdef OPENSSL_IS_BORINGSSL + return snprintf(buffer, size, "BoringSSL"); +#else /* OPENSSL_IS_BORINGSSL */ + +#if(OPENSSL_VERSION_NUMBER >= 0x905000) + { + char sub[3]; + unsigned long ssleay_value; + sub[2]='\0'; + sub[1]='\0'; + ssleay_value=SSLeay(); + if(ssleay_value < 0x906000) { + ssleay_value=SSLEAY_VERSION_NUMBER; + sub[0]='\0'; + } + else { + if(ssleay_value&0xff0) { + int minor_ver = (ssleay_value >> 4) & 0xff; + if(minor_ver > 26) { + /* handle extended version introduced for 0.9.8za */ + sub[1] = (char) ((minor_ver - 1) % 26 + 'a' + 1); + sub[0] = 'z'; + } + else { + sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1); + } + } + else + sub[0]='\0'; + } + + return snprintf(buffer, size, "%s/%lx.%lx.%lx%s", +#ifdef LIBRESSL_VERSION_NUMBER + "LibreSSL" +#else + "OpenSSL" +#endif + , (ssleay_value>>28)&0xf, + (ssleay_value>>20)&0xff, + (ssleay_value>>12)&0xff, + sub); + } + +#else /* OPENSSL_VERSION_NUMBER is less than 0.9.5 */ + +#if(OPENSSL_VERSION_NUMBER >= 0x900000) + return snprintf(buffer, size, "OpenSSL/%lx.%lx.%lx", + (OPENSSL_VERSION_NUMBER>>28)&0xff, + (OPENSSL_VERSION_NUMBER>>20)&0xff, + (OPENSSL_VERSION_NUMBER>>12)&0xf); + +#else /* (OPENSSL_VERSION_NUMBER >= 0x900000) */ + { + char sub[2]; + sub[1]='\0'; + if(OPENSSL_VERSION_NUMBER&0x0f) { + sub[0]=(OPENSSL_VERSION_NUMBER&0x0f) + 'a' -1; + } + else + sub[0]='\0'; + + return snprintf(buffer, size, "SSL/%x.%x.%x%s", + (OPENSSL_VERSION_NUMBER>>12)&0xff, + (OPENSSL_VERSION_NUMBER>>8)&0xf, + (OPENSSL_VERSION_NUMBER>>4)&0xf, sub); + } +#endif /* (OPENSSL_VERSION_NUMBER >= 0x900000) */ +#endif /* OPENSSL_VERSION_NUMBER is less than 0.9.5 */ + +#endif /* OPENSSL_IS_BORINGSSL */ +#endif /* YASSL_VERSION */ +} + +/* can be called with data == NULL */ +CURL_STATIC int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy, + size_t length) +{ + if(data) { + Curl_ossl_seed(data); /* Initiate the seed if not already done */ + } + RAND_bytes(entropy, curlx_uztosi(length)); + return 0; /* 0 as in no problem */ +} + +CURL_STATIC void Curl_ossl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum /* output */, + size_t unused) +{ + MD5_CTX MD5pw; + (void)unused; + MD5_Init(&MD5pw); + MD5_Update(&MD5pw, tmp, tmplen); + MD5_Final(md5sum, &MD5pw); +} + +bool Curl_ossl_cert_status_request(void) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_IS_BORINGSSL) + return TRUE; +#else + return FALSE; +#endif +} +#endif /* USE_OPENSSL */ diff --git a/libcurl/src/lib/vtls/openssl.h b/libcurl/src/lib/vtls/openssl.h new file mode 100644 index 0000000..bfa3bc0 --- /dev/null +++ b/libcurl/src/lib/vtls/openssl.h @@ -0,0 +1,113 @@ +#ifndef HEADER_CURL_SSLUSE_H +#define HEADER_CURL_SSLUSE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "../curl_setup.h" + +#ifdef USE_OPENSSL +/* + * This header should only be needed to get included by vtls.c and openssl.c + */ + +#include "urldata.h" + +CURL_STATIC CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex); +CURL_STATIC CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); + +/* close a SSL connection */ +CURL_STATIC void Curl_ossl_close(struct connectdata *conn, int sockindex); + +/* tell OpenSSL to close down all open information regarding connections (and + thus session ID caching etc) */ +CURL_STATIC void Curl_ossl_close_all(struct SessionHandle *data); + +/* Sets an OpenSSL engine */ +CURL_STATIC CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine); + +/* function provided for the generic SSL-layer, called when a session id + should be freed */ +CURL_STATIC void Curl_ossl_session_free(void *ptr); + +/* Sets engine as default for all SSL operations */ +CURL_STATIC CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data); + +/* Build list of OpenSSL engines */ +CURL_STATIC struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data); + +CURL_STATIC int Curl_ossl_init(void); +CURL_STATIC void Curl_ossl_cleanup(void); + +CURL_STATIC size_t Curl_ossl_version(char *buffer, size_t size); +CURL_STATIC int Curl_ossl_check_cxn(struct connectdata *cxn); +CURL_STATIC int Curl_ossl_shutdown(struct connectdata *conn, int sockindex); +CURL_STATIC bool Curl_ossl_data_pending(const struct connectdata *conn, + int connindex); + +/* return 0 if a find random is filled in */ +CURL_STATIC int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy, + size_t length); +CURL_STATIC void Curl_ossl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum /* output */, + size_t unused); + +bool Curl_ossl_cert_status_request(void); + +/* Set the API backend definition to OpenSSL */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL + +/* this backend supports the CAPATH option */ +#define have_curlssl_ca_path 1 + +/* this backend supports CURLOPT_CERTINFO */ +#define have_curlssl_certinfo 1 + +/* this backend suppots CURLOPT_SSL_CTX_* */ +#define have_curlssl_ssl_ctx 1 + +/* API setup for OpenSSL */ +#define curlssl_init Curl_ossl_init +#define curlssl_cleanup Curl_ossl_cleanup +#define curlssl_connect Curl_ossl_connect +#define curlssl_connect_nonblocking Curl_ossl_connect_nonblocking +#define curlssl_session_free(x) Curl_ossl_session_free(x) +#define curlssl_close_all Curl_ossl_close_all +#define curlssl_close Curl_ossl_close +#define curlssl_shutdown(x,y) Curl_ossl_shutdown(x,y) +#define curlssl_set_engine(x,y) Curl_ossl_set_engine(x,y) +#define curlssl_set_engine_default(x) Curl_ossl_set_engine_default(x) +#define curlssl_engines_list(x) Curl_ossl_engines_list(x) +#define curlssl_version Curl_ossl_version +#define curlssl_check_cxn Curl_ossl_check_cxn +#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y) +#define curlssl_random(x,y,z) Curl_ossl_random(x,y,z) +#define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d) +#define curlssl_cert_status_request() Curl_ossl_cert_status_request() + +#define DEFAULT_CIPHER_SELECTION \ + "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH" + +#endif /* USE_OPENSSL */ +#endif /* HEADER_CURL_SSLUSE_H */ diff --git a/libcurl/src/lib/vtls/polarssl.c b/libcurl/src/lib/vtls/polarssl.c new file mode 100644 index 0000000..8deef27 --- /dev/null +++ b/libcurl/src/lib/vtls/polarssl.c @@ -0,0 +1,753 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2011, Hoi-Ho Chan, + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "../curl_setup.h" + +#ifdef USE_POLARSSL + +#include +#include +#include +#include +#include + +#if POLARSSL_VERSION_NUMBER < 0x01030000 +#error too old PolarSSL +#endif + +#include +#include +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "polarssl.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "rawstr.h" +#include "polarssl_threadlock.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* apply threading? */ +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +#define THREADING_SUPPORT +#endif + +#if defined(THREADING_SUPPORT) +static entropy_context entropy; + +static int entropy_init_initialized = 0; + +/* start of entropy_init_mutex() */ +static void entropy_init_mutex(entropy_context *ctx) +{ + /* lock 0 = entropy_init_mutex() */ + polarsslthreadlock_lock_function(0); + if(entropy_init_initialized == 0) { + entropy_init(ctx); + entropy_init_initialized = 1; + } + polarsslthreadlock_unlock_function(0); +} +/* end of entropy_init_mutex() */ + +/* start of entropy_func_mutex() */ +static int entropy_func_mutex(void *data, unsigned char *output, size_t len) +{ + int ret; + /* lock 1 = entropy_func_mutex() */ + polarsslthreadlock_lock_function(1); + ret = entropy_func(data, output, len); + polarsslthreadlock_unlock_function(1); + + return ret; +} +/* end of entropy_func_mutex() */ + +#endif /* THREADING_SUPPORT */ + +/* Define this to enable lots of debugging for PolarSSL */ +#undef POLARSSL_DEBUG + +#ifdef POLARSSL_DEBUG +static void polarssl_debug(void *context, int level, const char *line) +{ + struct SessionHandle *data = NULL; + + if(!context) + return; + + data = (struct SessionHandle *)context; + + infof(data, "%s", line); + (void) level; +} +#else +#endif + +/* ALPN for http2? */ +#ifdef POLARSSL_SSL_ALPN +# define HAS_ALPN +#endif + +static Curl_recv polarssl_recv; +static Curl_send polarssl_send; + + +static CURLcode +polarssl_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct SessionHandle *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + + bool sni = TRUE; /* default is SNI enabled */ + int ret = -1; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + void *old_session = NULL; + size_t old_session_size = 0; + char errorbuf[128]; + errorbuf[0]=0; + + /* PolarSSL only supports SSLv3 and TLSv1 */ + if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + failf(data, "PolarSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) + sni = FALSE; /* SSLv3 has no SNI */ + +#ifdef THREADING_SUPPORT + entropy_init_mutex(&entropy); + + if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy, + connssl->ssn.id, connssl->ssn.length)) != 0) { +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#else + entropy_init(&connssl->entropy); + + if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy, + connssl->ssn.id, connssl->ssn.length)) != 0) { +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#endif /* THREADING_SUPPORT */ + + /* Load the trusted CA */ + memset(&connssl->cacert, 0, sizeof(x509_crt)); + + if(data->set.str[STRING_SSL_CAFILE]) { + ret = x509_crt_parse_file(&connssl->cacert, + data->set.str[STRING_SSL_CAFILE]); + + if(ret<0) { +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", + data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); + + if(data->set.ssl.verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + } + + if(data->set.str[STRING_SSL_CAPATH]) { + ret = x509_crt_parse_path(&connssl->cacert, + data->set.str[STRING_SSL_CAPATH]); + + if(ret<0) { +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", + data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); + + if(data->set.ssl.verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Load the client certificate */ + memset(&connssl->clicert, 0, sizeof(x509_crt)); + + if(data->set.str[STRING_CERT]) { + ret = x509_crt_parse_file(&connssl->clicert, + data->set.str[STRING_CERT]); + + if(ret) { +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", + data->set.str[STRING_CERT], -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the client private key */ + if(data->set.str[STRING_KEY]) { + pk_context pk; + pk_init(&pk); + ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY], + data->set.str[STRING_KEY_PASSWD]); + if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if(ret == 0) + rsa_copy(&connssl->rsa, pk_rsa(pk)); + else + rsa_free(&connssl->rsa); + pk_free(&pk); + + if(ret) { +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", + data->set.str[STRING_KEY], -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the CRL */ + memset(&connssl->crl, 0, sizeof(x509_crl)); + + if(data->set.str[STRING_SSL_CRLFILE]) { + ret = x509_crl_parse_file(&connssl->crl, + data->set.str[STRING_SSL_CRLFILE]); + + if(ret) { +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", + data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); + + return CURLE_SSL_CRL_BADFILE; + } + } + + infof(data, "PolarSSL: Connecting to %s:%d\n", + conn->host.name, conn->remote_port); + + if(ssl_init(&connssl->ssl)) { + failf(data, "PolarSSL: ssl_init failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch(data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_1); + break; + case CURL_SSLVERSION_SSLv3: + ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_0); + ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_0); + infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); + break; + case CURL_SSLVERSION_TLSv1_0: + ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_1); + ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_1); + infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n"); + break; + case CURL_SSLVERSION_TLSv1_1: + ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_2); + ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_2); + infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n"); + break; + case CURL_SSLVERSION_TLSv1_2: + ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_3); + ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_3); + infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n"); + break; + } + + ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); + ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL); + + ssl_set_rng(&connssl->ssl, ctr_drbg_random, + &connssl->ctr_drbg); + ssl_set_bio(&connssl->ssl, + net_recv, &conn->sock[sockindex], + net_send, &conn->sock[sockindex]); + + ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); + if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { + memcpy(&connssl->ssn, old_session, old_session_size); + infof(data, "PolarSSL re-using session\n"); + } + + ssl_set_session(&connssl->ssl, + &connssl->ssn); + + ssl_set_ca_chain(&connssl->ssl, + &connssl->cacert, + &connssl->crl, + conn->host.name); + + ssl_set_own_cert_rsa(&connssl->ssl, + &connssl->clicert, &connssl->rsa); + + if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && +#ifdef ENABLE_IPV6 + !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && +#endif + sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) { + infof(data, "WARNING: failed to configure " + "server name indication (SNI) TLS extension\n"); + } + +#ifdef HAS_ALPN + if(data->set.ssl_enable_alpn) { + static const char* protocols[3]; + int cur = 0; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur++] = ALPN_HTTP_1_1; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + protocols[cur] = NULL; + + ssl_set_alpn_protocols(&connssl->ssl, protocols); + } +#endif + +#ifdef POLARSSL_DEBUG + ssl_set_dbg(&connssl->ssl, polarssl_debug, data); +#endif + + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +polarssl_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret; + struct SessionHandle *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + char buffer[1024]; + + char errorbuf[128]; + errorbuf[0] = 0; + + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; + + ret = ssl_handshake(&connssl->ssl); + + switch(ret) { + case 0: + break; + + case POLARSSL_ERR_NET_WANT_READ: + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + + case POLARSSL_ERR_NET_WANT_WRITE: + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + + default: +#ifdef POLARSSL_ERROR_C + error_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* POLARSSL_ERROR_C */ + failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s", + -ret, errorbuf); + return CURLE_SSL_CONNECT_ERROR; + } + + infof(data, "PolarSSL: Handshake complete, cipher is %s\n", + ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) ); + + ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); + + if(ret && data->set.ssl.verifypeer) { + if(ret & BADCERT_EXPIRED) + failf(data, "Cert verify failed: BADCERT_EXPIRED"); + + if(ret & BADCERT_REVOKED) { + failf(data, "Cert verify failed: BADCERT_REVOKED"); + return CURLE_SSL_CACERT; + } + + if(ret & BADCERT_CN_MISMATCH) + failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); + + if(ret & BADCERT_NOT_TRUSTED) + failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); + + return CURLE_PEER_FAILED_VERIFICATION; + } + + if(ssl_get_peer_cert(&(connssl->ssl))) { + /* If the session was resumed, there will be no peer certs */ + memset(buffer, 0, sizeof(buffer)); + + if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ", + ssl_get_peer_cert(&(connssl->ssl))) != -1) + infof(data, "Dumping cert info:\n%s\n", buffer); + } + +#ifdef HAS_ALPN + if(data->set.ssl_enable_alpn) { + const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl); + + if(next_protocol != NULL) { + infof(data, "ALPN, server accepted to use %s\n", next_protocol); + +#ifdef USE_NGHTTP2 + if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2_0; + } + else +#endif + if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + } +#endif + + connssl->connecting_state = ssl_connect_3; + infof(data, "SSL connected\n"); + + return CURLE_OK; +} + +static CURLcode +polarssl_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode result = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; + void *old_ssl_sessionid = NULL; + ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn; + bool incache; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + /* Save the current session data for possible re-use */ + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + void *new_session = malloc(sizeof(ssl_session)); + + if(new_session) { + memcpy(new_session, our_ssl_sessionid, sizeof(ssl_session)); + + result = Curl_ssl_addsessionid(conn, new_session, sizeof(ssl_session)); + } + else + result = CURLE_OUT_OF_MEMORY; + + if(result) { + failf(data, "failed to store ssl session"); + return result; + } + } + + connssl->connecting_state = ssl_connect_done; + + return CURLE_OK; +} + +static ssize_t polarssl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + int ret = -1; + + ret = ssl_write(&conn->ssl[sockindex].ssl, + (unsigned char *)mem, len); + + if(ret < 0) { + *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ? + CURLE_AGAIN : CURLE_SEND_ERROR; + ret = -1; + } + + return ret; +} + +CURL_STATIC void Curl_polarssl_close(struct connectdata *conn, int sockindex) +{ + rsa_free(&conn->ssl[sockindex].rsa); + x509_crt_free(&conn->ssl[sockindex].clicert); + x509_crt_free(&conn->ssl[sockindex].cacert); + x509_crl_free(&conn->ssl[sockindex].crl); + ssl_free(&conn->ssl[sockindex].ssl); +} + +static ssize_t polarssl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + int ret = -1; + ssize_t len = -1; + + memset(buf, 0, buffersize); + ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize); + + if(ret <= 0) { + if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) + return 0; + + *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ? + CURLE_AGAIN : CURLE_RECV_ERROR; + return -1; + } + + len = ret; + + return len; +} + +CURL_STATIC void Curl_polarssl_session_free(void *ptr) +{ + free(ptr); +} + +/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and + higher) will be mbed TLS branded.. */ + +CURL_STATIC size_t Curl_polarssl_version(char *buffer, size_t size) +{ + unsigned int version = version_get_number(); + return snprintf(buffer, size, "%s/%d.%d.%d", + version >= 0x01030A00?"mbedTLS":"PolarSSL", + version>>24, (version>>16)&0xff, (version>>8)&0xff); +} + +static CURLcode +polarssl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = polarssl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = polarssl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = polarssl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +CURL_STATIC CURLcode +Curl_polarssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return polarssl_connect_common(conn, sockindex, TRUE, done); +} + + +CURL_STATIC CURLcode +Curl_polarssl_connect(struct connectdata *conn, + int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = polarssl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +/* + * return 0 error initializing SSL + * return 1 SSL initialized successfully + */ +int polarssl_init(void) +{ + return polarsslthreadlock_thread_setup(); +} + +void polarssl_cleanup(void) +{ + (void)polarsslthreadlock_thread_cleanup(); +} + +#endif /* USE_POLARSSL */ diff --git a/libcurl/src/lib/vtls/polarssl.h b/libcurl/src/lib/vtls/polarssl.h new file mode 100644 index 0000000..98c2e5c --- /dev/null +++ b/libcurl/src/lib/vtls/polarssl.h @@ -0,0 +1,75 @@ +#ifndef HEADER_CURL_POLARSSL_H +#define HEADER_CURL_POLARSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Hoi-Ho Chan, + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "../curl_setup.h" + +#ifdef USE_POLARSSL + +/* Called on first use PolarSSL, setup threading if supported */ +int polarssl_init(void); +void polarssl_cleanup(void); + + +CURL_STATIC CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex); + +CURL_STATIC CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); + + /* close a SSL connection */ +CURL_STATIC void Curl_polarssl_close(struct connectdata *conn, int sockindex); + +CURL_STATIC void Curl_polarssl_session_free(void *ptr); +CURL_STATIC size_t Curl_polarssl_version(char *buffer, size_t size); +CURL_STATIC int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex); + +/* Set the API backend definition to PolarSSL */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL + +/* this backend supports the CAPATH option */ +#define have_curlssl_ca_path 1 + +/* API setup for PolarSSL */ +#define curlssl_init() polarssl_init() +#define curlssl_cleanup() polarssl_cleanup() +#define curlssl_connect Curl_polarssl_connect +#define curlssl_connect_nonblocking Curl_polarssl_connect_nonblocking +#define curlssl_session_free(x) Curl_polarssl_session_free(x) +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_polarssl_close +#define curlssl_shutdown(x,y) 0 +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_polarssl_version +#define curlssl_check_cxn(x) ((void)x, -1) +#define curlssl_data_pending(x,y) ((void)x, (void)y, 0) + +/* This might cause libcurl to use a weeker random! + TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that +*/ +#define curlssl_random(x,y,z) ((void)x, (void)y, (void)z, CURLE_NOT_BUILT_IN) + +#endif /* USE_POLARSSL */ +#endif /* HEADER_CURL_POLARSSL_H */ diff --git a/libcurl/src/lib/vtls/polarssl_threadlock.c b/libcurl/src/lib/vtls/polarssl_threadlock.c new file mode 100644 index 0000000..8a8d3ea --- /dev/null +++ b/libcurl/src/lib/vtls/polarssl_threadlock.c @@ -0,0 +1,153 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, 2011, Hoi-Ho Chan, + * Copyright (C) 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "../curl_setup.h" + +#if defined(USE_POLARSSL) && \ + (defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)) + +#if defined(USE_THREADS_POSIX) +# ifdef HAVE_PTHREAD_H +# include +# endif +#elif defined(USE_THREADS_WIN32) +# ifdef HAVE_PROCESS_H +# include +# endif +#endif + +#include "polarssl_threadlock.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* number of thread locks */ +#define NUMT 2 + +/* This array will store all of the mutexes available to PolarSSL. */ +static POLARSSL_MUTEX_T *mutex_buf = NULL; + +int polarsslthreadlock_thread_setup(void) +{ + int i; + int ret; + + mutex_buf = malloc(NUMT * sizeof(POLARSSL_MUTEX_T)); + if(!mutex_buf) + return 0; /* error, no number of threads defined */ + +#ifdef HAVE_PTHREAD_H + for(i = 0; i < NUMT; i++) { + ret = pthread_mutex_init(&mutex_buf[i], NULL); + if(ret) + return 0; /* pthread_mutex_init failed */ + } +#elif defined(HAVE_PROCESS_H) + for(i = 0; i < NUMT; i++) { + mutex_buf[i] = CreateMutex(0, FALSE, 0); + if(mutex_buf[i] == 0) + return 0; /* CreateMutex failed */ + } +#endif /* HAVE_PTHREAD_H */ + + return 1; /* OK */ +} + +int polarsslthreadlock_thread_cleanup(void) +{ + int i; + int ret; + + if(!mutex_buf) + return 0; /* error, no threads locks defined */ + +#ifdef HAVE_PTHREAD_H + for(i = 0; i < NUMT; i++) { + ret = pthread_mutex_destroy(&mutex_buf[i]); + if(ret) + return 0; /* pthread_mutex_destroy failed */ + } +#elif defined(HAVE_PROCESS_H) + for(i = 0; i < NUMT; i++) { + ret = CloseHandle(mutex_buf[i]); + if(!ret) + return 0; /* CloseHandle failed */ + } +#endif /* HAVE_PTHREAD_H */ + free(mutex_buf); + mutex_buf = NULL; + + return 1; /* OK */ +} + +int polarsslthreadlock_lock_function(int n) +{ + int ret; +#ifdef HAVE_PTHREAD_H + if(n < NUMT) { + ret = pthread_mutex_lock(&mutex_buf[n]); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_lock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } + } +#elif defined(HAVE_PROCESS_H) + if(n < NUMT) { + ret = (WaitForSingleObject(mutex_buf[n], INFINITE)==WAIT_FAILED?1:0); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_lock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } + } +#endif /* HAVE_PTHREAD_H */ + return 1; /* OK */ +} + +int polarsslthreadlock_unlock_function(int n) +{ + int ret; +#ifdef HAVE_PTHREAD_H + if(n < NUMT) { + ret = pthread_mutex_unlock(&mutex_buf[n]); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_unlock_function failed\n")); + return 0; /* pthread_mutex_unlock failed */ + } + } +#elif defined(HAVE_PROCESS_H) + if(n < NUMT) { + ret = ReleaseMutex(mutex_buf[n]); + if(!ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_unlock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } + } +#endif /* HAVE_PTHREAD_H */ + return 1; /* OK */ +} + +#endif /* USE_POLARSSL */ diff --git a/libcurl/src/lib/vtls/polarssl_threadlock.h b/libcurl/src/lib/vtls/polarssl_threadlock.h new file mode 100644 index 0000000..b67b3f9 --- /dev/null +++ b/libcurl/src/lib/vtls/polarssl_threadlock.h @@ -0,0 +1,53 @@ +#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H +#define HEADER_CURL_POLARSSL_THREADLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Hoi-Ho Chan, + * Copyright (C) 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_POLARSSL + +#if defined(USE_THREADS_POSIX) +# define POLARSSL_MUTEX_T pthread_mutex_t +#elif defined(USE_THREADS_WIN32) +# define POLARSSL_MUTEX_T HANDLE +#endif + +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + +int polarsslthreadlock_thread_setup(void); +int polarsslthreadlock_thread_cleanup(void); +int polarsslthreadlock_lock_function(int n); +int polarsslthreadlock_unlock_function(int n); + +#else + +#define polarsslthreadlock_thread_setup() 1 +#define polarsslthreadlock_thread_cleanup() 1 +#define polarsslthreadlock_lock_function(x) 1 +#define polarsslthreadlock_unlock_function(x) 1 + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* USE_POLARSSL */ + +#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */ diff --git a/libcurl/src/lib/vtls/schannel.c b/libcurl/src/lib/vtls/schannel.c new file mode 100644 index 0000000..00f6b81 --- /dev/null +++ b/libcurl/src/lib/vtls/schannel.c @@ -0,0 +1,1364 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Marc Hoersken, + * Copyright (C) 2012, Mark Salisbury, + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all SChannel-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +/* + * Based upon the PolarSSL implementation in polarssl.c and polarssl.h: + * Copyright (C) 2010, 2011, Hoi-Ho Chan, + * + * Based upon the CyaSSL implementation in cyassl.c and cyassl.h: + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * Thanks for code and inspiration! + */ + +#include "../curl_setup.h" + +#ifdef USE_SCHANNEL + +#ifndef USE_WINDOWS_SSPI +# error "Can't compile SCHANNEL support without SSPI." +#endif + +#include "../curl_sspi.h" +#include "schannel.h" +#include "vtls.h" +#include "../sendf.h" +#include "../connect.h" /* for the connect timeout */ +#include "../strerror.h" +#include "../select.h" /* for the socket readyness */ +#include "../inet_pton.h" /* for IP addr SNI check */ +#include "../curl_multibyte.h" +#include "../warnless.h" +#include "../curl_printf.h" +#include "../curl_memory.h" +/* The last #include file should be: */ +#include "../memdebug.h" + +/* Uncomment to force verbose output + * #define infof(x, y, ...) printf(y, __VA_ARGS__) + * #define failf(x, y, ...) printf(y, __VA_ARGS__) + */ + +static Curl_recv schannel_recv; +static Curl_send schannel_send; + +#ifdef _WIN32_WCE +static CURLcode verify_certificate(struct connectdata *conn, int sockindex); +#endif + +static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType, + void *BufDataPtr, unsigned long BufByteSize) +{ + buffer->cbBuffer = BufByteSize; + buffer->BufferType = BufType; + buffer->pvBuffer = BufDataPtr; +} + +static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, + unsigned long NumArrElem) +{ + desc->ulVersion = SECBUFFER_VERSION; + desc->pBuffers = BufArr; + desc->cBuffers = NumArrElem; +} + +static CURLcode +schannel_connect_step1(struct connectdata *conn, int sockindex) +{ + ssize_t written = -1; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SecBuffer outbuf; + SecBufferDesc outbuf_desc; + SCHANNEL_CRED schannel_cred; + SECURITY_STATUS sspi_status = SEC_E_OK; + struct curl_schannel_cred *old_cred = NULL; + struct in_addr addr; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + TCHAR *host_name; + CURLcode result; + + infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", + conn->host.name, conn->remote_port); + + /* check for an existing re-usable credential handle */ + if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)) { + connssl->cred = old_cred; + infof(data, "schannel: re-using existing credential handle\n"); + } + else { + /* setup Schannel API options */ + memset(&schannel_cred, 0, sizeof(schannel_cred)); + schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; + + if(data->set.ssl.verifypeer) { +#ifdef _WIN32_WCE + /* certificate validation on CE doesn't seem to work right; we'll + do it following a more manual process. */ + schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | + SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; +#else + schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION | + SCH_CRED_REVOCATION_CHECK_CHAIN; +#endif + infof(data, "schannel: checking server certificate revocation\n"); + } + else { + schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | + SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + infof(data, "schannel: disable server certificate revocation checks\n"); + } + + if(!data->set.ssl.verifyhost) { + schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + infof(data, "schannel: verifyhost setting prevents Schannel from " + "comparing the supplied target name with the subject " + "names in server certificates. Also disables SNI.\n"); + } + + switch(data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | + SP_PROT_TLS1_1_CLIENT | + SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_0: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_1: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_2: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_SSLv3: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; + break; + case CURL_SSLVERSION_SSLv2: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; + break; + } + + /* allocate memory for the re-usable credential handle */ + connssl->cred = (struct curl_schannel_cred *) + malloc(sizeof(struct curl_schannel_cred)); + if(!connssl->cred) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + memset(connssl->cred, 0, sizeof(struct curl_schannel_cred)); + + /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx */ + sspi_status = s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, + SECPKG_CRED_OUTBOUND, NULL, &schannel_cred, NULL, NULL, + &connssl->cred->cred_handle, &connssl->cred->time_stamp); + + if(sspi_status != SEC_E_OK) { + if(sspi_status == SEC_E_WRONG_PRINCIPAL) + failf(data, "schannel: SNI or certificate check failed: %s", + Curl_sspi_strerror(conn, sspi_status)); + else + failf(data, "schannel: AcquireCredentialsHandle failed: %s", + Curl_sspi_strerror(conn, sspi_status)); + Curl_safefree(connssl->cred); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* Warn if SNI is disabled due to use of an IP address */ + if(Curl_inet_pton(AF_INET, conn->host.name, &addr) +#ifdef ENABLE_IPV6 + || Curl_inet_pton(AF_INET6, conn->host.name, &addr6) +#endif + ) { + infof(data, "schannel: using IP address, SNI is not supported by OS.\n"); + } + + /* setup output buffer */ + InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, &outbuf, 1); + + /* setup request flags */ + connssl->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | + ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_STREAM; + + /* allocate memory for the security context handle */ + connssl->ctxt = (struct curl_schannel_ctxt *) + malloc(sizeof(struct curl_schannel_ctxt)); + if(!connssl->ctxt) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt)); + + host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */ + + sspi_status = s_pSecFn->InitializeSecurityContext( + &connssl->cred->cred_handle, NULL, host_name, + connssl->req_flags, 0, 0, NULL, 0, &connssl->ctxt->ctxt_handle, + &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + if(sspi_status != SEC_I_CONTINUE_NEEDED) { + if(sspi_status == SEC_E_WRONG_PRINCIPAL) + failf(data, "schannel: SNI or certificate check failed: %s", + Curl_sspi_strerror(conn, sspi_status)); + else + failf(data, "schannel: initial InitializeSecurityContext failed: %s", + Curl_sspi_strerror(conn, sspi_status)); + Curl_safefree(connssl->ctxt); + return CURLE_SSL_CONNECT_ERROR; + } + + infof(data, "schannel: sending initial handshake data: " + "sending %lu bytes...\n", outbuf.cbBuffer); + + /* send initial handshake data which is now stored in output buffer */ + result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + outbuf.cbBuffer, &written); + s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); + if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { + failf(data, "schannel: failed to send initial handshake data: " + "sent %zd of %lu bytes", written, outbuf.cbBuffer); + return CURLE_SSL_CONNECT_ERROR; + } + + infof(data, "schannel: sent initial handshake data: " + "sent %zd bytes\n", written); + + /* continue to second handshake step */ + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +schannel_connect_step2(struct connectdata *conn, int sockindex) +{ + int i; + ssize_t nread = -1, written = -1; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned char *reallocated_buffer; + size_t reallocated_length; + SecBuffer outbuf[2]; + SecBufferDesc outbuf_desc; + SecBuffer inbuf[2]; + SecBufferDesc inbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + TCHAR *host_name; + CURLcode result; + bool doread; + + doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; + + infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", + conn->host.name, conn->remote_port); + + if(!connssl->cred || !connssl->ctxt) + return CURLE_SSL_CONNECT_ERROR; + + /* buffer to store previously received and encrypted data */ + if(connssl->encdata_buffer == NULL) { + connssl->encdata_offset = 0; + connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; + connssl->encdata_buffer = malloc(connssl->encdata_length); + if(connssl->encdata_buffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + } + + /* if we need a bigger buffer to read a full message, increase buffer now */ + if(connssl->encdata_length - connssl->encdata_offset < + CURL_SCHANNEL_BUFFER_FREE_SIZE) { + /* increase internal encrypted data buffer */ + reallocated_length = connssl->encdata_offset + + CURL_SCHANNEL_BUFFER_FREE_SIZE; + reallocated_buffer = realloc(connssl->encdata_buffer, + reallocated_length); + + if(reallocated_buffer == NULL) { + failf(data, "schannel: unable to re-allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + else { + connssl->encdata_buffer = reallocated_buffer; + connssl->encdata_length = reallocated_length; + } + } + + for(;;) { + if(doread) { + /* read encrypted handshake data from socket */ + result = Curl_read_plain(conn->sock[sockindex], + (char *) (connssl->encdata_buffer + + connssl->encdata_offset), + connssl->encdata_length - + connssl->encdata_offset, + &nread); + if(result == CURLE_AGAIN) { + if(connssl->connecting_state != ssl_connect_2_writing) + connssl->connecting_state = ssl_connect_2_reading; + infof(data, "schannel: failed to receive handshake, " + "need more data\n"); + return CURLE_OK; + } + else if((result != CURLE_OK) || (nread == 0)) { + failf(data, "schannel: failed to receive handshake, " + "SSL/TLS connection failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* increase encrypted data buffer offset */ + connssl->encdata_offset += nread; + } + + infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", + connssl->encdata_offset, connssl->encdata_length); + + /* setup input buffers */ + InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset), + curlx_uztoul(connssl->encdata_offset)); + InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, inbuf, 2); + + /* setup output buffers */ + InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0); + InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0); + InitSecBufferDesc(&outbuf_desc, outbuf, 2); + + if(inbuf[0].pvBuffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + + /* copy received handshake data into input buffer */ + memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer, + connssl->encdata_offset); + + host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */ + + sspi_status = s_pSecFn->InitializeSecurityContext( + &connssl->cred->cred_handle, &connssl->ctxt->ctxt_handle, + host_name, connssl->req_flags, 0, 0, &inbuf_desc, 0, NULL, + &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + /* free buffer for received handshake data */ + Curl_safefree(inbuf[0].pvBuffer); + + /* check if the handshake was incomplete */ + if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + connssl->connecting_state = ssl_connect_2_reading; + infof(data, "schannel: received incomplete message, need more data\n"); + return CURLE_OK; + } + + /* check if the handshake needs to be continued */ + if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) { + for(i = 0; i < 2; i++) { + /* search for handshake tokens that need to be send */ + if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { + infof(data, "schannel: sending next handshake data: " + "sending %lu bytes...\n", outbuf[i].cbBuffer); + + /* send handshake token to server */ + result = Curl_write_plain(conn, conn->sock[sockindex], + outbuf[i].pvBuffer, outbuf[i].cbBuffer, + &written); + if((result != CURLE_OK) || + (outbuf[i].cbBuffer != (size_t) written)) { + failf(data, "schannel: failed to send next handshake data: " + "sent %zd of %lu bytes", written, outbuf[i].cbBuffer); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* free obsolete buffer */ + if(outbuf[i].pvBuffer != NULL) { + s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer); + } + } + } + else { + if(sspi_status == SEC_E_WRONG_PRINCIPAL) + failf(data, "schannel: SNI or certificate check failed: %s", + Curl_sspi_strerror(conn, sspi_status)); + else + failf(data, "schannel: next InitializeSecurityContext failed: %s", + Curl_sspi_strerror(conn, sspi_status)); + return CURLE_SSL_CONNECT_ERROR; + } + + /* check if there was additional remaining encrypted data */ + if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { + infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer); + /* + There are two cases where we could be getting extra data here: + 1) If we're renegotiating a connection and the handshake is already + complete (from the server perspective), it can encrypted app data + (not handshake data) in an extra buffer at this point. + 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a + connection and this extra data is part of the handshake. + We should process the data immediately; waiting for the socket to + be ready may fail since the server is done sending handshake data. + */ + /* check if the remaining data is less than the total amount + and therefore begins after the already processed data */ + if(connssl->encdata_offset > inbuf[1].cbBuffer) { + memmove(connssl->encdata_buffer, + (connssl->encdata_buffer + connssl->encdata_offset) - + inbuf[1].cbBuffer, inbuf[1].cbBuffer); + connssl->encdata_offset = inbuf[1].cbBuffer; + if(sspi_status == SEC_I_CONTINUE_NEEDED) { + doread = FALSE; + continue; + } + } + } + else { + connssl->encdata_offset = 0; + } + break; + } + + /* check if the handshake needs to be continued */ + if(sspi_status == SEC_I_CONTINUE_NEEDED) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + + /* check if the handshake is complete */ + if(sspi_status == SEC_E_OK) { + connssl->connecting_state = ssl_connect_3; + infof(data, "schannel: SSL/TLS handshake complete\n"); + } + +#ifdef _WIN32_WCE + /* Windows CE doesn't do any server certificate validation. + We have to do it manually. */ + if(data->set.ssl.verifypeer) + return verify_certificate(conn, sockindex); +#endif + + return CURLE_OK; +} + +static CURLcode +schannel_connect_step3(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct curl_schannel_cred *old_cred = NULL; + bool incache; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", + conn->host.name, conn->remote_port); + + if(!connssl->cred) + return CURLE_SSL_CONNECT_ERROR; + + /* check if the required context attributes are met */ + if(connssl->ret_flags != connssl->req_flags) { + if(!(connssl->ret_flags & ISC_RET_SEQUENCE_DETECT)) + failf(data, "schannel: failed to setup sequence detection"); + if(!(connssl->ret_flags & ISC_RET_REPLAY_DETECT)) + failf(data, "schannel: failed to setup replay detection"); + if(!(connssl->ret_flags & ISC_RET_CONFIDENTIALITY)) + failf(data, "schannel: failed to setup confidentiality"); + if(!(connssl->ret_flags & ISC_RET_ALLOCATED_MEMORY)) + failf(data, "schannel: failed to setup memory allocation"); + if(!(connssl->ret_flags & ISC_RET_STREAM)) + failf(data, "schannel: failed to setup stream orientation"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* increment the reference counter of the credential/session handle */ + if(connssl->cred && connssl->ctxt) { + connssl->cred->refcount++; + infof(data, "schannel: incremented credential handle refcount = %d\n", + connssl->cred->refcount); + } + + /* save the current session data for possible re-use */ + incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)); + if(incache) { + if(old_cred != connssl->cred) { + infof(data, "schannel: old credential handle is stale, removing\n"); + Curl_ssl_delsessionid(conn, (void *)old_cred); + incache = FALSE; + } + } + + if(!incache) { + result = Curl_ssl_addsessionid(conn, (void *)connssl->cred, + sizeof(struct curl_schannel_cred)); + if(result) { + failf(data, "schannel: failed to store credential handle"); + return result; + } + else { + connssl->cred->cached = TRUE; + infof(data, "schannel: stored credential handle in session cache\n"); + } + } + + connssl->connecting_state = ssl_connect_done; + + return CURLE_OK; +} + +static CURLcode +schannel_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + CURLcode result; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* check out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = schannel_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; + + what = Curl_socket_ready(readfd, writefd, nonblocking ? 0 : timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = schannel_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = schannel_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = schannel_recv; + conn->send[sockindex] = schannel_send; + *done = TRUE; + } + else + *done = FALSE; + + /* reset our connection state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static ssize_t +schannel_send(struct connectdata *conn, int sockindex, + const void *buf, size_t len, CURLcode *err) +{ + ssize_t written = -1; + size_t data_len = 0; + unsigned char *data = NULL; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SecBuffer outbuf[4]; + SecBufferDesc outbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + CURLcode result; + + /* check if the maximum stream sizes were queried */ + if(connssl->stream_sizes.cbMaximumMessage == 0) { + sspi_status = s_pSecFn->QueryContextAttributes( + &connssl->ctxt->ctxt_handle, + SECPKG_ATTR_STREAM_SIZES, + &connssl->stream_sizes); + if(sspi_status != SEC_E_OK) { + *err = CURLE_SEND_ERROR; + return -1; + } + } + + /* check if the buffer is longer than the maximum message length */ + if(len > connssl->stream_sizes.cbMaximumMessage) { + *err = CURLE_SEND_ERROR; + return -1; + } + + /* calculate the complete message length and allocate a buffer for it */ + data_len = connssl->stream_sizes.cbHeader + len + + connssl->stream_sizes.cbTrailer; + data = (unsigned char *) malloc(data_len); + if(data == NULL) { + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + + /* setup output buffers (header, data, trailer, empty) */ + InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, + data, connssl->stream_sizes.cbHeader); + InitSecBuffer(&outbuf[1], SECBUFFER_DATA, + data + connssl->stream_sizes.cbHeader, curlx_uztoul(len)); + InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, + data + connssl->stream_sizes.cbHeader + len, + connssl->stream_sizes.cbTrailer); + InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, outbuf, 4); + + /* copy data into output buffer */ + memcpy(outbuf[1].pvBuffer, buf, len); + + /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */ + sspi_status = s_pSecFn->EncryptMessage(&connssl->ctxt->ctxt_handle, 0, + &outbuf_desc, 0); + + /* check if the message was encrypted */ + if(sspi_status == SEC_E_OK) { + written = 0; + + /* send the encrypted message including header, data and trailer */ + len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; + + /* + It's important to send the full message which includes the header, + encrypted payload, and trailer. Until the client receives all the + data a coherent message has not been delivered and the client + can't read any of it. + + If we wanted to buffer the unwritten encrypted bytes, we would + tell the client that all data it has requested to be sent has been + sent. The unwritten encrypted bytes would be the first bytes to + send on the next invocation. + Here's the catch with this - if we tell the client that all the + bytes have been sent, will the client call this method again to + send the buffered data? Looking at who calls this function, it + seems the answer is NO. + */ + + /* send entire message or fail */ + while(len > (size_t)written) { + ssize_t this_write; + long timeleft; + int what; + + this_write = 0; + + timeleft = Curl_timeleft(conn->data, NULL, FALSE); + if(timeleft < 0) { + /* we already got the timeout */ + failf(conn->data, "schannel: timed out sending data " + "(bytes sent: %zd)", written); + *err = CURLE_OPERATION_TIMEDOUT; + written = -1; + break; + } + + what = Curl_socket_ready(CURL_SOCKET_BAD, conn->sock[sockindex], + timeleft); + if(what < 0) { + /* fatal error */ + failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + *err = CURLE_SEND_ERROR; + written = -1; + break; + } + else if(0 == what) { + failf(conn->data, "schannel: timed out sending data " + "(bytes sent: %zd)", written); + *err = CURLE_OPERATION_TIMEDOUT; + written = -1; + break; + } + /* socket is writable */ + + result = Curl_write_plain(conn, conn->sock[sockindex], data + written, + len - written, &this_write); + if(result == CURLE_AGAIN) + continue; + else if(result != CURLE_OK) { + *err = result; + written = -1; + break; + } + + written += this_write; + } + } + else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) { + *err = CURLE_OUT_OF_MEMORY; + } + else{ + *err = CURLE_SEND_ERROR; + } + + Curl_safefree(data); + + if(len == (size_t)written) + /* Encrypted message including header, data and trailer entirely sent. + The return value is the number of unencrypted bytes that were sent. */ + written = outbuf[1].cbBuffer; + + return written; +} + +static ssize_t +schannel_recv(struct connectdata *conn, int sockindex, + char *buf, size_t len, CURLcode *err) +{ + size_t size = 0; + ssize_t nread = 0, ret = -1; + CURLcode result; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned char *reallocated_buffer; + size_t reallocated_length; + bool done = FALSE; + SecBuffer inbuf[4]; + SecBufferDesc inbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + + infof(data, "schannel: client wants to read %zu bytes\n", len); + *err = CURLE_OK; + + /* buffer to store previously received and decrypted data */ + if(connssl->decdata_buffer == NULL) { + connssl->decdata_offset = 0; + connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; + connssl->decdata_buffer = malloc(connssl->decdata_length); + if(connssl->decdata_buffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + } + + /* increase buffer in order to fit the requested amount of data */ + if(connssl->encdata_length - connssl->encdata_offset < + CURL_SCHANNEL_BUFFER_FREE_SIZE || connssl->encdata_length < len) { + /* increase internal encrypted data buffer */ + reallocated_length = connssl->encdata_offset + + CURL_SCHANNEL_BUFFER_FREE_SIZE; + /* make sure that the requested amount of data fits */ + if(reallocated_length < len) { + reallocated_length = len; + } + reallocated_buffer = realloc(connssl->encdata_buffer, + reallocated_length); + + if(reallocated_buffer == NULL) { + failf(data, "schannel: unable to re-allocate memory"); + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + else { + connssl->encdata_buffer = reallocated_buffer; + connssl->encdata_length = reallocated_length; + } + } + + /* read encrypted data from socket */ + infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", + connssl->encdata_offset, connssl->encdata_length); + size = connssl->encdata_length - connssl->encdata_offset; + if(size > 0) { + *err = Curl_read_plain(conn->sock[sockindex], + (char *) (connssl->encdata_buffer + connssl->encdata_offset), + size, &nread); + /* check for received data */ + if(*err != CURLE_OK) + ret = -1; + else { + if(nread > 0) + /* increase encrypted data buffer offset */ + connssl->encdata_offset += nread; + ret = nread; + } + infof(data, "schannel: encrypted data got %zd\n", ret); + } + + infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", + connssl->encdata_offset, connssl->encdata_length); + + /* check if we still have some data in our buffers */ + while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK && + connssl->decdata_offset < len) { + /* prepare data buffer for DecryptMessage call */ + InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer, + curlx_uztoul(connssl->encdata_offset)); + + /* we need 3 more empty input buffers for possible output */ + InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); + InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0); + InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0); + + InitSecBufferDesc(&inbuf_desc, inbuf, 4); + + /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx */ + sspi_status = s_pSecFn->DecryptMessage(&connssl->ctxt->ctxt_handle, + &inbuf_desc, 0, NULL); + + /* check if we need more data */ + if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + infof(data, "schannel: failed to decrypt data, need more data\n"); + *err = CURLE_AGAIN; + return -1; + } + + /* check if everything went fine (server may want to renegotiate + or shutdown the connection context) */ + if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE || + sspi_status == SEC_I_CONTEXT_EXPIRED) { + /* check for successfully decrypted data, even before actual + renegotiation or shutdown of the connection context */ + if(inbuf[1].BufferType == SECBUFFER_DATA) { + infof(data, "schannel: decrypted data length: %lu\n", + inbuf[1].cbBuffer); + + /* increase buffer in order to fit the received amount of data */ + size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? + inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE; + if(connssl->decdata_length - connssl->decdata_offset < size || + connssl->decdata_length < len) { + /* increase internal decrypted data buffer */ + reallocated_length = connssl->decdata_offset + size; + /* make sure that the requested amount of data fits */ + if(reallocated_length < len) { + reallocated_length = len; + } + reallocated_buffer = realloc(connssl->decdata_buffer, + reallocated_length); + + if(reallocated_buffer == NULL) { + failf(data, "schannel: unable to re-allocate memory"); + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + else { + connssl->decdata_buffer = reallocated_buffer; + connssl->decdata_length = reallocated_length; + } + } + + /* copy decrypted data to internal buffer */ + size = inbuf[1].cbBuffer; + if(size > 0) { + memcpy(connssl->decdata_buffer + connssl->decdata_offset, + inbuf[1].pvBuffer, size); + connssl->decdata_offset += size; + } + + infof(data, "schannel: decrypted data added: %zu\n", size); + infof(data, "schannel: decrypted data cached: offset %zu length %zu\n", + connssl->decdata_offset, connssl->decdata_length); + } + + /* check for remaining encrypted data */ + if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { + infof(data, "schannel: encrypted data length: %lu\n", + inbuf[3].cbBuffer); + + /* check if the remaining data is less than the total amount + * and therefore begins after the already processed data + */ + if(connssl->encdata_offset > inbuf[3].cbBuffer) { + /* move remaining encrypted data forward to the beginning of + buffer */ + memmove(connssl->encdata_buffer, + (connssl->encdata_buffer + connssl->encdata_offset) - + inbuf[3].cbBuffer, inbuf[3].cbBuffer); + connssl->encdata_offset = inbuf[3].cbBuffer; + } + + infof(data, "schannel: encrypted data cached: offset %zu length %zu\n", + connssl->encdata_offset, connssl->encdata_length); + } + else{ + /* reset encrypted buffer offset, because there is no data remaining */ + connssl->encdata_offset = 0; + } + } + + /* check if server wants to renegotiate the connection context */ + if(sspi_status == SEC_I_RENEGOTIATE) { + infof(data, "schannel: remote party requests SSL/TLS renegotiation\n"); + + /* begin renegotiation */ + infof(data, "schannel: renegotiating SSL/TLS connection\n"); + connssl->state = ssl_connection_negotiating; + connssl->connecting_state = ssl_connect_2_writing; + result = schannel_connect_common(conn, sockindex, FALSE, &done); + if(result) + *err = result; + else { + infof(data, "schannel: SSL/TLS connection renegotiated\n"); + /* now retry receiving data */ + return schannel_recv(conn, sockindex, buf, len, err); + } + } + } + + infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", + connssl->decdata_offset, connssl->decdata_length); + + /* copy requested decrypted data to supplied buffer */ + size = len < connssl->decdata_offset ? len : connssl->decdata_offset; + if(size > 0) { + memcpy(buf, connssl->decdata_buffer, size); + ret = size; + + /* move remaining decrypted data forward to the beginning of buffer */ + memmove(connssl->decdata_buffer, connssl->decdata_buffer + size, + connssl->decdata_offset - size); + connssl->decdata_offset -= size; + + infof(data, "schannel: decrypted data returned %zd\n", size); + infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", + connssl->decdata_offset, connssl->decdata_length); + } + else + ret = 0; + + /* check if the server closed the connection */ + if(ret <= 0 && ( /* special check for Windows 2000 Professional */ + sspi_status == SEC_I_CONTEXT_EXPIRED || (sspi_status == SEC_E_OK && + connssl->encdata_offset > 0 && connssl->encdata_buffer[0] == 0x15))) { + infof(data, "schannel: server closed the connection\n"); + *err = CURLE_OK; + return 0; + } + + /* check if something went wrong and we need to return an error */ + if(ret < 0 && sspi_status != SEC_E_OK) { + infof(data, "schannel: failed to read data from server: %s\n", + Curl_sspi_strerror(conn, sspi_status)); + *err = CURLE_RECV_ERROR; + return -1; + } + + return ret; +} + +CURL_STATIC CURLcode +Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + return schannel_connect_common(conn, sockindex, TRUE, done); +} + +CURL_STATIC CURLcode +Curl_schannel_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = schannel_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +CURL_STATIC bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->use) /* SSL/TLS is in use */ + return (connssl->encdata_offset > 0 || + connssl->decdata_offset > 0 ) ? TRUE : FALSE; + else + return FALSE; +} + +CURL_STATIC void Curl_schannel_close(struct connectdata *conn, int sockindex) +{ + if(conn->ssl[sockindex].use) + /* if the SSL/TLS channel hasn't been shut down yet, do that now. */ + Curl_ssl_shutdown(conn, sockindex); +} + +CURL_STATIC int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) +{ + /* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx + * Shutting Down an Schannel Connection + */ + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", + conn->host.name, conn->remote_port); + + if(connssl->cred && connssl->ctxt) { + SecBufferDesc BuffDesc; + SecBuffer Buffer; + SECURITY_STATUS sspi_status; + SecBuffer outbuf; + SecBufferDesc outbuf_desc; + CURLcode result; + TCHAR *host_name; + DWORD dwshut = SCHANNEL_SHUTDOWN; + + InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); + InitSecBufferDesc(&BuffDesc, &Buffer, 1); + + sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle, + &BuffDesc); + + if(sspi_status != SEC_E_OK) + failf(data, "schannel: ApplyControlToken failure: %s", + Curl_sspi_strerror(conn, sspi_status)); + + host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* setup output buffer */ + InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, &outbuf, 1); + + sspi_status = s_pSecFn->InitializeSecurityContext( + &connssl->cred->cred_handle, + &connssl->ctxt->ctxt_handle, + host_name, + connssl->req_flags, + 0, + 0, + NULL, + 0, + &connssl->ctxt->ctxt_handle, + &outbuf_desc, + &connssl->ret_flags, + &connssl->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { + /* send close message which is in output buffer */ + ssize_t written; + result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + outbuf.cbBuffer, &written); + + s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); + if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { + infof(data, "schannel: failed to send close msg: %s" + " (bytes written: %zd)\n", curl_easy_strerror(result), written); + } + } + } + + /* free SSPI Schannel API security context handle */ + if(connssl->ctxt) { + infof(data, "schannel: clear security context handle\n"); + s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle); + Curl_safefree(connssl->ctxt); + } + + /* free SSPI Schannel API credential handle */ + if(connssl->cred) { + /* decrement the reference counter of the credential/session handle */ + if(connssl->cred->refcount > 0) { + connssl->cred->refcount--; + infof(data, "schannel: decremented credential handle refcount = %d\n", + connssl->cred->refcount); + } + + /* if the handle was not cached and the refcount is zero */ + if(!connssl->cred->cached && connssl->cred->refcount == 0) { + infof(data, "schannel: clear credential handle\n"); + s_pSecFn->FreeCredentialsHandle(&connssl->cred->cred_handle); + Curl_safefree(connssl->cred); + } + } + + /* free internal buffer for received encrypted data */ + if(connssl->encdata_buffer != NULL) { + Curl_safefree(connssl->encdata_buffer); + connssl->encdata_length = 0; + connssl->encdata_offset = 0; + } + + /* free internal buffer for received decrypted data */ + if(connssl->decdata_buffer != NULL) { + Curl_safefree(connssl->decdata_buffer); + connssl->decdata_length = 0; + connssl->decdata_offset = 0; + } + + return CURLE_OK; +} + +CURL_STATIC void Curl_schannel_session_free(void *ptr) +{ + struct curl_schannel_cred *cred = ptr; + + if(cred && cred->cached) { + if(cred->refcount == 0) { + s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); + Curl_safefree(cred); + } + else { + cred->cached = FALSE; + } + } +} + +CURL_STATIC int Curl_schannel_init(void) +{ + return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0); +} + +CURL_STATIC void Curl_schannel_cleanup(void) +{ + Curl_sspi_global_cleanup(); +} + +CURL_STATIC size_t Curl_schannel_version(char *buffer, size_t size) +{ + size = snprintf(buffer, size, "WinSSL"); + + return size; +} + +CURL_STATIC int Curl_schannel_random(unsigned char *entropy, size_t length) +{ + HCRYPTPROV hCryptProv = 0; + + if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + return 1; + + if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) { + CryptReleaseContext(hCryptProv, 0UL); + return 1; + } + + CryptReleaseContext(hCryptProv, 0UL); + return 0; +} + +#ifdef _WIN32_WCE +static CURLcode verify_certificate(struct connectdata *conn, int sockindex) +{ + SECURITY_STATUS status; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CURLcode result = CURLE_OK; + CERT_CONTEXT *pCertContextServer = NULL; + const CERT_CHAIN_CONTEXT *pChainContext = NULL; + + status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); + + if((status != SEC_E_OK) || (pCertContextServer == NULL)) { + failf(data, "schannel: Failed to read remote certificate context: %s", + Curl_sspi_strerror(conn, status)); + result = CURLE_PEER_FAILED_VERIFICATION; + } + + if(result == CURLE_OK) { + CERT_CHAIN_PARA ChainPara; + memset(&ChainPara, 0, sizeof(ChainPara)); + ChainPara.cbSize = sizeof(ChainPara); + + if(!CertGetCertificateChain(NULL, + pCertContextServer, + NULL, + pCertContextServer->hCertStore, + &ChainPara, + 0, + NULL, + &pChainContext)) { + failf(data, "schannel: CertGetCertificateChain failed: %s", + Curl_sspi_strerror(conn, GetLastError())); + pChainContext = NULL; + result = CURLE_PEER_FAILED_VERIFICATION; + } + + if(result == CURLE_OK) { + CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0]; + DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED| + CERT_TRUST_REVOCATION_STATUS_UNKNOWN); + dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; + if(dwTrustErrorMask) { + if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_PARTIAL_CHAIN"); + if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_UNTRUSTED_ROOT"); + if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_NOT_TIME_VALID"); + failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x", + dwTrustErrorMask); + result = CURLE_PEER_FAILED_VERIFICATION; + } + } + } + + if(result == CURLE_OK) { + if(data->set.ssl.verifyhost) { + TCHAR cert_hostname_buff[128]; + xcharp_u hostname; + xcharp_u cert_hostname; + DWORD len; + + cert_hostname.const_tchar_ptr = cert_hostname_buff; + hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name); + + len = CertGetNameString(pCertContextServer, + CERT_NAME_DNS_TYPE, + 0, + NULL, + cert_hostname.tchar_ptr, + 128); + if(len > 0 && *cert_hostname.tchar_ptr == '*') { + /* this is a wildcard cert. try matching the last len - 1 chars */ + int hostname_len = strlen(conn->host.name); + cert_hostname.tchar_ptr++; + if(_tcsicmp(cert_hostname.const_tchar_ptr, + hostname.const_tchar_ptr + hostname_len - len + 2) != 0) + result = CURLE_PEER_FAILED_VERIFICATION; + } + else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr, + cert_hostname.const_tchar_ptr) != 0) { + result = CURLE_PEER_FAILED_VERIFICATION; + } + if(result == CURLE_PEER_FAILED_VERIFICATION) { + char *_cert_hostname; + _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr); + failf(data, "schannel: CertGetNameString() certificate hostname " + "(%s) did not match connection (%s)", + _cert_hostname, conn->host.name); + Curl_unicodefree(_cert_hostname); + } + Curl_unicodefree(hostname.tchar_ptr); + } + } + + if(pChainContext) + CertFreeCertificateChain(pChainContext); + + if(pCertContextServer) + CertFreeCertificateContext(pCertContextServer); + + return result; +} +#endif /* _WIN32_WCE */ + +#endif /* USE_SCHANNEL */ diff --git a/libcurl/src/lib/vtls/schannel.h b/libcurl/src/lib/vtls/schannel.h new file mode 100644 index 0000000..e48dd97 --- /dev/null +++ b/libcurl/src/lib/vtls/schannel.h @@ -0,0 +1,117 @@ +#ifndef HEADER_CURL_SCHANNEL_H +#define HEADER_CURL_SCHANNEL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Marc Hoersken, , et al. + * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "../curl_setup.h" + +#ifdef USE_SCHANNEL + +#include "../urldata.h" + +#ifndef UNISP_NAME_A +#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider" +#endif + +#ifndef UNISP_NAME_W +#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider" +#endif + +#ifndef UNISP_NAME +#ifdef UNICODE +#define UNISP_NAME UNISP_NAME_W +#else +#define UNISP_NAME UNISP_NAME_A +#endif +#endif + +#ifndef SP_PROT_SSL2_CLIENT +#define SP_PROT_SSL2_CLIENT 0x00000008 +#endif + +#ifndef SP_PROT_SSL3_CLIENT +#define SP_PROT_SSL3_CLIENT 0x00000008 +#endif + +#ifndef SP_PROT_TLS1_CLIENT +#define SP_PROT_TLS1_CLIENT 0x00000080 +#endif + +#ifndef SP_PROT_TLS1_0_CLIENT +#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT +#endif + +#ifndef SP_PROT_TLS1_1_CLIENT +#define SP_PROT_TLS1_1_CLIENT 0x00000200 +#endif + +#ifndef SP_PROT_TLS1_2_CLIENT +#define SP_PROT_TLS1_2_CLIENT 0x00000800 +#endif + +#ifndef SECBUFFER_ALERT +#define SECBUFFER_ALERT 17 +#endif + +#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096 +#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024 + + +CURL_STATIC CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex); + +CURL_STATIC CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); + +CURL_STATIC bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex); +CURL_STATIC void Curl_schannel_close(struct connectdata *conn, int sockindex); +CURL_STATIC int Curl_schannel_shutdown(struct connectdata *conn, int sockindex); +CURL_STATIC void Curl_schannel_session_free(void *ptr); + +CURL_STATIC int Curl_schannel_init(void); +CURL_STATIC void Curl_schannel_cleanup(void); +CURL_STATIC size_t Curl_schannel_version(char *buffer, size_t size); + +CURL_STATIC int Curl_schannel_random(unsigned char *entropy, size_t length); + +/* Set the API backend definition to Schannel */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL + +/* API setup for Schannel */ +#define curlssl_init Curl_schannel_init +#define curlssl_cleanup Curl_schannel_cleanup +#define curlssl_connect Curl_schannel_connect +#define curlssl_connect_nonblocking Curl_schannel_connect_nonblocking +#define curlssl_session_free Curl_schannel_session_free +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_schannel_close +#define curlssl_shutdown Curl_schannel_shutdown +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_schannel_version +#define curlssl_check_cxn(x) ((void)x, -1) +#define curlssl_data_pending Curl_schannel_data_pending +#define curlssl_random(x,y,z) ((void)x, Curl_schannel_random(y,z)) + +#endif /* USE_SCHANNEL */ +#endif /* HEADER_CURL_SCHANNEL_H */ diff --git a/libcurl/src/lib/vtls/vtls.c b/libcurl/src/lib/vtls/vtls.c new file mode 100644 index 0000000..b7f7059 --- /dev/null +++ b/libcurl/src/lib/vtls/vtls.c @@ -0,0 +1,895 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * + * 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. + * + ***************************************************************************/ + +/* This file is for implementing all "generic" SSL functions that all libcurl + internals should use. It is then responsible for calling the proper + "backend" function. + + SSL-functions in libcurl should call functions in this source file, and not + to any specific SSL-layer. + + Curl_ssl_ - prefix for generic ones + Curl_ossl_ - prefix for OpenSSL ones + Curl_gtls_ - prefix for GnuTLS ones + Curl_nss_ - prefix for NSS ones + Curl_gskit_ - prefix for GSKit ones + Curl_polarssl_ - prefix for PolarSSL ones + Curl_cyassl_ - prefix for CyaSSL ones + Curl_schannel_ - prefix for Schannel SSPI ones + Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones + + Note that this source code uses curlssl_* functions, and they are all + defines/macros #defined by the lib-specific header files. + + "SSL/TLS Strong Encryption: An Introduction" + http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html +*/ + +#include "../curl_setup.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#include "../urldata.h" + +#include "vtls.h" /* generic SSL protos etc */ +#include "../slist.h" +#include "../sendf.h" +#include "../rawstr.h" +#include "../url.h" +#include "../progress.h" +#include "../share.h" +#include "../timeval.h" +#include "../curl_md5.h" +#include "../warnless.h" +#include "../curl_base64.h" +#include "../curl_printf.h" + +/* The last #include files should be: */ +#include "../curl_memory.h" +#include "../memdebug.h" + +/* convenience macro to check if this handle is using a shared SSL session */ +#define SSLSESSION_SHARED(data) (data->share && \ + (data->share->specifier & \ + (1<version == needle->version) && + (data->verifypeer == needle->verifypeer) && + (data->verifyhost == needle->verifyhost) && + safe_strequal(data->CApath, needle->CApath) && + safe_strequal(data->CAfile, needle->CAfile) && + safe_strequal(data->random_file, needle->random_file) && + safe_strequal(data->egdsocket, needle->egdsocket) && + safe_strequal(data->cipher_list, needle->cipher_list)) + return TRUE; + + return FALSE; +} + +CURL_STATIC bool +Curl_clone_ssl_config(struct ssl_config_data *source, + struct ssl_config_data *dest) +{ + dest->sessionid = source->sessionid; + dest->verifyhost = source->verifyhost; + dest->verifypeer = source->verifypeer; + dest->version = source->version; + + if(source->CAfile) { + dest->CAfile = strdup(source->CAfile); + if(!dest->CAfile) + return FALSE; + } + else + dest->CAfile = NULL; + + if(source->CApath) { + dest->CApath = strdup(source->CApath); + if(!dest->CApath) + return FALSE; + } + else + dest->CApath = NULL; + + if(source->cipher_list) { + dest->cipher_list = strdup(source->cipher_list); + if(!dest->cipher_list) + return FALSE; + } + else + dest->cipher_list = NULL; + + if(source->egdsocket) { + dest->egdsocket = strdup(source->egdsocket); + if(!dest->egdsocket) + return FALSE; + } + else + dest->egdsocket = NULL; + + if(source->random_file) { + dest->random_file = strdup(source->random_file); + if(!dest->random_file) + return FALSE; + } + else + dest->random_file = NULL; + + return TRUE; +} + +CURL_STATIC void Curl_free_ssl_config(struct ssl_config_data* sslc) +{ + Curl_safefree(sslc->CAfile); + Curl_safefree(sslc->CApath); + Curl_safefree(sslc->cipher_list); + Curl_safefree(sslc->egdsocket); + Curl_safefree(sslc->random_file); +} + + +/* + * Curl_rand() returns a random unsigned integer, 32bit. + * + * This non-SSL function is put here only because this file is the only one + * with knowledge of what the underlying SSL libraries provide in terms of + * randomizers. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ + +CURL_STATIC unsigned int Curl_rand(struct SessionHandle *data) +{ + unsigned int r = 0; + static unsigned int randseed; + static bool seeded = FALSE; + +#ifdef CURLDEBUG + char *force_entropy = getenv("CURL_ENTROPY"); + if(force_entropy) { + if(!seeded) { + size_t elen = strlen(force_entropy); + size_t clen = sizeof(randseed); + size_t min = elen < clen ? elen : clen; + memcpy((char *)&randseed, force_entropy, min); + seeded = TRUE; + } + else + randseed++; + return randseed; + } +#endif + + /* data may be NULL! */ + if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r))) + return r; + + /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we + instead perform a "best effort" */ + +#ifdef RANDOM_FILE + if(!seeded) { + /* if there's a random file to read a seed from, use it */ + int fd = open(RANDOM_FILE, O_RDONLY); + if(fd > -1) { + /* read random data into the randseed variable */ + ssize_t nread = read(fd, &randseed, sizeof(randseed)); + if(nread == sizeof(randseed)) + seeded = TRUE; + close(fd); + } + } +#endif + + if(!seeded) { + struct timeval now = curlx_tvnow(); + infof(data, "WARNING: Using weak random seed\n"); + randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + seeded = TRUE; + } + + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + return (r << 16) | ((r >> 16) & 0xFFFF); +} + +CURL_STATIC int Curl_ssl_backend(void) +{ + return (int)CURL_SSL_BACKEND; +} + +#ifdef USE_SSL + +/* "global" init done? */ +static bool init_ssl=FALSE; + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +CURL_STATIC int Curl_ssl_init(void) +{ + /* make sure this is only done once */ + if(init_ssl) + return 1; + init_ssl = TRUE; /* never again */ + + return curlssl_init(); +} + + +/* Global cleanup */ +CURL_STATIC void Curl_ssl_cleanup(void) +{ + if(init_ssl) { + /* only cleanup if we did a previous init */ + curlssl_cleanup(); + init_ssl = FALSE; + } +} + +static bool ssl_prefs_check(struct SessionHandle *data) +{ + /* check for CURLOPT_SSLVERSION invalid parameter value */ + if((data->set.ssl.version < 0) + || (data->set.ssl.version >= CURL_SSLVERSION_LAST)) { + failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION"); + return FALSE; + } + return TRUE; +} + +CURL_STATIC CURLcode +Curl_ssl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + + if(!ssl_prefs_check(conn->data)) + return CURLE_SSL_CONNECT_ERROR; + + /* mark this is being ssl-enabled from here on. */ + conn->ssl[sockindex].use = TRUE; + conn->ssl[sockindex].state = ssl_connection_negotiating; + + result = curlssl_connect(conn, sockindex); + + if(!result) + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + + return result; +} + +CURL_STATIC CURLcode +Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + CURLcode result; + + if(!ssl_prefs_check(conn->data)) + return CURLE_SSL_CONNECT_ERROR; + + /* mark this is being ssl requested from here on. */ + conn->ssl[sockindex].use = TRUE; +#ifdef curlssl_connect_nonblocking + result = curlssl_connect_nonblocking(conn, sockindex, done); +#else + *done = TRUE; /* fallback to BLOCKING */ + result = curlssl_connect(conn, sockindex); +#endif /* non-blocking connect support */ + if(!result && *done) + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + return result; +} + +/* + * Check if there's a session ID for the given connection in the cache, and if + * there's one suitable, it is provided. Returns TRUE when no entry matched. + */ +CURL_STATIC bool Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize) /* set 0 if unknown */ +{ + struct curl_ssl_session *check; + struct SessionHandle *data = conn->data; + size_t i; + long *general_age; + bool no_match = TRUE; + + *ssl_sessionid = NULL; + + if(!conn->ssl_config.sessionid) + /* session ID re-use is disabled */ + return TRUE; + + /* Lock if shared */ + if(SSLSESSION_SHARED(data)) { + Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); + general_age = &data->share->sessionage; + } + else + general_age = &data->state.sessionage; + + for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { + check = &data->state.session[i]; + if(!check->sessionid) + /* not session ID means blank entry */ + continue; + if(Curl_raw_equal(conn->host.name, check->name) && + (conn->remote_port == check->remote_port) && + Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { + /* yes, we have a session ID! */ + (*general_age)++; /* increase general age */ + check->age = *general_age; /* set this as used in this age */ + *ssl_sessionid = check->sessionid; + if(idsize) + *idsize = check->idsize; + no_match = FALSE; + break; + } + } + + /* Unlock */ + if(SSLSESSION_SHARED(data)) + Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); + + return no_match; +} + +/* + * Kill a single session ID entry in the cache. + */ +CURL_STATIC void Curl_ssl_kill_session(struct curl_ssl_session *session) +{ + if(session->sessionid) { + /* defensive check */ + + /* free the ID the SSL-layer specific way */ + curlssl_session_free(session->sessionid); + + session->sessionid = NULL; + session->age = 0; /* fresh */ + + Curl_free_ssl_config(&session->ssl_config); + + Curl_safefree(session->name); + } +} + +/* + * Delete the given session ID from the cache. + */ +CURL_STATIC void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) +{ + size_t i; + struct SessionHandle *data=conn->data; + + if(SSLSESSION_SHARED(data)) + Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); + + for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { + struct curl_ssl_session *check = &data->state.session[i]; + + if(check->sessionid == ssl_sessionid) { + Curl_ssl_kill_session(check); + break; + } + } + + if(SSLSESSION_SHARED(data)) + Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); +} + +/* + * Store session id in the session cache. The ID passed on to this function + * must already have been extracted and allocated the proper way for the SSL + * layer. Curl_XXXX_session_free() will be called to free/kill the session ID + * later on. + */ +CURL_STATIC CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize) +{ + size_t i; + struct SessionHandle *data=conn->data; /* the mother of all structs */ + struct curl_ssl_session *store = &data->state.session[0]; + long oldest_age=data->state.session[0].age; /* zero if unused */ + char *clone_host; + long *general_age; + + /* Even though session ID re-use might be disabled, that only disables USING + IT. We still store it here in case the re-using is again enabled for an + upcoming transfer */ + + clone_host = strdup(conn->host.name); + if(!clone_host) + return CURLE_OUT_OF_MEMORY; /* bail out */ + + /* Now we should add the session ID and the host name to the cache, (remove + the oldest if necessary) */ + + /* If using shared SSL session, lock! */ + if(SSLSESSION_SHARED(data)) { + Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); + general_age = &data->share->sessionage; + } + else { + general_age = &data->state.sessionage; + } + + /* find an empty slot for us, or find the oldest */ + for(i = 1; (i < data->set.ssl.max_ssl_sessions) && + data->state.session[i].sessionid; i++) { + if(data->state.session[i].age < oldest_age) { + oldest_age = data->state.session[i].age; + store = &data->state.session[i]; + } + } + if(i == data->set.ssl.max_ssl_sessions) + /* cache is full, we must "kill" the oldest entry! */ + Curl_ssl_kill_session(store); + else + store = &data->state.session[i]; /* use this slot */ + + /* now init the session struct wisely */ + store->sessionid = ssl_sessionid; + store->idsize = idsize; + store->age = *general_age; /* set current age */ + /* free it if there's one already present */ + free(store->name); + store->name = clone_host; /* clone host name */ + store->remote_port = conn->remote_port; /* port number */ + + + /* Unlock */ + if(SSLSESSION_SHARED(data)) + Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); + + if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { + store->sessionid = NULL; /* let caller free sessionid */ + free(clone_host); + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + + +CURL_STATIC void Curl_ssl_close_all(struct SessionHandle *data) +{ + size_t i; + /* kill the session ID cache if not shared */ + if(data->state.session && !SSLSESSION_SHARED(data)) { + for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) + /* the single-killer function handles empty table slots */ + Curl_ssl_kill_session(&data->state.session[i]); + + /* free the cache data */ + Curl_safefree(data->state.session); + } + + curlssl_close_all(data); +} + +CURL_STATIC void Curl_ssl_close(struct connectdata *conn, int sockindex) +{ + DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); + curlssl_close(conn, sockindex); +} + +CURL_STATIC CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) +{ + if(curlssl_shutdown(conn, sockindex)) + return CURLE_SSL_SHUTDOWN_FAILED; + + conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ + conn->ssl[sockindex].state = ssl_connection_none; + + conn->recv[sockindex] = Curl_recv_plain; + conn->send[sockindex] = Curl_send_plain; + + return CURLE_OK; +} + +/* Selects an SSL crypto engine + */ +CURL_STATIC CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine) +{ + return curlssl_set_engine(data, engine); +} + +/* Selects the default SSL crypto engine + */ +CURL_STATIC CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data) +{ + return curlssl_set_engine_default(data); +} + +/* Return list of OpenSSL crypto engine names. */ +CURL_STATIC struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data) +{ + return curlssl_engines_list(data); +} + +/* + * This sets up a session ID cache to the specified size. Make sure this code + * is agnostic to what underlying SSL technology we use. + */ +CURL_STATIC CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount) +{ + struct curl_ssl_session *session; + + if(data->state.session) + /* this is just a precaution to prevent multiple inits */ + return CURLE_OK; + + session = calloc(amount, sizeof(struct curl_ssl_session)); + if(!session) + return CURLE_OUT_OF_MEMORY; + + /* store the info in the SSL section */ + data->set.ssl.max_ssl_sessions = amount; + data->state.session = session; + data->state.sessionage = 1; /* this is brand new */ + return CURLE_OK; +} + +CURL_STATIC size_t Curl_ssl_version(char *buffer, size_t size) +{ + return curlssl_version(buffer, size); +} + +/* + * This function tries to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +CURL_STATIC int Curl_ssl_check_cxn(struct connectdata *conn) +{ + return curlssl_check_cxn(conn); +} + +CURL_STATIC bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex) +{ + return curlssl_data_pending(conn, connindex); +} + +CURL_STATIC void Curl_ssl_free_certinfo(struct SessionHandle *data) +{ + int i; + struct curl_certinfo *ci = &data->info.certs; + + if(ci->num_of_certs) { + /* free all individual lists used */ + for(i=0; inum_of_certs; i++) { + curl_slist_free_all(ci->certinfo[i]); + ci->certinfo[i] = NULL; + } + + free(ci->certinfo); /* free the actual array too */ + ci->certinfo = NULL; + ci->num_of_certs = 0; + } +} + +CURL_STATIC CURLcode Curl_ssl_init_certinfo(struct SessionHandle *data, int num) +{ + struct curl_certinfo *ci = &data->info.certs; + struct curl_slist **table; + + /* Free any previous certificate information structures */ + Curl_ssl_free_certinfo(data); + + /* Allocate the required certificate information structures */ + table = calloc((size_t) num, sizeof(struct curl_slist *)); + if(!table) + return CURLE_OUT_OF_MEMORY; + + ci->num_of_certs = num; + ci->certinfo = table; + + return CURLE_OK; +} + +/* + * 'value' is NOT a zero terminated string + */ +CURL_STATIC CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data, + int certnum, + const char *label, + const char *value, + size_t valuelen) +{ + struct curl_certinfo * ci = &data->info.certs; + char * output; + struct curl_slist * nl; + CURLcode result = CURLE_OK; + size_t labellen = strlen(label); + size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ + + output = malloc(outlen); + if(!output) + return CURLE_OUT_OF_MEMORY; + + /* sprintf the label and colon */ + snprintf(output, outlen, "%s:", label); + + /* memcpy the value (it might not be zero terminated) */ + memcpy(&output[labellen+1], value, valuelen); + + /* zero terminate the output */ + output[labellen + 1 + valuelen] = 0; + + nl = Curl_slist_append_nodup(ci->certinfo[certnum], output); + if(!nl) { + free(output); + curl_slist_free_all(ci->certinfo[certnum]); + result = CURLE_OUT_OF_MEMORY; + } + + ci->certinfo[certnum] = nl; + return result; +} + +/* + * This is a convenience function for push_certinfo_len that takes a zero + * terminated value. + */ +CURL_STATIC CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data, + int certnum, + const char *label, + const char *value) +{ + size_t valuelen = strlen(value); + + return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); +} + +CURL_STATIC int Curl_ssl_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length) +{ + return curlssl_random(data, entropy, length); +} + +/* + * Public key pem to der conversion + */ + +static CURLcode pubkey_pem_to_der(const char *pem, + unsigned char **der, size_t *der_len) +{ + char *stripped_pem, *begin_pos, *end_pos; + size_t pem_count, stripped_pem_count = 0, pem_len; + CURLcode result; + + /* if no pem, exit. */ + if(!pem) + return CURLE_BAD_CONTENT_ENCODING; + + begin_pos = strstr(pem, "-----BEGIN PUBLIC KEY-----"); + if(!begin_pos) + return CURLE_BAD_CONTENT_ENCODING; + + pem_count = begin_pos - pem; + /* Invalid if not at beginning AND not directly following \n */ + if(0 != pem_count && '\n' != pem[pem_count - 1]) + return CURLE_BAD_CONTENT_ENCODING; + + /* 26 is length of "-----BEGIN PUBLIC KEY-----" */ + pem_count += 26; + + /* Invalid if not directly following \n */ + end_pos = strstr(pem + pem_count, "\n-----END PUBLIC KEY-----"); + if(!end_pos) + return CURLE_BAD_CONTENT_ENCODING; + + pem_len = end_pos - pem; + + stripped_pem = malloc(pem_len - pem_count + 1); + if(!stripped_pem) + return CURLE_OUT_OF_MEMORY; + + /* + * Here we loop through the pem array one character at a time between the + * correct indices, and place each character that is not '\n' or '\r' + * into the stripped_pem array, which should represent the raw base64 string + */ + while(pem_count < pem_len) { + if('\n' != pem[pem_count] && '\r' != pem[pem_count]) + stripped_pem[stripped_pem_count++] = pem[pem_count]; + ++pem_count; + } + /* Place the null terminator in the correct place */ + stripped_pem[stripped_pem_count] = '\0'; + + result = Curl_base64_decode(stripped_pem, der, der_len); + + Curl_safefree(stripped_pem); + + return result; +} + +/* + * Generic pinned public key check. + */ + +CURL_STATIC CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey, + const unsigned char *pubkey, size_t pubkeylen) +{ + FILE *fp; + unsigned char *buf = NULL, *pem_ptr = NULL; + long filesize; + size_t size, pem_len; + CURLcode pem_read; + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + if(!pubkey || !pubkeylen) + return result; + fp = fopen(pinnedpubkey, "rb"); + if(!fp) + return result; + + do { + /* Determine the file's size */ + if(fseek(fp, 0, SEEK_END)) + break; + filesize = ftell(fp); + if(fseek(fp, 0, SEEK_SET)) + break; + if(filesize < 0 || filesize > MAX_PINNED_PUBKEY_SIZE) + break; + + /* + * if the size of our certificate is bigger than the file + * size then it can't match + */ + size = curlx_sotouz((curl_off_t) filesize); + if(pubkeylen > size) + break; + + /* + * Allocate buffer for the pinned key + * With 1 additional byte for null terminator in case of PEM key + */ + buf = malloc(size + 1); + if(!buf) + break; + + /* Returns number of elements read, which should be 1 */ + if((int) fread(buf, size, 1, fp) != 1) + break; + + /* If the sizes are the same, it can't be base64 encoded, must be der */ + if(pubkeylen == size) { + if(!memcmp(pubkey, buf, pubkeylen)) + result = CURLE_OK; + break; + } + + /* + * Otherwise we will assume it's PEM and try to decode it + * after placing null terminator + */ + buf[size] = '\0'; + pem_read = pubkey_pem_to_der((const char *)buf, &pem_ptr, &pem_len); + /* if it wasn't read successfully, exit */ + if(pem_read) + break; + + /* + * if the size of our certificate doesn't match the size of + * the decoded file, they can't be the same, otherwise compare + */ + if(pubkeylen == pem_len && !memcmp(pubkey, pem_ptr, pubkeylen)) + result = CURLE_OK; + } while(0); + + Curl_safefree(buf); + Curl_safefree(pem_ptr); + fclose(fp); + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +CURL_STATIC CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ +#ifdef curlssl_md5sum + curlssl_md5sum(tmp, tmplen, md5sum, md5len); +#else + MD5_context *MD5pw; + + (void) md5len; + + MD5pw = Curl_MD5_init(Curl_DIGEST_MD5); + if(!MD5pw) + return CURLE_OUT_OF_MEMORY; + Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen)); + Curl_MD5_final(MD5pw, md5sum); +#endif + return CURLE_OK; +} +#endif + +/* + * Check whether the SSL backend supports the status_request extension. + */ +CURL_STATIC bool Curl_ssl_cert_status_request(void) +{ +#ifdef curlssl_cert_status_request + return curlssl_cert_status_request(); +#else + return FALSE; +#endif +} + +/* + * Check whether the SSL backend supports false start. + */ +CURL_STATIC bool Curl_ssl_false_start(void) +{ +#ifdef curlssl_false_start + return curlssl_false_start(); +#else + return FALSE; +#endif +} + +#endif /* USE_SSL */ diff --git a/libcurl/src/lib/vtls/vtls.h b/libcurl/src/lib/vtls/vtls.h new file mode 100644 index 0000000..cc2503f --- /dev/null +++ b/libcurl/src/lib/vtls/vtls.h @@ -0,0 +1,153 @@ +#ifndef HEADER_CURL_VTLS_H +#define HEADER_CURL_VTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "../curl_setup.h" + +#include "openssl.h" /* OpenSSL versions */ +#include "gtls.h" /* GnuTLS versions */ +#include "nssg.h" /* NSS versions */ +#include "gskit.h" /* Global Secure ToolKit versions */ +#include "polarssl.h" /* PolarSSL versions */ +#include "axtls.h" /* axTLS versions */ +#include "cyassl.h" /* CyaSSL versions */ +#include "schannel.h" /* Schannel SSPI version */ +#include "darwinssl.h" /* SecureTransport (Darwin) version */ + +#ifndef MAX_PINNED_PUBKEY_SIZE +#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */ +#endif + +#ifndef MD5_DIGEST_LENGTH +#define MD5_DIGEST_LENGTH 16 /* fixed size */ +#endif + +/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */ +#define ALPN_HTTP_1_1_LENGTH 8 +#define ALPN_HTTP_1_1 "http/1.1" + +CURL_STATIC bool Curl_ssl_config_matches(struct ssl_config_data* data, + struct ssl_config_data* needle); +CURL_STATIC bool Curl_clone_ssl_config(struct ssl_config_data* source, + struct ssl_config_data* dest); +CURL_STATIC void Curl_free_ssl_config(struct ssl_config_data* sslc); + +CURL_STATIC unsigned int Curl_rand(struct SessionHandle *); + +CURL_STATIC int Curl_ssl_backend(void); + +#ifdef USE_SSL +CURL_STATIC int Curl_ssl_init(void); +CURL_STATIC void Curl_ssl_cleanup(void); +CURL_STATIC CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); +CURL_STATIC CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +/* tell the SSL stuff to close down all open information regarding + connections (and thus session ID caching etc) */ +CURL_STATIC void Curl_ssl_close_all(struct SessionHandle *data); +CURL_STATIC void Curl_ssl_close(struct connectdata *conn, int sockindex); +CURL_STATIC CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); +CURL_STATIC CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine); +/* Sets engine as default for all SSL operations */ +CURL_STATIC CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data); +CURL_STATIC struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data); + +/* init the SSL session ID cache */ +CURL_STATIC CURLcode Curl_ssl_initsessions(struct SessionHandle *, size_t); +CURL_STATIC size_t Curl_ssl_version(char *buffer, size_t size); +CURL_STATIC bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex); +CURL_STATIC int Curl_ssl_check_cxn(struct connectdata *conn); + +/* Certificate information list handling. */ + +CURL_STATIC void Curl_ssl_free_certinfo(struct SessionHandle *data); +CURL_STATIC CURLcode Curl_ssl_init_certinfo(struct SessionHandle * data, int num); +CURL_STATIC CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle * data, int certnum, + const char * label, const char * value, + size_t valuelen); +CURL_STATIC CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum, + const char * label, const char * value); + +/* Functions to be used by SSL library adaptation functions */ + +/* extract a session ID */ +CURL_STATIC bool Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize) /* set 0 if unknown */; +/* add a new session ID */ +CURL_STATIC CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize); +/* Kill a single session ID entry in the cache */ +CURL_STATIC void Curl_ssl_kill_session(struct curl_ssl_session *session); +/* delete a session from the cache */ +CURL_STATIC void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); + +/* get N random bytes into the buffer, return 0 if a find random is filled + in */ +CURL_STATIC int Curl_ssl_random(struct SessionHandle *data, unsigned char *buffer, + size_t length); +CURL_STATIC CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); +/* Check pinned public key. */ +CURL_STATIC CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey, + const unsigned char *pubkey, size_t pubkeylen); + +CURL_STATIC bool Curl_ssl_cert_status_request(void); + +CURL_STATIC bool Curl_ssl_false_start(void); + +#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ + +#else +/* Set the API backend definition to none */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_NONE + +/* When SSL support is not present, just define away these function calls */ +#define Curl_ssl_init() 1 +#define Curl_ssl_cleanup() Curl_nop_stmt +#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_close_all(x) Curl_nop_stmt +#define Curl_ssl_close(x,y) Curl_nop_stmt +#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN +#define Curl_ssl_engines_list(x) NULL +#define Curl_ssl_send(a,b,c,d,e) -1 +#define Curl_ssl_recv(a,b,c,d,e) -1 +#define Curl_ssl_initsessions(x,y) CURLE_OK +#define Curl_ssl_version(x,y) 0 +#define Curl_ssl_data_pending(x,y) 0 +#define Curl_ssl_check_cxn(x) 0 +#define Curl_ssl_free_certinfo(x) Curl_nop_stmt +#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN +#define Curl_ssl_kill_session(x) Curl_nop_stmt +#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_ssl_cert_status_request() FALSE +#define Curl_ssl_false_start() FALSE +#endif + +#endif /* HEADER_CURL_VTLS_H */ diff --git a/libcurl/src/lib/warnless.c b/libcurl/src/lib/warnless.c new file mode 100644 index 0000000..7e4415e --- /dev/null +++ b/libcurl/src/lib/warnless.c @@ -0,0 +1,486 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#endif /* __INTEL_COMPILER && __unix__ */ + +#define BUILDING_WARNLESS_C 1 + +#include "warnless.h" + +#define CURL_MASK_SCHAR 0x7F +#define CURL_MASK_UCHAR 0xFF + +#if (SIZEOF_SHORT == 2) +# define CURL_MASK_SSHORT 0x7FFF +# define CURL_MASK_USHORT 0xFFFF +#elif (SIZEOF_SHORT == 4) +# define CURL_MASK_SSHORT 0x7FFFFFFF +# define CURL_MASK_USHORT 0xFFFFFFFF +#elif (SIZEOF_SHORT == 8) +# define CURL_MASK_SSHORT 0x7FFFFFFFFFFFFFFF +# define CURL_MASK_USHORT 0xFFFFFFFFFFFFFFFF +#else +# error "SIZEOF_SHORT not defined" +#endif + +#if (SIZEOF_INT == 2) +# define CURL_MASK_SINT 0x7FFF +# define CURL_MASK_UINT 0xFFFF +#elif (SIZEOF_INT == 4) +# define CURL_MASK_SINT 0x7FFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFF +#elif (SIZEOF_INT == 8) +# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFF +#elif (SIZEOF_INT == 16) +# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +#else +# error "SIZEOF_INT not defined" +#endif + +#if (CURL_SIZEOF_LONG == 2) +# define CURL_MASK_SLONG 0x7FFFL +# define CURL_MASK_ULONG 0xFFFFUL +#elif (CURL_SIZEOF_LONG == 4) +# define CURL_MASK_SLONG 0x7FFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFUL +#elif (CURL_SIZEOF_LONG == 8) +# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL +#elif (CURL_SIZEOF_LONG == 16) +# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL +#else +# error "CURL_SIZEOF_LONG not defined" +#endif + +#if (CURL_SIZEOF_CURL_OFF_T == 2) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFF) +#elif (CURL_SIZEOF_CURL_OFF_T == 4) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFF) +#elif (CURL_SIZEOF_CURL_OFF_T == 8) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF) +#elif (CURL_SIZEOF_CURL_OFF_T == 16) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +#else +# error "CURL_SIZEOF_CURL_OFF_T not defined" +#endif + +#if (SIZEOF_SIZE_T == SIZEOF_SHORT) +# define CURL_MASK_SSIZE_T CURL_MASK_SSHORT +# define CURL_MASK_USIZE_T CURL_MASK_USHORT +#elif (SIZEOF_SIZE_T == SIZEOF_INT) +# define CURL_MASK_SSIZE_T CURL_MASK_SINT +# define CURL_MASK_USIZE_T CURL_MASK_UINT +#elif (SIZEOF_SIZE_T == CURL_SIZEOF_LONG) +# define CURL_MASK_SSIZE_T CURL_MASK_SLONG +# define CURL_MASK_USIZE_T CURL_MASK_ULONG +#elif (SIZEOF_SIZE_T == CURL_SIZEOF_CURL_OFF_T) +# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT +# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT +#else +# error "SIZEOF_SIZE_T not defined" +#endif + +/* +** unsigned long to unsigned short +*/ + +CURL_STATIC unsigned short curlx_ultous(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_USHORT); + return (unsigned short)(ulnum & (unsigned long) CURL_MASK_USHORT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned long to unsigned char +*/ + +CURL_STATIC unsigned char curlx_ultouc(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_UCHAR); + return (unsigned char)(ulnum & (unsigned long) CURL_MASK_UCHAR); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned long to signed int +*/ + +CURL_STATIC int curlx_ultosi(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_SINT); + return (int)(ulnum & (unsigned long) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed curl_off_t +*/ + +CURL_STATIC curl_off_t curlx_uztoso(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT); + return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed int +*/ + +CURL_STATIC int curlx_uztosi(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SINT); + return (int)(uznum & (size_t) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to unsigned long +*/ + +CURL_STATIC unsigned long curlx_uztoul(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + +#if (CURL_SIZEOF_LONG < SIZEOF_SIZE_T) + DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG); +#endif + return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to unsigned int +*/ + +CURL_STATIC unsigned int curlx_uztoui(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + +#if (SIZEOF_INT < SIZEOF_SIZE_T) + DEBUGASSERT(uznum <= (size_t) CURL_MASK_UINT); +#endif + return (unsigned int)(uznum & (size_t) CURL_MASK_UINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to signed int +*/ + +CURL_STATIC int curlx_sltosi(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); +#if (SIZEOF_INT < CURL_SIZEOF_LONG) + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT); +#endif + return (int)(slnum & (long) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to unsigned int +*/ + +CURL_STATIC unsigned int curlx_sltoui(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); +#if (SIZEOF_INT < CURL_SIZEOF_LONG) + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT); +#endif + return (unsigned int)(slnum & (long) CURL_MASK_UINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to unsigned short +*/ + +CURL_STATIC unsigned short curlx_sltous(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_USHORT); + return (unsigned short)(slnum & (long) CURL_MASK_USHORT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed ssize_t +*/ + +CURL_STATIC ssize_t curlx_uztosz(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SSIZE_T); + return (ssize_t)(uznum & (size_t) CURL_MASK_SSIZE_T); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed curl_off_t to unsigned size_t +*/ + +CURL_STATIC size_t curlx_sotouz(curl_off_t sonum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sonum >= 0); + return (size_t)(sonum & (curl_off_t) CURL_MASK_USIZE_T); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed ssize_t to signed int +*/ + +CURL_STATIC int curlx_sztosi(ssize_t sznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sznum >= 0); +#if (SIZEOF_INT < SIZEOF_SIZE_T) + DEBUGASSERT((size_t) sznum <= (size_t) CURL_MASK_SINT); +#endif + return (int)(sznum & (ssize_t) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed int to unsigned size_t +*/ + +CURL_STATIC size_t curlx_sitouz(int sinum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sinum >= 0); + return (size_t) sinum; + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +#ifdef USE_WINSOCK + +/* +** curl_socket_t to signed int +*/ + +CURL_STATIC int curlx_sktosi(curl_socket_t s) +{ + return (int)((ssize_t) s); +} + +/* +** signed int to curl_socket_t +*/ + +CURL_STATIC curl_socket_t curlx_sitosk(int i) +{ + return (curl_socket_t)((ssize_t) i); +} + +#endif /* USE_WINSOCK */ + +#if defined(WIN32) || defined(_WIN32) + +CURL_STATIC ssize_t curlx_read(int fd, void *buf, size_t count) +{ + return (ssize_t)_read(fd, buf, curlx_uztoui(count)); +} + +CURL_STATIC ssize_t curlx_write(int fd, const void *buf, size_t count) +{ + return (ssize_t)_write(fd, buf, curlx_uztoui(count)); +} + +#endif /* WIN32 || _WIN32 */ + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +CURL_STATIC int curlx_FD_ISSET(int fd, fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:1469) /* clobber ignored */ + return FD_ISSET(fd, fdset); + #pragma warning(pop) +} + +CURL_STATIC void curlx_FD_SET(int fd, fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:1469) /* clobber ignored */ + FD_SET(fd, fdset); + #pragma warning(pop) +} + +CURL_STATIC void curlx_FD_ZERO(fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:593) /* variable was set but never used */ + FD_ZERO(fdset); + #pragma warning(pop) +} + +CURL_STATIC unsigned short curlx_htons(unsigned short usnum) +{ +#if (__INTEL_COMPILER == 910) && defined(__i386__) + return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF)); +#else + #pragma warning(push) + #pragma warning(disable:810) /* conversion may lose significant bits */ + return htons(usnum); + #pragma warning(pop) +#endif +} + +CURL_STATIC unsigned short curlx_ntohs(unsigned short usnum) +{ +#if (__INTEL_COMPILER == 910) && defined(__i386__) + return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF)); +#else + #pragma warning(push) + #pragma warning(disable:810) /* conversion may lose significant bits */ + return ntohs(usnum); + #pragma warning(pop) +#endif +} + +#endif /* __INTEL_COMPILER && __unix__ */ diff --git a/libcurl/src/lib/warnless.h b/libcurl/src/lib/warnless.h new file mode 100644 index 0000000..53fa0d6 --- /dev/null +++ b/libcurl/src/lib/warnless.h @@ -0,0 +1,107 @@ +#ifndef HEADER_CURL_WARNLESS_H +#define HEADER_CURL_WARNLESS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_WINSOCK +#include /* for curl_socket_t */ +#endif + +CURL_STATIC unsigned short curlx_ultous(unsigned long ulnum); + +CURL_STATIC unsigned char curlx_ultouc(unsigned long ulnum); + +CURL_STATIC int curlx_ultosi(unsigned long ulnum); + +CURL_STATIC int curlx_uztosi(size_t uznum); + +CURL_STATIC curl_off_t curlx_uztoso(size_t uznum); + +CURL_STATIC unsigned long curlx_uztoul(size_t uznum); + +CURL_STATIC unsigned int curlx_uztoui(size_t uznum); + +CURL_STATIC int curlx_sltosi(long slnum); + +CURL_STATIC unsigned int curlx_sltoui(long slnum); + +CURL_STATIC unsigned short curlx_sltous(long slnum); + +CURL_STATIC ssize_t curlx_uztosz(size_t uznum); + +CURL_STATIC size_t curlx_sotouz(curl_off_t sonum); + +CURL_STATIC int curlx_sztosi(ssize_t sznum); + +CURL_STATIC size_t curlx_sitouz(int sinum); + +#ifdef USE_WINSOCK + +CURL_STATIC int curlx_sktosi(curl_socket_t s); + +CURL_STATIC curl_socket_t curlx_sitosk(int i); + +#endif /* USE_WINSOCK */ + +#if defined(WIN32) || defined(_WIN32) + +CURL_STATIC ssize_t curlx_read(int fd, void *buf, size_t count); + +CURL_STATIC ssize_t curlx_write(int fd, const void *buf, size_t count); + +#ifndef BUILDING_WARNLESS_C +# undef read +# define read(fd, buf, count) curlx_read(fd, buf, count) +# undef write +# define write(fd, buf, count) curlx_write(fd, buf, count) +#endif + +#endif /* WIN32 || _WIN32 */ + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +CURL_STATIC int curlx_FD_ISSET(int fd, fd_set *fdset); + +CURL_STATIC void curlx_FD_SET(int fd, fd_set *fdset); + +CURL_STATIC void curlx_FD_ZERO(fd_set *fdset); + +CURL_STATIC unsigned short curlx_htons(unsigned short usnum); + +CURL_STATIC unsigned short curlx_ntohs(unsigned short usnum); + +#ifndef BUILDING_WARNLESS_C +# undef FD_ISSET +# define FD_ISSET(a,b) curlx_FD_ISSET((a),(b)) +# undef FD_SET +# define FD_SET(a,b) curlx_FD_SET((a),(b)) +# undef FD_ZERO +# define FD_ZERO(a) curlx_FD_ZERO((a)) +# undef htons +# define htons(a) curlx_htons((a)) +# undef ntohs +# define ntohs(a) curlx_ntohs((a)) +#endif + +#endif /* __INTEL_COMPILER && __unix__ */ + +#endif /* HEADER_CURL_WARNLESS_H */ diff --git a/libcurl/src/lib/wildcard.c b/libcurl/src/lib/wildcard.c new file mode 100644 index 0000000..a16a06a --- /dev/null +++ b/libcurl/src/lib/wildcard.c @@ -0,0 +1,69 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "wildcard.h" +#include "llist.h" +#include "fileinfo.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +CURL_STATIC CURLcode Curl_wildcard_init(struct WildcardData *wc) +{ + DEBUGASSERT(wc->filelist == NULL); + /* now allocate only wc->filelist, everything else + will be allocated if it is needed. */ + wc->filelist = Curl_llist_alloc(Curl_fileinfo_dtor); + if(!wc->filelist) {; + return CURLE_OUT_OF_MEMORY; + } + return CURLE_OK; +} + +CURL_STATIC void Curl_wildcard_dtor(struct WildcardData *wc) +{ + if(!wc) + return; + + if(wc->tmp_dtor) { + wc->tmp_dtor(wc->tmp); + wc->tmp_dtor = ZERO_NULL; + wc->tmp = NULL; + } + DEBUGASSERT(wc->tmp == NULL); + + if(wc->filelist) { + Curl_llist_destroy(wc->filelist, NULL); + wc->filelist = NULL; + } + + free(wc->path); + wc->path = NULL; + free(wc->pattern); + wc->pattern = NULL; + + wc->customptr = NULL; + wc->state = CURLWC_INIT; +} diff --git a/libcurl/src/lib/wildcard.h b/libcurl/src/lib/wildcard.h new file mode 100644 index 0000000..3a0ddbd --- /dev/null +++ b/libcurl/src/lib/wildcard.h @@ -0,0 +1,58 @@ +#ifndef HEADER_CURL_WILDCARD_H +#define HEADER_CURL_WILDCARD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +/* list of wildcard process states */ +typedef enum { + CURLWC_INIT = 0, + CURLWC_MATCHING, /* library is trying to get list of addresses for + downloading */ + CURLWC_DOWNLOADING, + CURLWC_CLEAN, /* deallocate resources and reset settings */ + CURLWC_SKIP, /* skip over concrete file */ + CURLWC_ERROR, /* error cases */ + CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop + will end */ +} curl_wildcard_states; + +typedef void (*curl_wildcard_tmp_dtor)(void *ptr); + +/* struct keeping information about wildcard download process */ +struct WildcardData { + curl_wildcard_states state; + char *path; /* path to the directory, where we trying wildcard-match */ + char *pattern; /* wildcard pattern */ + struct curl_llist *filelist; /* llist with struct Curl_fileinfo */ + void *tmp; /* pointer to protocol specific temporary data */ + curl_wildcard_tmp_dtor tmp_dtor; + void *customptr; /* for CURLOPT_CHUNK_DATA pointer */ +}; + +CURL_STATIC CURLcode Curl_wildcard_init(struct WildcardData *wc); +CURL_STATIC void Curl_wildcard_dtor(struct WildcardData *wc); + +struct SessionHandle; + +#endif /* HEADER_CURL_WILDCARD_H */ diff --git a/libcurl/src/lib/x509asn1.c b/libcurl/src/lib/x509asn1.c new file mode 100644 index 0000000..d0d6b7d --- /dev/null +++ b/libcurl/src/lib/x509asn1.c @@ -0,0 +1,1187 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) + +#include +#include "urldata.h" +#include "strequal.h" +#include "hostcheck.h" +#include "vtls/vtls.h" +#include "sendf.h" +#include "inet_pton.h" +#include "curl_base64.h" +#include "x509asn1.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + + +/* ASN.1 OIDs. */ +static const char cnOID[] = "2.5.4.3"; /* Common name. */ +static const char sanOID[] = "2.5.29.17"; /* Subject alternative name. */ + +static const curl_OID OIDtable[] = { + { "1.2.840.10040.4.1", "dsa" }, + { "1.2.840.10040.4.3", "dsa-with-sha1" }, + { "1.2.840.10045.2.1", "ecPublicKey" }, + { "1.2.840.10045.3.0.1", "c2pnb163v1" }, + { "1.2.840.10045.4.1", "ecdsa-with-SHA1" }, + { "1.2.840.10046.2.1", "dhpublicnumber" }, + { "1.2.840.113549.1.1.1", "rsaEncryption" }, + { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" }, + { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" }, + { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" }, + { "1.2.840.113549.1.1.10", "RSASSA-PSS" }, + { "1.2.840.113549.1.1.14", "sha224WithRSAEncryption" }, + { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" }, + { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" }, + { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" }, + { "1.2.840.113549.2.2", "md2" }, + { "1.2.840.113549.2.5", "md5" }, + { "1.3.14.3.2.26", "sha1" }, + { cnOID, "CN" }, + { "2.5.4.4", "SN" }, + { "2.5.4.5", "serialNumber" }, + { "2.5.4.6", "C" }, + { "2.5.4.7", "L" }, + { "2.5.4.8", "ST" }, + { "2.5.4.9", "streetAddress" }, + { "2.5.4.10", "O" }, + { "2.5.4.11", "OU" }, + { "2.5.4.12", "title" }, + { "2.5.4.13", "description" }, + { "2.5.4.17", "postalCode" }, + { "2.5.4.41", "name" }, + { "2.5.4.42", "givenName" }, + { "2.5.4.43", "initials" }, + { "2.5.4.44", "generationQualifier" }, + { "2.5.4.45", "X500UniqueIdentifier" }, + { "2.5.4.46", "dnQualifier" }, + { "2.5.4.65", "pseudonym" }, + { "1.2.840.113549.1.9.1", "emailAddress" }, + { "2.5.4.72", "role" }, + { sanOID, "subjectAltName" }, + { "2.5.29.18", "issuerAltName" }, + { "2.5.29.19", "basicConstraints" }, + { "2.16.840.1.101.3.4.2.4", "sha224" }, + { "2.16.840.1.101.3.4.2.1", "sha256" }, + { "2.16.840.1.101.3.4.2.2", "sha384" }, + { "2.16.840.1.101.3.4.2.3", "sha512" }, + { (const char *) NULL, (const char *) NULL } +}; + +/* + * Lightweight ASN.1 parser. + * In particular, it does not check for syntactic/lexical errors. + * It is intended to support certificate information gathering for SSL backends + * that offer a mean to get certificates as a whole, but do not supply + * entry points to get particular certificate sub-fields. + * Please note there is no pretention here to rewrite a full SSL library. + */ + + +CURL_STATIC const char * Curl_getASN1Element(curl_asn1Element * elem, + const char * beg, const char * end) +{ + unsigned char b; + unsigned long len; + curl_asn1Element lelem; + + /* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg' + ending at `end'. + Returns a pointer in source string after the parsed element, or NULL + if an error occurs. */ + + if(beg >= end || !*beg) + return (const char *) NULL; + + /* Process header byte. */ + elem->header = beg; + b = (unsigned char) *beg++; + elem->constructed = (b & 0x20) != 0; + elem->class = (b >> 6) & 3; + b &= 0x1F; + if(b == 0x1F) + return (const char *) NULL; /* Long tag values not supported here. */ + elem->tag = b; + + /* Process length. */ + if(beg >= end) + return (const char *) NULL; + b = (unsigned char) *beg++; + if(!(b & 0x80)) + len = b; + else if(!(b &= 0x7F)) { + /* Unspecified length. Since we have all the data, we can determine the + effective length by skipping element until an end element is found. */ + if(!elem->constructed) + return (const char *) NULL; + elem->beg = beg; + while(beg < end && *beg) { + beg = Curl_getASN1Element(&lelem, beg, end); + if(!beg) + return (const char *) NULL; + } + if(beg >= end) + return (const char *) NULL; + elem->end = beg; + return beg + 1; + } + else if(beg + b > end) + return (const char *) NULL; /* Does not fit in source. */ + else { + /* Get long length. */ + len = 0; + do { + if(len & 0xFF000000L) + return (const char *) NULL; /* Lengths > 32 bits are not supported. */ + len = (len << 8) | (unsigned char) *beg++; + } while(--b); + } + if((unsigned long) (end - beg) < len) + return (const char *) NULL; /* Element data does not fit in source. */ + elem->beg = beg; + elem->end = beg + len; + return elem->end; +} + +static const curl_OID * searchOID(const char * oid) +{ + const curl_OID * op; + + /* Search the null terminated OID or OID identifier in local table. + Return the table entry pointer or NULL if not found. */ + + for(op = OIDtable; op->numoid; op++) + if(!strcmp(op->numoid, oid) || curl_strequal(op->textoid, oid)) + return op; + + return (const curl_OID *) NULL; +} + +static const char * bool2str(const char * beg, const char * end) +{ + /* Convert an ASN.1 Boolean value into its string representation. + Return the dynamically allocated string, or NULL if source is not an + ASN.1 Boolean value. */ + + if(end - beg != 1) + return (const char *) NULL; + return strdup(*beg? "TRUE": "FALSE"); +} + +static const char * octet2str(const char * beg, const char * end) +{ + size_t n = end - beg; + char * buf; + + /* Convert an ASN.1 octet string to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + buf = malloc(3 * n + 1); + if(buf) + for(n = 0; beg < end; n += 3) + snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); + return buf; +} + +static const char * bit2str(const char * beg, const char * end) +{ + /* Convert an ASN.1 bit string to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + if(++beg > end) + return (const char *) NULL; + return octet2str(beg, end); +} + +static const char * int2str(const char * beg, const char * end) +{ + long val = 0; + size_t n = end - beg; + + /* Convert an ASN.1 integer value into its string representation. + Return the dynamically allocated string, or NULL if source is not an + ASN.1 integer value. */ + + if(!n) + return (const char *) NULL; + + if(n > 4) + return octet2str(beg, end); + + /* Represent integers <= 32-bit as a single value. */ + if(*beg & 0x80) + val = ~val; + + do + val = (val << 8) | *(const unsigned char *) beg++; + while(beg < end); + return curl_maprintf("%s%lx", (val < 0 || val >= 10)? "0x": "", val); +} + +static ssize_t +utf8asn1str(char * * to, int type, const char * from, const char * end) +{ + size_t inlength = end - from; + int size = 1; + size_t outlength; + int charsize; + unsigned int wc; + char * buf; + + /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the + destination buffer dynamically. The allocation size will normally be too + large: this is to avoid buffer overflows. + Terminate the string with a nul byte and return the converted + string length. */ + + *to = (char *) NULL; + switch (type) { + case CURL_ASN1_BMP_STRING: + size = 2; + break; + case CURL_ASN1_UNIVERSAL_STRING: + size = 4; + break; + case CURL_ASN1_NUMERIC_STRING: + case CURL_ASN1_PRINTABLE_STRING: + case CURL_ASN1_TELETEX_STRING: + case CURL_ASN1_IA5_STRING: + case CURL_ASN1_VISIBLE_STRING: + case CURL_ASN1_UTF8_STRING: + break; + default: + return -1; /* Conversion not supported. */ + } + + if(inlength % size) + return -1; /* Length inconsistent with character size. */ + buf = malloc(4 * (inlength / size) + 1); + if(!buf) + return -1; /* Not enough memory. */ + + if(type == CURL_ASN1_UTF8_STRING) { + /* Just copy. */ + outlength = inlength; + if(outlength) + memcpy(buf, from, outlength); + } + else { + for(outlength = 0; from < end;) { + wc = 0; + switch (size) { + case 4: + wc = (wc << 8) | *(const unsigned char *) from++; + wc = (wc << 8) | *(const unsigned char *) from++; + /* fallthrough */ + case 2: + wc = (wc << 8) | *(const unsigned char *) from++; + /* fallthrough */ + default: /* case 1: */ + wc = (wc << 8) | *(const unsigned char *) from++; + } + charsize = 1; + if(wc >= 0x00000080) { + if(wc >= 0x00000800) { + if(wc >= 0x00010000) { + if(wc >= 0x00200000) { + free(buf); + return -1; /* Invalid char. size for target encoding. */ + } + buf[outlength + 3] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x00010000; + charsize++; + } + buf[outlength + 2] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x00000800; + charsize++; + } + buf[outlength + 1] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x000000C0; + charsize++; + } + buf[outlength] = (char) wc; + outlength += charsize; + } + } + buf[outlength] = '\0'; + *to = buf; + return outlength; +} + +static const char * string2str(int type, const char * beg, const char * end) +{ + char * buf; + + /* Convert an ASN.1 String into its UTF-8 string representation. + Return the dynamically allocated string, or NULL if an error occurs. */ + + if(utf8asn1str(&buf, type, beg, end) < 0) + return (const char *) NULL; + return buf; +} + +static int encodeUint(char * buf, int n, unsigned int x) +{ + int i = 0; + unsigned int y = x / 10; + + /* Decimal ASCII encode unsigned integer `x' in the `n'-byte buffer at `buf'. + Return the total number of encoded digits, even if larger than `n'. */ + + if(y) { + i += encodeUint(buf, n, y); + x -= y * 10; + } + if(i < n) + buf[i] = (char) ('0' + x); + i++; + if(i < n) + buf[i] = '\0'; /* Store a terminator if possible. */ + return i; +} + +static int encodeOID(char * buf, int n, const char * beg, const char * end) +{ + int i = 0; + unsigned int x; + unsigned int y; + + /* Convert an ASN.1 OID into its dotted string representation. + Store the result in th `n'-byte buffer at `buf'. + Return the converted string length, or -1 if an error occurs. */ + + /* Process the first two numbers. */ + y = *(const unsigned char *) beg++; + x = y / 40; + y -= x * 40; + i += encodeUint(buf + i, n - i, x); + if(i < n) + buf[i] = '.'; + i++; + i += encodeUint(buf + i, n - i, y); + + /* Process the trailing numbers. */ + while(beg < end) { + if(i < n) + buf[i] = '.'; + i++; + x = 0; + do { + if(x & 0xFF000000) + return -1; + y = *(const unsigned char *) beg++; + x = (x << 7) | (y & 0x7F); + } while(y & 0x80); + i += encodeUint(buf + i, n - i, x); + } + if(i < n) + buf[i] = '\0'; + return i; +} + +static const char * OID2str(const char * beg, const char * end, bool symbolic) +{ + char * buf = (char *) NULL; + const curl_OID * op; + int n; + + /* Convert an ASN.1 OID into its dotted or symbolic string representation. + Return the dynamically allocated string, or NULL if an error occurs. */ + + if(beg < end) { + n = encodeOID((char *) NULL, -1, beg, end); + if(n >= 0) { + buf = malloc(n + 1); + if(buf) { + encodeOID(buf, n, beg, end); + buf[n] = '\0'; + + if(symbolic) { + op = searchOID(buf); + if(op) { + free(buf); + buf = strdup(op->textoid); + } + } + } + } + } + return buf; +} + +static const char * GTime2str(const char * beg, const char * end) +{ + const char * tzp; + const char * fracp; + char sec1, sec2; + size_t fracl; + size_t tzl; + const char * sep = ""; + + /* Convert an ASN.1 Generalized time to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + for(fracp = beg; fracp < end && *fracp >= '0' && *fracp <= '9'; fracp++) + ; + + /* Get seconds digits. */ + sec1 = '0'; + switch (fracp - beg - 12) { + case 0: + sec2 = '0'; + break; + case 2: + sec1 = fracp[-2]; + case 1: + sec2 = fracp[-1]; + break; + default: + return (const char *) NULL; + } + + /* Scan for timezone, measure fractional seconds. */ + tzp = fracp; + fracl = 0; + if(fracp < end && (*fracp == '.' || *fracp == ',')) { + fracp++; + do + tzp++; + while(tzp < end && *tzp >= '0' && *tzp <= '9'); + /* Strip leading zeroes in fractional seconds. */ + for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--) + ; + } + + /* Process timezone. */ + if(tzp >= end) + ; /* Nothing to do. */ + else if(*tzp == 'Z') { + tzp = " GMT"; + end = tzp + 4; + } + else { + sep = " "; + tzp++; + } + + tzl = end - tzp; + return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s", + beg, beg + 4, beg + 6, + beg + 8, beg + 10, sec1, sec2, + fracl? ".": "", fracl, fracp, + sep, tzl, tzp); +} + +static const char * UTime2str(const char * beg, const char * end) +{ + const char * tzp; + size_t tzl; + const char * sec; + + /* Convert an ASN.1 UTC time to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++) + ; + /* Get the seconds. */ + sec = beg + 10; + switch (tzp - sec) { + case 0: + sec = "00"; + case 2: + break; + default: + return (const char *) NULL; + } + + /* Process timezone. */ + if(tzp >= end) + return (const char *) NULL; + if(*tzp == 'Z') { + tzp = "GMT"; + end = tzp + 3; + } + else + tzp++; + + tzl = end - tzp; + return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s", + 20 - (*beg >= '5'), beg, beg + 2, beg + 4, + beg + 6, beg + 8, sec, + tzl, tzp); +} + +CURL_STATIC const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) +{ + /* Convert an ASN.1 element to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + if(elem->constructed) + return (const char *) NULL; /* No conversion of structured elements. */ + + if(!type) + type = elem->tag; /* Type not forced: use element tag as type. */ + + switch (type) { + case CURL_ASN1_BOOLEAN: + return bool2str(elem->beg, elem->end); + case CURL_ASN1_INTEGER: + case CURL_ASN1_ENUMERATED: + return int2str(elem->beg, elem->end); + case CURL_ASN1_BIT_STRING: + return bit2str(elem->beg, elem->end); + case CURL_ASN1_OCTET_STRING: + return octet2str(elem->beg, elem->end); + case CURL_ASN1_NULL: + return strdup(""); + case CURL_ASN1_OBJECT_IDENTIFIER: + return OID2str(elem->beg, elem->end, TRUE); + case CURL_ASN1_UTC_TIME: + return UTime2str(elem->beg, elem->end); + case CURL_ASN1_GENERALIZED_TIME: + return GTime2str(elem->beg, elem->end); + case CURL_ASN1_UTF8_STRING: + case CURL_ASN1_NUMERIC_STRING: + case CURL_ASN1_PRINTABLE_STRING: + case CURL_ASN1_TELETEX_STRING: + case CURL_ASN1_IA5_STRING: + case CURL_ASN1_VISIBLE_STRING: + case CURL_ASN1_UNIVERSAL_STRING: + case CURL_ASN1_BMP_STRING: + return string2str(type, elem->beg, elem->end); + } + + return (const char *) NULL; /* Unsupported. */ +} + +static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn) +{ + curl_asn1Element rdn; + curl_asn1Element atv; + curl_asn1Element oid; + curl_asn1Element value; + size_t l = 0; + const char * p1; + const char * p2; + const char * p3; + const char * str; + + /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'. + Return the total string length, even if larger than `n'. */ + + for(p1 = dn->beg; p1 < dn->end;) { + p1 = Curl_getASN1Element(&rdn, p1, dn->end); + for(p2 = rdn.beg; p2 < rdn.end;) { + p2 = Curl_getASN1Element(&atv, p2, rdn.end); + p3 = Curl_getASN1Element(&oid, atv.beg, atv.end); + Curl_getASN1Element(&value, p3, atv.end); + str = Curl_ASN1tostr(&oid, 0); + if(!str) + return -1; + + /* Encode delimiter. + If attribute has a short uppercase name, delimiter is ", ". */ + if(l) { + for(p3 = str; isupper(*p3); p3++) + ; + for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) { + if(l < n) + buf[l] = *p3; + l++; + } + } + + /* Encode attribute name. */ + for(p3 = str; *p3; p3++) { + if(l < n) + buf[l] = *p3; + l++; + } + free((char *) str); + + /* Generate equal sign. */ + if(l < n) + buf[l] = '='; + l++; + + /* Generate value. */ + str = Curl_ASN1tostr(&value, 0); + if(!str) + return -1; + for(p3 = str; *p3; p3++) { + if(l < n) + buf[l] = *p3; + l++; + } + free((char *) str); + } + } + + return l; +} + +CURL_STATIC const char * Curl_DNtostr(curl_asn1Element * dn) +{ + char * buf = (char *) NULL; + ssize_t n = encodeDN(buf, 0, dn); + + /* Convert an ASN.1 distinguished name into a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + if(n >= 0) { + buf = malloc(n + 1); + if(buf) { + encodeDN(buf, n + 1, dn); + buf[n] = '\0'; + } + } + return (const char *) buf; +} + +/* + * X509 parser. + */ + +CURL_STATIC void Curl_parseX509(curl_X509certificate * cert, + const char * beg, const char * end) +{ + curl_asn1Element elem; + curl_asn1Element tbsCertificate; + const char * ccp; + static const char defaultVersion = 0; /* v1. */ + + /* ASN.1 parse an X509 certificate into structure subfields. + Syntax is assumed to have already been checked by the SSL backend. + See RFC 5280. */ + + cert->certificate.header = NULL; + cert->certificate.beg = beg; + cert->certificate.end = end; + + /* Get the sequence content. */ + Curl_getASN1Element(&elem, beg, end); + beg = elem.beg; + end = elem.end; + + /* Get tbsCertificate. */ + beg = Curl_getASN1Element(&tbsCertificate, beg, end); + /* Skip the signatureAlgorithm. */ + beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end); + /* Get the signatureValue. */ + Curl_getASN1Element(&cert->signature, beg, end); + + /* Parse TBSCertificate. */ + beg = tbsCertificate.beg; + end = tbsCertificate.end; + /* Get optional version, get serialNumber. */ + cert->version.header = NULL; + cert->version.beg = &defaultVersion; + cert->version.end = &defaultVersion + sizeof defaultVersion;; + beg = Curl_getASN1Element(&elem, beg, end); + if(elem.tag == 0) { + Curl_getASN1Element(&cert->version, elem.beg, elem.end); + beg = Curl_getASN1Element(&elem, beg, end); + } + cert->serialNumber = elem; + /* Get signature algorithm. */ + beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end); + /* Get issuer. */ + beg = Curl_getASN1Element(&cert->issuer, beg, end); + /* Get notBefore and notAfter. */ + beg = Curl_getASN1Element(&elem, beg, end); + ccp = Curl_getASN1Element(&cert->notBefore, elem.beg, elem.end); + Curl_getASN1Element(&cert->notAfter, ccp, elem.end); + /* Get subject. */ + beg = Curl_getASN1Element(&cert->subject, beg, end); + /* Get subjectPublicKeyAlgorithm and subjectPublicKey. */ + beg = Curl_getASN1Element(&cert->subjectPublicKeyInfo, beg, end); + ccp = Curl_getASN1Element(&cert->subjectPublicKeyAlgorithm, + cert->subjectPublicKeyInfo.beg, + cert->subjectPublicKeyInfo.end); + Curl_getASN1Element(&cert->subjectPublicKey, ccp, + cert->subjectPublicKeyInfo.end); + /* Get optional issuerUiqueID, subjectUniqueID and extensions. */ + cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0; + cert->extensions.tag = elem.tag = 0; + cert->issuerUniqueID.header = cert->subjectUniqueID.header = NULL; + cert->issuerUniqueID.beg = cert->issuerUniqueID.end = ""; + cert->subjectUniqueID.beg = cert->subjectUniqueID.end = ""; + cert->extensions.header = NULL; + cert->extensions.beg = cert->extensions.end = ""; + if(beg < end) + beg = Curl_getASN1Element(&elem, beg, end); + if(elem.tag == 1) { + cert->issuerUniqueID = elem; + if(beg < end) + beg = Curl_getASN1Element(&elem, beg, end); + } + if(elem.tag == 2) { + cert->subjectUniqueID = elem; + if(beg < end) + beg = Curl_getASN1Element(&elem, beg, end); + } + if(elem.tag == 3) + Curl_getASN1Element(&cert->extensions, elem.beg, elem.end); +} + +static size_t copySubstring(char * to, const char * from) +{ + size_t i; + + /* Copy at most 64-characters, terminate with a newline and returns the + effective number of stored characters. */ + + for(i = 0; i < 64; i++) { + to[i] = *from; + if(!*from++) + break; + } + + to[i++] = '\n'; + return i; +} + +static const char * dumpAlgo(curl_asn1Element * param, + const char * beg, const char * end) +{ + curl_asn1Element oid; + + /* Get algorithm parameters and return algorithm name. */ + + beg = Curl_getASN1Element(&oid, beg, end); + param->header = NULL; + param->tag = 0; + param->beg = param->end = end; + if(beg < end) + Curl_getASN1Element(param, beg, end); + return OID2str(oid.beg, oid.end, TRUE); +} + +static void do_pubkey_field(struct SessionHandle * data, int certnum, + const char * label, curl_asn1Element * elem) +{ + const char * output; + + /* Generate a certificate information record for the public key. */ + + output = Curl_ASN1tostr(elem, 0); + if(output) { + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, label, output); + if(!certnum) + infof(data, " %s: %s\n", label, output); + free((char *) output); + } +} + +static void do_pubkey(struct SessionHandle * data, int certnum, + const char * algo, curl_asn1Element * param, + curl_asn1Element * pubkey) +{ + curl_asn1Element elem; + curl_asn1Element pk; + const char * p; + const char * q; + unsigned long len; + unsigned int i; + + /* Generate all information records for the public key. */ + + /* Get the public key (single element). */ + Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end); + + if(curl_strequal(algo, "rsaEncryption")) { + p = Curl_getASN1Element(&elem, pk.beg, pk.end); + /* Compute key length. */ + for(q = elem.beg; !*q && q < elem.end; q++) + ; + len = (unsigned long)((elem.end - q) * 8); + if(len) + for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1) + len--; + if(len > 32) + elem.beg = q; /* Strip leading zero bytes. */ + if(!certnum) + infof(data, " RSA Public Key (%lu bits)\n", len); + if(data->set.ssl.certinfo) { + q = curl_maprintf("%lu", len); + if(q) { + Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q); + free((char *) q); + } + } + /* Generate coefficients. */ + do_pubkey_field(data, certnum, "rsa(n)", &elem); + Curl_getASN1Element(&elem, p, pk.end); + do_pubkey_field(data, certnum, "rsa(e)", &elem); + } + else if(curl_strequal(algo, "dsa")) { + p = Curl_getASN1Element(&elem, param->beg, param->end); + do_pubkey_field(data, certnum, "dsa(p)", &elem); + p = Curl_getASN1Element(&elem, p, param->end); + do_pubkey_field(data, certnum, "dsa(q)", &elem); + Curl_getASN1Element(&elem, p, param->end); + do_pubkey_field(data, certnum, "dsa(g)", &elem); + do_pubkey_field(data, certnum, "dsa(pub_key)", &pk); + } + else if(curl_strequal(algo, "dhpublicnumber")) { + p = Curl_getASN1Element(&elem, param->beg, param->end); + do_pubkey_field(data, certnum, "dh(p)", &elem); + Curl_getASN1Element(&elem, param->beg, param->end); + do_pubkey_field(data, certnum, "dh(g)", &elem); + do_pubkey_field(data, certnum, "dh(pub_key)", &pk); + } +#if 0 /* Patent-encumbered. */ + else if(curl_strequal(algo, "ecPublicKey")) { + /* Left TODO. */ + } +#endif +} + +CURL_STATIC CURLcode Curl_extract_certinfo(struct connectdata * conn, + int certnum, + const char * beg, + const char * end) +{ + curl_X509certificate cert; + struct SessionHandle * data = conn->data; + curl_asn1Element param; + const char * ccp; + char * cp1; + size_t cl1; + char * cp2; + CURLcode result; + unsigned long version; + size_t i; + size_t j; + + if(!data->set.ssl.certinfo) + if(certnum) + return CURLE_OK; + + /* Prepare the certificate information for curl_easy_getinfo(). */ + + /* Extract the certificate ASN.1 elements. */ + Curl_parseX509(&cert, beg, end); + + /* Subject. */ + ccp = Curl_DNtostr(&cert.subject); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Subject", ccp); + if(!certnum) + infof(data, "%2d Subject: %s\n", certnum, ccp); + free((char *) ccp); + + /* Issuer. */ + ccp = Curl_DNtostr(&cert.issuer); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp); + if(!certnum) + infof(data, " Issuer: %s\n", ccp); + free((char *) ccp); + + /* Version (always fits in less than 32 bits). */ + version = 0; + for(ccp = cert.version.beg; ccp < cert.version.end; ccp++) + version = (version << 8) | *(const unsigned char *) ccp; + if(data->set.ssl.certinfo) { + ccp = curl_maprintf("%lx", version); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + Curl_ssl_push_certinfo(data, certnum, "Version", ccp); + free((char *) ccp); + } + if(!certnum) + infof(data, " Version: %lu (0x%lx)\n", version + 1, version); + + /* Serial number. */ + ccp = Curl_ASN1tostr(&cert.serialNumber, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp); + if(!certnum) + infof(data, " Serial Number: %s\n", ccp); + free((char *) ccp); + + /* Signature algorithm .*/ + ccp = dumpAlgo(¶m, cert.signatureAlgorithm.beg, + cert.signatureAlgorithm.end); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp); + if(!certnum) + infof(data, " Signature Algorithm: %s\n", ccp); + free((char *) ccp); + + /* Start Date. */ + ccp = Curl_ASN1tostr(&cert.notBefore, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp); + if(!certnum) + infof(data, " Start Date: %s\n", ccp); + free((char *) ccp); + + /* Expire Date. */ + ccp = Curl_ASN1tostr(&cert.notAfter, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp); + if(!certnum) + infof(data, " Expire Date: %s\n", ccp); + free((char *) ccp); + + /* Public Key Algorithm. */ + ccp = dumpAlgo(¶m, cert.subjectPublicKeyAlgorithm.beg, + cert.subjectPublicKeyAlgorithm.end); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp); + if(!certnum) + infof(data, " Public Key Algorithm: %s\n", ccp); + do_pubkey(data, certnum, ccp, ¶m, &cert.subjectPublicKey); + free((char *) ccp); + +/* TODO: extensions. */ + + /* Signature. */ + ccp = Curl_ASN1tostr(&cert.signature, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Signature", ccp); + if(!certnum) + infof(data, " Signature: %s\n", ccp); + free((char *) ccp); + + /* Generate PEM certificate. */ + result = Curl_base64_encode(data, cert.certificate.beg, + cert.certificate.end - cert.certificate.beg, + &cp1, &cl1); + if(result) + return result; + /* Compute the number of characters in final certificate string. Format is: + -----BEGIN CERTIFICATE-----\n + \n + . + . + . + -----END CERTIFICATE-----\n + */ + i = 28 + cl1 + (cl1 + 64 - 1) / 64 + 26; + cp2 = malloc(i + 1); + if(!cp2) { + free(cp1); + return CURLE_OUT_OF_MEMORY; + } + /* Build the certificate string. */ + i = copySubstring(cp2, "-----BEGIN CERTIFICATE-----"); + for(j = 0; j < cl1; j += 64) + i += copySubstring(cp2 + i, cp1 + j); + i += copySubstring(cp2 + i, "-----END CERTIFICATE-----"); + cp2[i] = '\0'; + free(cp1); + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Cert", cp2); + if(!certnum) + infof(data, "%s\n", cp2); + free(cp2); + return CURLE_OK; +} + +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS */ + +#if defined(USE_GSKIT) + +static const char * checkOID(const char * beg, const char * end, + const char * oid) +{ + curl_asn1Element e; + const char * ccp; + const char * p; + bool matched; + + /* Check if first ASN.1 element at `beg' is the given OID. + Return a pointer in the source after the OID if found, else NULL. */ + + ccp = Curl_getASN1Element(&e, beg, end); + if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER) + return (const char *) NULL; + + p = OID2str(e.beg, e.end, FALSE); + if(!p) + return (const char *) NULL; + + matched = !strcmp(p, oid); + free((char *) p); + return matched? ccp: (const char *) NULL; +} + +CURL_STATIC CURLcode Curl_verifyhost(struct connectdata * conn, + const char * beg, const char * end) +{ + struct SessionHandle * data = conn->data; + curl_X509certificate cert; + curl_asn1Element dn; + curl_asn1Element elem; + curl_asn1Element ext; + curl_asn1Element name; + int i; + const char * p; + const char * q; + char * dnsname; + int matched = -1; + size_t addrlen = (size_t) -1; + ssize_t len; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + + /* Verify that connection server matches info in X509 certificate at + `beg'..`end'. */ + + if(!data->set.ssl.verifyhost) + return CURLE_OK; + + if(!beg) + return CURLE_PEER_FAILED_VERIFICATION; + Curl_parseX509(&cert, beg, end); + + /* Get the server IP address. */ +#ifdef ENABLE_IPV6 + if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr)) + addrlen = sizeof(struct in6_addr); + else +#endif + if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) + addrlen = sizeof(struct in_addr); + + /* Process extensions. */ + for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) { + p = Curl_getASN1Element(&ext, p, cert.extensions.end); + /* Check if extension is a subjectAlternativeName. */ + ext.beg = checkOID(ext.beg, ext.end, sanOID); + if(ext.beg) { + ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end); + /* Skip critical if present. */ + if(elem.tag == CURL_ASN1_BOOLEAN) + ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end); + /* Parse the octet string contents: is a single sequence. */ + Curl_getASN1Element(&elem, elem.beg, elem.end); + /* Check all GeneralNames. */ + for(q = elem.beg; matched != 1 && q < elem.end;) { + q = Curl_getASN1Element(&name, q, elem.end); + switch (name.tag) { + case 2: /* DNS name. */ + i = 0; + len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING, + name.beg, name.end); + if(len > 0) + if(strlen(dnsname) == (size_t) len) + i = Curl_cert_hostcheck((const char *) dnsname, conn->host.name); + free(dnsname); + if(!i) + return CURLE_PEER_FAILED_VERIFICATION; + matched = i; + break; + + case 7: /* IP address. */ + matched = (size_t) (name.end - q) == addrlen && + !memcmp(&addr, q, addrlen); + break; + } + } + } + } + + switch (matched) { + case 1: + /* an alternative name matched the server hostname */ + infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname); + return CURLE_OK; + case 0: + /* an alternative name field existed, but didn't match and then + we MUST fail */ + infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + + /* Process subject. */ + name.header = NULL; + name.beg = name.end = ""; + q = cert.subject.beg; + /* we have to look to the last occurrence of a commonName in the + distinguished one to get the most significant one. */ + while(q < cert.subject.end) { + q = Curl_getASN1Element(&dn, q, cert.subject.end); + for(p = dn.beg; p < dn.end;) { + p = Curl_getASN1Element(&elem, p, dn.end); + /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */ + elem.beg = checkOID(elem.beg, elem.end, cnOID); + if(elem.beg) + name = elem; /* Latch CN. */ + } + } + + /* Check the CN if found. */ + if(!Curl_getASN1Element(&elem, name.beg, name.end)) + failf(data, "SSL: unable to obtain common name from peer certificate"); + else { + len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end); + if(len < 0) { + free(dnsname); + return CURLE_OUT_OF_MEMORY; + } + if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */ + failf(data, "SSL: illegal cert name field"); + else if(Curl_cert_hostcheck((const char *) dnsname, conn->host.name)) { + infof(data, "\t common name: %s (matched)\n", dnsname); + free(dnsname); + return CURLE_OK; + } + else + failf(data, "SSL: certificate subject name '%s' does not match " + "target host name '%s'", dnsname, conn->host.dispname); + free(dnsname); + } + + return CURLE_PEER_FAILED_VERIFICATION; +} + +#endif /* USE_GSKIT */ diff --git a/libcurl/src/lib/x509asn1.h b/libcurl/src/lib/x509asn1.h new file mode 100644 index 0000000..f874e07 --- /dev/null +++ b/libcurl/src/lib/x509asn1.h @@ -0,0 +1,131 @@ +#ifndef HEADER_CURL_X509ASN1_H +#define HEADER_CURL_X509ASN1_H + +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) + +#include "urldata.h" + +/* + * Constants. + */ + +/* ASN.1 classes. */ +#define CURL_ASN1_UNIVERSAL 0 +#define CURL_ASN1_APPLICATION 1 +#define CURL_ASN1_CONTEXT_SPECIFIC 2 +#define CURL_ASN1_PRIVATE 3 + +/* ASN.1 types. */ +#define CURL_ASN1_BOOLEAN 1 +#define CURL_ASN1_INTEGER 2 +#define CURL_ASN1_BIT_STRING 3 +#define CURL_ASN1_OCTET_STRING 4 +#define CURL_ASN1_NULL 5 +#define CURL_ASN1_OBJECT_IDENTIFIER 6 +#define CURL_ASN1_OBJECT_DESCRIPTOR 7 +#define CURL_ASN1_INSTANCE_OF 8 +#define CURL_ASN1_REAL 9 +#define CURL_ASN1_ENUMERATED 10 +#define CURL_ASN1_EMBEDDED 11 +#define CURL_ASN1_UTF8_STRING 12 +#define CURL_ASN1_RELATIVE_OID 13 +#define CURL_ASN1_SEQUENCE 16 +#define CURL_ASN1_SET 17 +#define CURL_ASN1_NUMERIC_STRING 18 +#define CURL_ASN1_PRINTABLE_STRING 19 +#define CURL_ASN1_TELETEX_STRING 20 +#define CURL_ASN1_VIDEOTEX_STRING 21 +#define CURL_ASN1_IA5_STRING 22 +#define CURL_ASN1_UTC_TIME 23 +#define CURL_ASN1_GENERALIZED_TIME 24 +#define CURL_ASN1_GRAPHIC_STRING 25 +#define CURL_ASN1_VISIBLE_STRING 26 +#define CURL_ASN1_GENERAL_STRING 27 +#define CURL_ASN1_UNIVERSAL_STRING 28 +#define CURL_ASN1_CHARACTER_STRING 29 +#define CURL_ASN1_BMP_STRING 30 + + +/* + * Types. + */ + +/* ASN.1 parsed element. */ +typedef struct { + const char * header; /* Pointer to header byte. */ + const char * beg; /* Pointer to element data. */ + const char * end; /* Pointer to 1st byte after element. */ + unsigned char class; /* ASN.1 element class. */ + unsigned char tag; /* ASN.1 element tag. */ + bool constructed; /* Element is constructed. */ +} curl_asn1Element; + + +/* ASN.1 OID table entry. */ +typedef struct { + const char * numoid; /* Dotted-numeric OID. */ + const char * textoid; /* OID name. */ +} curl_OID; + + +/* X509 certificate: RFC 5280. */ +typedef struct { + curl_asn1Element certificate; + curl_asn1Element version; + curl_asn1Element serialNumber; + curl_asn1Element signatureAlgorithm; + curl_asn1Element signature; + curl_asn1Element issuer; + curl_asn1Element notBefore; + curl_asn1Element notAfter; + curl_asn1Element subject; + curl_asn1Element subjectPublicKeyInfo; + curl_asn1Element subjectPublicKeyAlgorithm; + curl_asn1Element subjectPublicKey; + curl_asn1Element issuerUniqueID; + curl_asn1Element subjectUniqueID; + curl_asn1Element extensions; +} curl_X509certificate; + + +/* + * Prototypes. + */ + +CURL_STATIC const char * Curl_getASN1Element(curl_asn1Element * elem, + const char * beg, const char * end); +CURL_STATIC const char * Curl_ASN1tostr(curl_asn1Element * elem, int type); +CURL_STATIC const char * Curl_DNtostr(curl_asn1Element * dn); +CURL_STATIC void Curl_parseX509(curl_X509certificate * cert, + const char * beg, const char * end); +CURL_STATIC CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum, + const char * beg, const char * end); +CURL_STATIC CURLcode Curl_verifyhost(struct connectdata * conn, + const char * beg, const char * end); + +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS */ +#endif /* HEADER_CURL_X509ASN1_H */ diff --git a/libcurl/src/libcurl_unified.c b/libcurl/src/libcurl_unified.c new file mode 100644 index 0000000..c5dbf46 --- /dev/null +++ b/libcurl/src/libcurl_unified.c @@ -0,0 +1,172 @@ +# ifndef CURL_STATICLIB +# define CURL_STATICLIB +# endif + +# define BUILDING_LIBCURL +# if !defined(CURL_STATICLIB) +# define CURL_STATICLIB +# endif + +// #include "InternalOverrides.h" + +# if defined(WINAPI_FAMILY) +# include +# if WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_APP) || WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_PHONE_APP) +# define CURL_WINRT +# endif +# endif + +# if !defined(CURL_DISABLE_TYPECHECK) +# define CURL_DISABLE_TYPECHECK +# endif +# define CURL_DISABLE_CRYPTO_AUTH +# define CURL_DISABLE_TFTP +# define CURL_DISABLE_FTP +# define CURL_DISABLE_LDAP +# define CURL_DISABLE_TELNET +# define CURL_DISABLE_DICT +# define CURL_DISABLE_FILE +# define CURL_DISABLE_RTSP +# define CURL_DISABLE_POP3 +# define CURL_DISABLE_IMAP +# define CURL_DISABLE_SMB +# define CURL_DISABLE_SMTP +# define CURL_DISABLE_RTMP +# define CURL_DISABLE_GOPHER + +# define CURL_STATIC static __inline +# define CURL_STATIC_VAR static +# define CURL_STATIC_DEF(t,n,v) +# define CURL_STATIC_DECL(t,n,v) static t n = v + +//# define USE_AXTLS +# define USE_SCHANNEL +# define USE_WINDOWS_SSPI // USE_SCHANNEL require this + +# include "lib/mprintf.c" + +# include "lib/urldata.h" + +static const struct Curl_handler Curl_handler_http; +# if defined(USE_SSL) +static const struct Curl_handler Curl_handler_https; +# endif + +//# include "lib/vtls/axtls.c" +//# include "lib/vtls/darwinssl.c" +# include "lib/vtls/schannel.c" +//# include "lib/vtls/cyassl.c" +//# include "lib/vtls/gskit.c" +//# include "lib/vtls/gtls.c" +//# include "lib/vtls/nss.c" +//# include "lib/vtls/openssl.c" +//# include "lib/vtls/polarssl.c" +//# include "lib/vtls/polarssl_threadlock.c" +# include "lib/vtls/vtls.c" +//# include "lib/amigaos.c" +//# include "lib/asyn-ares.c" +# include "lib/asyn-thread.c" +# include "lib/base64.c" +# include "lib/bundles.c" +# include "lib/conncache.c" +# include "lib/connect.c" +//# include "lib/content_encoding.c" +# include "lib/cookie.c" +# include "lib/parsedate.c" // earlier so Curl_wkday and Curl_month will be defined +//# include "lib/dict.c" +# include "lib/dotdot.c" +# include "lib/easy.c" +# include "lib/escape.c" +//# include "lib/file.c" +# include "lib/fileinfo.c" +# include "lib/formdata.c" +//# include "lib/ftp.c" +//# include "lib/ftplistparser.c" +# include "lib/getenv.c" +# include "lib/getinfo.c" +//# include "lib/gopher.c" +# include "lib/hash.c" +//# include "lib/hmac.c" +# include "lib/hostasyn.c" +//# include "lib/hostcheck.c" +# include "lib/hostip.c" +# include "lib/hostip4.c" +//# include "lib/hostip6.c" +//# include "lib/hostsyn.c" +# include "lib/http.c" +# include "lib/http_chunks.c" +//# include "lib/http_digest.c" +//# include "lib/http_negotiate.c" +//# include "lib/http_negotiate_sspi.c" +# include "lib/http_proxy.c" +//# include "lib/http2.c" +//# include "lib/idn_win32.c" +# include "lib/if2ip.c" +//# include "lib/imap.c" +# include "lib/inet_ntop.c" +# include "lib/inet_pton.c" +//# include "lib/krb5.c" +//# include "lib/ldap.c" +# include "lib/llist.c" +//# include "lib/md4.c" +//# include "lib/md5.c" +//# include "lib/memdebug.c" +# include "lib/multi.c" +# include "lib/netrc.c" +//# include "lib/non-ascii.c" +# include "lib/nonblock.c" +//# include "lib/nwlib.c" +//# include "lib/nwos.c" +//# include "lib/openldap.c" +//# include "lib/pingpong.c" +# include "lib/pipeline.c" +//# include "lib/pop3.c" +# include "lib/progress.c" +# include "lib/rawstr.c" +//# include "lib/rtsp.c" +//# include "lib/security.c" +# include "lib/select.c" +# include "lib/sendf.c" +# include "lib/share.c" +# include "lib/slist.c" +//# include "lib/smb.c" +//# include "lib/smtp.c" +# include "lib/socks.c" +//# include "lib/socks_gssapi.c" +# include "lib/socks_sspi.c" +# include "lib/speedcheck.c" +# include "lib/splay.c" +//# include "lib/ssh.c" +# include "lib/strdup.c" +# include "lib/strequal.c" +# include "lib/strerror.c" +# include "lib/strtok.c" +//# include "lib/strtoofft.c" +//# include "lib/telnet.c" +//# include "lib/tftp.c" +# include "lib/timeval.c" +# include "lib/transfer.c" +# include "lib/url.c" +//# include "lib/version.c" +# include "lib/warnless.c" +# include "lib/wildcard.c" +//# include "lib/x509asn1.c" + +# include "lib/curl_addrinfo.c" +//# include "lib/curl_des.c" +//# include "lib/curl_endian.c" +//# include "lib/curl_fnmatch.c" +//# include "lib/curl_gethostname.c" +//# include "lib/curl_gssapi.c" +# include "lib/curl_memrchr.c" +# include "lib/curl_multibyte.c" +//# include "lib/curl_ntlm.c" +//# include "lib/curl_ntlm_core.c" +//# include "lib/curl_ntlm_msgs.c" +//# include "lib/curl_ntlm_wb.c" +//# include "lib/curl_rtmp.c" +//# include "lib/curl_sasl.c" +//# include "lib/curl_sasl_sspi.c" +//# include "lib/curl_sasl_gssapi.c" +# include "lib/curl_sspi.c" +# include "lib/curl_threads.c" diff --git a/libmad/configured/config.h b/libmad/configured/config.h deleted file mode 100644 index 02683a5..0000000 --- a/libmad/configured/config.h +++ /dev/null @@ -1,130 +0,0 @@ -/* config.h. Generated by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to enable diagnostic debugging support. */ -/* #undef DEBUG */ - -/* Define to enable experimental code. */ -/* #undef EXPERIMENTAL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if you have the `fcntl' function. */ -/* #undef HAVE_FCNTL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `fork' function. */ -/* #undef HAVE_FORK */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define if your MIPS CPU supports a 2-operand MADD16 instruction. */ -/* #undef HAVE_MADD16_ASM */ - -/* Define if your MIPS CPU supports a 2-operand MADD instruction. */ -/* #undef HAVE_MADD_ASM */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `pipe' function. */ -/* #undef HAVE_PIPE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have that is POSIX.1 compatible. */ -/* #undef HAVE_SYS_WAIT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Define to 1 if you have the `waitpid' function. */ -/* #undef HAVE_WAITPID */ - -/* Define to disable debugging assertions. */ -/* #undef NDEBUG */ - -/* Define to optimize for accuracy over speed. */ -/* #undef OPT_ACCURACY */ - -/* Define to optimize for speed over accuracy. */ -/* #undef OPT_SPEED */ - -/* Define to enable a fast subband synthesis approximation optimization. */ -/* #undef OPT_SSO */ - -/* Define to influence a strict interpretation of the ISO/IEC standards, even - if this is in opposition with best accepted practices. */ -/* #undef OPT_STRICT */ - -/* Name of package */ -#define PACKAGE "libmad" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "support@underbit.com" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "MPEG Audio Decoder" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "MPEG Audio Decoder 0.15.1b" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libmad" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "0.15.1b" - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of a `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "0.15.1b" - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ -#define inline __inline - -/* Define to `int' if does not define. */ -/* #undef pid_t */ diff --git a/libmad/configured/mad.h b/libmad/configured/mad.h deleted file mode 100644 index d483478..0000000 --- a/libmad/configured/mad.h +++ /dev/null @@ -1,948 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * If you would like to negotiate alternate licensing terms, you may do - * so by contacting: Underbit Technologies, Inc. - */ - -# ifdef __cplusplus -extern "C" { -# endif - -# define FPM_INTEL - - - -# define SIZEOF_INT 4 -# define SIZEOF_LONG 4 -# define SIZEOF_LONG_LONG 8 - - -/* Id: version.h,v 1.24 2003/05/27 22:40:37 rob Exp */ - -# ifndef LIBMAD_VERSION_H -# define LIBMAD_VERSION_H - -# define MAD_VERSION_MAJOR 0 -# define MAD_VERSION_MINOR 15 -# define MAD_VERSION_PATCH 1 -# define MAD_VERSION_EXTRA " (beta)" - -# define MAD_VERSION_STRINGIZE(str) #str -# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) - -# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \ - MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \ - MAD_VERSION_STRING(MAD_VERSION_PATCH) \ - MAD_VERSION_EXTRA - -# define MAD_PUBLISHYEAR "2000-2003" -# define MAD_AUTHOR "Underbit Technologies, Inc." -# define MAD_EMAIL "info@underbit.com" - -extern char const mad_version[]; -extern char const mad_copyright[]; -extern char const mad_author[]; -extern char const mad_build[]; - -# endif - -/* Id: fixed.h,v 1.36 2003/05/28 04:36:00 rob Exp */ - -# ifndef LIBMAD_FIXED_H -# define LIBMAD_FIXED_H - -# if SIZEOF_INT >= 4 -typedef signed int mad_fixed_t; - -typedef signed int mad_fixed64hi_t; -typedef unsigned int mad_fixed64lo_t; -# else -typedef signed long mad_fixed_t; - -typedef signed long mad_fixed64hi_t; -typedef unsigned long mad_fixed64lo_t; -# endif - -# if defined(_MSC_VER) -# define mad_fixed64_t signed __int64 -# elif 1 || defined(__GNUC__) -# define mad_fixed64_t signed long long -# endif - -# if defined(FPM_FLOAT) -typedef double mad_sample_t; -# else -typedef mad_fixed_t mad_sample_t; -# endif - -/* - * Fixed-point format: 0xABBBBBBB - * A == whole part (sign + 3 bits) - * B == fractional part (28 bits) - * - * Values are signed two's complement, so the effective range is: - * 0x80000000 to 0x7fffffff - * -8.0 to +7.9999999962747097015380859375 - * - * The smallest representable value is: - * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) - * - * 28 bits of fractional accuracy represent about - * 8.6 digits of decimal accuracy. - * - * Fixed-point numbers can be added or subtracted as normal - * integers, but multiplication requires shifting the 64-bit result - * from 56 fractional bits back to 28 (and rounding.) - * - * Changing the definition of MAD_F_FRACBITS is only partially - * supported, and must be done with care. - */ - -# define MAD_F_FRACBITS 28 - -# if MAD_F_FRACBITS == 28 -# define MAD_F(x) ((mad_fixed_t) (x##L)) -# else -# if MAD_F_FRACBITS < 28 -# warning "MAD_F_FRACBITS < 28" -# define MAD_F(x) ((mad_fixed_t) \ - (((x##L) + \ - (1L << (28 - MAD_F_FRACBITS - 1))) >> \ - (28 - MAD_F_FRACBITS))) -# elif MAD_F_FRACBITS > 28 -# error "MAD_F_FRACBITS > 28 not currently supported" -# define MAD_F(x) ((mad_fixed_t) \ - ((x##L) << (MAD_F_FRACBITS - 28))) -# endif -# endif - -# define MAD_F_MIN ((mad_fixed_t) -0x80000000L) -# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) - -# define MAD_F_ONE MAD_F(0x10000000) - -# define mad_f_tofixed(x) ((mad_fixed_t) \ - ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) -# define mad_f_todouble(x) ((double) \ - ((x) / (double) (1L << MAD_F_FRACBITS))) - -# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) -# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) - /* (x should be positive) */ - -# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) - -# define mad_f_add(x, y) ((x) + (y)) -# define mad_f_sub(x, y) ((x) - (y)) - -# if defined(FPM_FLOAT) -# error "FPM_FLOAT not yet supported" - -# undef MAD_F -# define MAD_F(x) mad_f_todouble(x) - -# define mad_f_mul(x, y) ((x) * (y)) -# define mad_f_scale64 - -# undef ASO_ZEROCHECK - -# elif defined(FPM_64BIT) - -/* - * This version should be the most accurate if 64-bit types are supported by - * the compiler, although it may not be the most efficient. - */ -# if defined(OPT_ACCURACY) -# define mad_f_mul(x, y) \ - ((mad_fixed_t) \ - ((((mad_fixed64_t) (x) * (y)) + \ - (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) -# else -# define mad_f_mul(x, y) \ - ((mad_fixed_t) (((mad_fixed64_t) (x) * (y)) >> MAD_F_SCALEBITS)) -# endif - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- Intel --------------------------------------------------------------- */ - -# elif defined(FPM_INTEL) - -# if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4035) /* no return value */ -static __forceinline -mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) -{ - enum { - fracbits = MAD_F_FRACBITS - }; - - __asm { - mov eax, x - imul y - shrd eax, edx, fracbits - } - - /* implicit return of eax */ -} -# pragma warning(pop) - -# define mad_f_mul mad_f_mul_inline -# define mad_f_scale64 -# else -/* - * This Intel version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("imull %3" \ - : "=a" (lo), "=d" (hi) \ - : "%a" (x), "rm" (y) \ - : "cc") - -# if defined(OPT_ACCURACY) -/* - * This gives best accuracy but is not very fast. - */ -# define MAD_F_MLA(hi, lo, x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - asm ("addl %2,%0\n\t" \ - "adcl %3,%1" \ - : "=rm" (lo), "=rm" (hi) \ - : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ - : "cc"); \ - }) -# endif /* OPT_ACCURACY */ - -# if defined(OPT_ACCURACY) -/* - * Surprisingly, this is faster than SHRD followed by ADC. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed64hi_t __hi_; \ - mad_fixed64lo_t __lo_; \ - mad_fixed_t __result; \ - asm ("addl %4,%2\n\t" \ - "adcl %5,%3" \ - : "=rm" (__lo_), "=rm" (__hi_) \ - : "0" (lo), "1" (hi), \ - "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ - : "cc"); \ - asm ("shrdl %3,%2,%1" \ - : "=rm" (__result) \ - : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# else -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("shrdl %3,%2,%1" \ - : "=rm" (__result) \ - : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# endif /* OPT_ACCURACY */ - -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* --- ARM ----------------------------------------------------------------- */ - -# elif defined(FPM_ARM) - -/* - * This ARM V4 version is as accurate as FPM_64BIT but much faster. The - * least significant bit is properly rounded at no CPU cycle cost! - */ -# if 1 -/* - * This is faster than the default implementation via MAD_F_MLX() and - * mad_f_scale64(). - */ -# define mad_f_mul(x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - mad_fixed_t __result; \ - asm ("smull %0, %1, %3, %4\n\t" \ - "movs %0, %0, lsr %5\n\t" \ - "adc %2, %0, %1, lsl %6" \ - : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ - : "%r" (x), "r" (y), \ - "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# endif - -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("smull %0, %1, %2, %3" \ - : "=&r" (lo), "=&r" (hi) \ - : "%r" (x), "r" (y)) - -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("smlal %0, %1, %2, %3" \ - : "+r" (lo), "+r" (hi) \ - : "%r" (x), "r" (y)) - -# define MAD_F_MLN(hi, lo) \ - asm ("rsbs %0, %2, #0\n\t" \ - "rsc %1, %3, #0" \ - : "=r" (lo), "=r" (hi) \ - : "0" (lo), "1" (hi) \ - : "cc") - -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("movs %0, %1, lsr %3\n\t" \ - "adc %0, %0, %2, lsl %4" \ - : "=&r" (__result) \ - : "r" (lo), "r" (hi), \ - "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- MIPS ---------------------------------------------------------------- */ - -# elif defined(FPM_MIPS) - -/* - * This MIPS version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" (x), "r" (y)) - -# if defined(HAVE_MADD_ASM) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" (x), "r" (y)) -# elif defined(HAVE_MADD16_ASM) -/* - * This loses significant accuracy due to the 16-bit integer limit in the - * multiply/accumulate instruction. - */ -# define MAD_F_ML0(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd16 %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) -# endif - -# if defined(OPT_SPEED) -# define mad_f_scale64(hi, lo) \ - ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* --- SPARC --------------------------------------------------------------- */ - -# elif defined(FPM_SPARC) - -/* - * This SPARC V8 version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("smul %2, %3, %0\n\t" \ - "rd %%y, %1" \ - : "=r" (lo), "=r" (hi) \ - : "%r" (x), "rI" (y)) - -/* --- PowerPC ------------------------------------------------------------- */ - -# elif defined(FPM_PPC) - -/* - * This PowerPC version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - do { \ - asm ("mullw %0,%1,%2" \ - : "=r" (lo) \ - : "%r" (x), "r" (y)); \ - asm ("mulhw %0,%1,%2" \ - : "=r" (hi) \ - : "%r" (x), "r" (y)); \ - } \ - while (0) - -# if defined(OPT_ACCURACY) -/* - * This gives best accuracy but is not very fast. - */ -# define MAD_F_MLA(hi, lo, x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - asm ("addc %0,%2,%3\n\t" \ - "adde %1,%4,%5" \ - : "=r" (lo), "=r" (hi) \ - : "%r" (lo), "r" (__lo), \ - "%r" (hi), "r" (__hi) \ - : "xer"); \ - }) -# endif - -# if defined(OPT_ACCURACY) -/* - * This is slower than the truncating version below it. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result, __round; \ - asm ("rotrwi %0,%1,%2" \ - : "=r" (__result) \ - : "r" (lo), "i" (MAD_F_SCALEBITS)); \ - asm ("extrwi %0,%1,1,0" \ - : "=r" (__round) \ - : "r" (__result)); \ - asm ("insrwi %0,%1,%2,0" \ - : "+r" (__result) \ - : "r" (hi), "i" (MAD_F_SCALEBITS)); \ - asm ("add %0,%1,%2" \ - : "=r" (__result) \ - : "%r" (__result), "r" (__round)); \ - __result; \ - }) -# else -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("rotrwi %0,%1,%2" \ - : "=r" (__result) \ - : "r" (lo), "i" (MAD_F_SCALEBITS)); \ - asm ("insrwi %0,%1,%2,0" \ - : "+r" (__result) \ - : "r" (hi), "i" (MAD_F_SCALEBITS)); \ - __result; \ - }) -# endif - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- Default ------------------------------------------------------------- */ - -# elif defined(FPM_DEFAULT) - -/* - * This version is the most portable but it loses significant accuracy. - * Furthermore, accuracy is biased against the second argument, so care - * should be taken when ordering operands. - * - * The scale factors are constant as this is not used with SSO. - * - * Pre-rounding is required to stay within the limits of compliance. - */ -# if defined(OPT_SPEED) -# define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16)) -# else -# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ - (((y) + (1L << 15)) >> 16)) -# endif - -/* ------------------------------------------------------------------------- */ - -# else -# error "no FPM selected" -# endif - -/* default implementations */ - -# if !defined(mad_f_mul) -# define mad_f_mul(x, y) \ - ({ register mad_fixed64hi_t __hi; \ - register mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - mad_f_scale64(__hi, __lo); \ - }) -# endif - -# if !defined(MAD_F_MLA) -# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) -# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) -# define MAD_F_MLN(hi, lo) ((lo) = -(lo)) -# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) -# endif - -# if !defined(MAD_F_ML0) -# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) -# endif - -# if !defined(MAD_F_MLN) -# define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi)) -# endif - -# if !defined(MAD_F_MLZ) -# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) -# endif - -# if !defined(mad_f_scale64) -# if defined(OPT_ACCURACY) -# define mad_f_scale64(hi, lo) \ - ((((mad_fixed_t) \ - (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ - ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) -# else -# define mad_f_scale64(hi, lo) \ - ((mad_fixed_t) \ - (((hi) << (32 - MAD_F_SCALEBITS)) | \ - ((lo) >> MAD_F_SCALEBITS))) -# endif -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* C routines */ - -mad_fixed_t mad_f_abs(mad_fixed_t); -mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t); - -# endif - -/* Id: bit.h,v 1.11 2003/05/27 22:40:36 rob Exp */ - -# ifndef LIBMAD_BIT_H -# define LIBMAD_BIT_H - -struct mad_bitptr { - unsigned char const *byte; - unsigned short cache; - unsigned short left; -}; - -void mad_bit_init(struct mad_bitptr *, unsigned char const *); - -# define mad_bit_finish(bitptr) /* nothing */ - -unsigned int mad_bit_length(struct mad_bitptr const *, - struct mad_bitptr const *); - -# define mad_bit_bitsleft(bitptr) ((bitptr)->left) -unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *); - -void mad_bit_skip(struct mad_bitptr *, unsigned int); -unsigned long mad_bit_read(struct mad_bitptr *, unsigned int); -void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long); - -unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short); - -# endif - -/* Id: timer.h,v 1.15 2003/05/27 22:40:37 rob Exp */ - -# ifndef LIBMAD_TIMER_H -# define LIBMAD_TIMER_H - -typedef struct { - signed long seconds; /* whole seconds */ - unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */ -} mad_timer_t; - -extern mad_timer_t const mad_timer_zero; - -# define MAD_TIMER_RESOLUTION 352800000UL - -enum mad_units { - MAD_UNITS_HOURS = -2, - MAD_UNITS_MINUTES = -1, - MAD_UNITS_SECONDS = 0, - - /* metric units */ - - MAD_UNITS_DECISECONDS = 10, - MAD_UNITS_CENTISECONDS = 100, - MAD_UNITS_MILLISECONDS = 1000, - - /* audio sample units */ - - MAD_UNITS_8000_HZ = 8000, - MAD_UNITS_11025_HZ = 11025, - MAD_UNITS_12000_HZ = 12000, - - MAD_UNITS_16000_HZ = 16000, - MAD_UNITS_22050_HZ = 22050, - MAD_UNITS_24000_HZ = 24000, - - MAD_UNITS_32000_HZ = 32000, - MAD_UNITS_44100_HZ = 44100, - MAD_UNITS_48000_HZ = 48000, - - /* video frame/field units */ - - MAD_UNITS_24_FPS = 24, - MAD_UNITS_25_FPS = 25, - MAD_UNITS_30_FPS = 30, - MAD_UNITS_48_FPS = 48, - MAD_UNITS_50_FPS = 50, - MAD_UNITS_60_FPS = 60, - - /* CD audio frames */ - - MAD_UNITS_75_FPS = 75, - - /* video drop-frame units */ - - MAD_UNITS_23_976_FPS = -24, - MAD_UNITS_24_975_FPS = -25, - MAD_UNITS_29_97_FPS = -30, - MAD_UNITS_47_952_FPS = -48, - MAD_UNITS_49_95_FPS = -50, - MAD_UNITS_59_94_FPS = -60 -}; - -# define mad_timer_reset(timer) ((void) (*(timer) = mad_timer_zero)) - -int mad_timer_compare(mad_timer_t, mad_timer_t); - -# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero) - -void mad_timer_negate(mad_timer_t *); -mad_timer_t mad_timer_abs(mad_timer_t); - -void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long); -void mad_timer_add(mad_timer_t *, mad_timer_t); -void mad_timer_multiply(mad_timer_t *, signed long); - -signed long mad_timer_count(mad_timer_t, enum mad_units); -unsigned long mad_timer_fraction(mad_timer_t, unsigned long); -void mad_timer_string(mad_timer_t, char *, char const *, - enum mad_units, enum mad_units, unsigned long); - -# endif - -/* Id: stream.h,v 1.18 2003/05/27 22:40:37 rob Exp */ - -# ifndef LIBMAD_STREAM_H -# define LIBMAD_STREAM_H - - -# define MAD_BUFFER_GUARD 8 -# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD) - -enum mad_error { - MAD_ERROR_NONE = 0x0000, /* no error */ - - MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */ - MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */ - - MAD_ERROR_NOMEM = 0x0031, /* not enough memory */ - - MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */ - MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */ - MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */ - MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */ - MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */ - - MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */ - MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */ - MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */ - MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */ - MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */ - MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */ - MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */ - MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */ - MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */ - MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */ - MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */ - MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */ -}; - -# define MAD_RECOVERABLE(error) ((error) & 0xff00) - -struct mad_stream { - unsigned char const *buffer; /* input bitstream buffer */ - unsigned char const *bufend; /* end of buffer */ - unsigned long skiplen; /* bytes to skip before next frame */ - - int sync; /* stream sync found */ - unsigned long freerate; /* free bitrate (fixed) */ - - unsigned char const *this_frame; /* start of current frame */ - unsigned char const *next_frame; /* start of next frame */ - struct mad_bitptr ptr; /* current processing bit pointer */ - - struct mad_bitptr anc_ptr; /* ancillary bits pointer */ - unsigned int anc_bitlen; /* number of ancillary bits */ - - unsigned char (*main_data)[MAD_BUFFER_MDLEN]; - /* Layer III main_data() */ - unsigned int md_len; /* bytes in main_data */ - - int options; /* decoding options (see below) */ - enum mad_error error; /* error code (see above) */ -}; - -enum { - MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */ - MAD_OPTION_HALFSAMPLERATE = 0x0002 /* generate PCM at 1/2 sample rate */ -# if 0 /* not yet implemented */ - MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */ - MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */ - MAD_OPTION_SINGLECHANNEL = 0x0030 /* combine channels */ -# endif -}; - -void mad_stream_init(struct mad_stream *); -void mad_stream_finish(struct mad_stream *); - -# define mad_stream_options(stream, opts) \ - ((void) ((stream)->options = (opts))) - -void mad_stream_buffer(struct mad_stream *, - unsigned char const *, unsigned long); -void mad_stream_skip(struct mad_stream *, unsigned long); - -int mad_stream_sync(struct mad_stream *); - -char const *mad_stream_errorstr(struct mad_stream const *); - -# endif - -/* Id: frame.h,v 1.19 2003/05/27 22:40:36 rob Exp */ - -# ifndef LIBMAD_FRAME_H -# define LIBMAD_FRAME_H - - -enum mad_layer { - MAD_LAYER_I = 1, /* Layer I */ - MAD_LAYER_II = 2, /* Layer II */ - MAD_LAYER_III = 3 /* Layer III */ -}; - -enum mad_mode { - MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ - MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ - MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */ - MAD_MODE_STEREO = 3 /* normal LR stereo */ -}; - -enum mad_emphasis { - MAD_EMPHASIS_NONE = 0, /* no emphasis */ - MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */ - MAD_EMPHASIS_CCITT_J_17 = 3, /* CCITT J.17 emphasis */ - MAD_EMPHASIS_RESERVED = 2 /* unknown emphasis */ -}; - -struct mad_header { - enum mad_layer layer; /* audio layer (1, 2, or 3) */ - enum mad_mode mode; /* channel mode (see above) */ - int mode_extension; /* additional mode info */ - enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ - - unsigned long bitrate; /* stream bitrate (bps) */ - unsigned int samplerate; /* sampling frequency (Hz) */ - - unsigned short crc_check; /* frame CRC accumulator */ - unsigned short crc_target; /* final target CRC checksum */ - - int flags; /* flags (see below) */ - int private_bits; /* private bits (see below) */ - - mad_timer_t duration; /* audio playing time of frame */ -}; - -struct mad_frame { - struct mad_header header; /* MPEG audio header */ - - int options; /* decoding options (from stream) */ - - mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ - mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ -}; - -# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1) -# define MAD_NSBSAMPLES(header) \ - ((header)->layer == MAD_LAYER_I ? 12 : \ - (((header)->layer == MAD_LAYER_III && \ - ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36)) - -enum { - MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */ - MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */ - - MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */ - MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */ - MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */ - MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */ - - MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */ - MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */ - MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */ - - MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */ - MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */ - MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */ -}; - -enum { - MAD_PRIVATE_HEADER = 0x0100, /* header private bit */ - MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */ -}; - -void mad_header_init(struct mad_header *); - -# define mad_header_finish(header) /* nothing */ - -int mad_header_decode(struct mad_header *, struct mad_stream *); - -void mad_frame_init(struct mad_frame *); -void mad_frame_finish(struct mad_frame *); - -int mad_frame_decode(struct mad_frame *, struct mad_stream *); - -void mad_frame_mute(struct mad_frame *); - -# endif - -/* Id: synth.h,v 1.14 2003/05/27 22:40:37 rob Exp */ - -# ifndef LIBMAD_SYNTH_H -# define LIBMAD_SYNTH_H - - -struct mad_pcm { - unsigned int samplerate; /* sampling frequency (Hz) */ - unsigned short channels; /* number of channels */ - unsigned short length; /* number of samples per channel */ - mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */ -}; - -struct mad_synth { - mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ - /* [ch][eo][peo][s][v] */ - - unsigned int phase; /* current processing phase */ - - struct mad_pcm pcm; /* PCM output */ -}; - -/* single channel PCM selector */ -enum { - MAD_PCM_CHANNEL_SINGLE = 0 -}; - -/* dual channel PCM selector */ -enum { - MAD_PCM_CHANNEL_DUAL_1 = 0, - MAD_PCM_CHANNEL_DUAL_2 = 1 -}; - -/* stereo PCM selector */ -enum { - MAD_PCM_CHANNEL_STEREO_LEFT = 0, - MAD_PCM_CHANNEL_STEREO_RIGHT = 1 -}; - -void mad_synth_init(struct mad_synth *); - -# define mad_synth_finish(synth) /* nothing */ - -void mad_synth_mute(struct mad_synth *); - -void mad_synth_frame(struct mad_synth *, struct mad_frame const *); - -# endif - -/* Id: decoder.h,v 1.16 2003/05/27 22:40:36 rob Exp */ - -# ifndef LIBMAD_DECODER_H -# define LIBMAD_DECODER_H - - -enum mad_decoder_mode { - MAD_DECODER_MODE_SYNC = 0, - MAD_DECODER_MODE_ASYNC -}; - -enum mad_flow { - MAD_FLOW_CONTINUE = 0x0000, /* continue normally */ - MAD_FLOW_STOP = 0x0010, /* stop decoding normally */ - MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */ - MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */ -}; - -struct mad_decoder { - enum mad_decoder_mode mode; - - int options; - - struct { - long pid; - int in; - int out; - } async; - - struct { - struct mad_stream stream; - struct mad_frame frame; - struct mad_synth synth; - } *sync; - - void *cb_data; - - enum mad_flow (*input_func)(void *, struct mad_stream *); - enum mad_flow (*header_func)(void *, struct mad_header const *); - enum mad_flow (*filter_func)(void *, - struct mad_stream const *, struct mad_frame *); - enum mad_flow (*output_func)(void *, - struct mad_header const *, struct mad_pcm *); - enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); - enum mad_flow (*message_func)(void *, void *, unsigned int *); -}; - -void mad_decoder_init(struct mad_decoder *, void *, - enum mad_flow (*)(void *, struct mad_stream *), - enum mad_flow (*)(void *, struct mad_header const *), - enum mad_flow (*)(void *, - struct mad_stream const *, - struct mad_frame *), - enum mad_flow (*)(void *, - struct mad_header const *, - struct mad_pcm *), - enum mad_flow (*)(void *, - struct mad_stream *, - struct mad_frame *), - enum mad_flow (*)(void *, void *, unsigned int *)); -int mad_decoder_finish(struct mad_decoder *); - -# define mad_decoder_options(decoder, opts) \ - ((void) ((decoder)->options = (opts))) - -int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode); -int mad_decoder_message(struct mad_decoder *, void *, unsigned int *); - -# endif - -# ifdef __cplusplus -} -# endif diff --git a/libmad/libmad.vcxproj b/libmad/libmad.vcxproj deleted file mode 100644 index 2a8de58..0000000 --- a/libmad/libmad.vcxproj +++ /dev/null @@ -1,141 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {7DDFB46B-0754-450D-9A7A-4B982E40367D} - libmad - Win32Proj - - - - StaticLibrary - NotSet - true - v110_xp - - - StaticLibrary - NotSet - v110_xp - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)build\temp\lib\ - $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ - $(SolutionDir)build\temp\lib\ - $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ - AllRules.ruleset - - - AllRules.ruleset - - - $(ProjectName)-mt-debug - $(ProjectName)-mt - - - - Disabled - $(ProjectDir)configured\;%(AdditionalIncludeDirectories) - _WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;FPM_INTEL;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - false - - - EnableFastChecks - MultiThreadedDebug - - - $(IntDir)vc90.pdb - Level3 - OldStyle - - - - - xcopy "$(ProjectDir)configured\mad.h" "$(SolutionDir)build\temp\include\" /I /Y /D - - - - - - MaxSpeed - true - $(ProjectDir)configured\;%(AdditionalIncludeDirectories) - _WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;FPM_INTEL;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - - - MultiThreaded - true - - - $(IntDir)vc90.pdb - Level3 - - - - - - - xcopy "$(ProjectDir)configured\mad.h" "$(SolutionDir)build\temp\include\" /I /Y /D - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libmad/libmad.vcxproj.filters b/libmad/libmad.vcxproj.filters deleted file mode 100644 index ebc6bb9..0000000 --- a/libmad/libmad.vcxproj.filters +++ /dev/null @@ -1,105 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - \ No newline at end of file diff --git a/libmad/src/CHANGES b/libmad/src/CHANGES deleted file mode 100644 index 9291760..0000000 --- a/libmad/src/CHANGES +++ /dev/null @@ -1,338 +0,0 @@ - - libmad - MPEG audio decoder library - Copyright (C) 2000-2004 Underbit Technologies, Inc. - - $Id: CHANGES,v 1.14 2004/02/17 02:02:03 rob Exp $ - -=============================================================================== - -Version 0.15.1 (beta) - - * Updated to autoconf 2.59, automake 1.8.2, libtool 1.5.2. - - * Replaced Layer III IMDCT routine with one based on a faster algorithm, - improving both speed and accuracy. - - * Improved portability of the Huffman table initialization. - - * Fixed a problem that could result in an assertion failure in layer3.c - due to an invalid Layer III free format bitrate. - - * Improved the robustness of Layer II bitrate/mode combinations, and added - a new MAD_ERROR_BADMODE error enum. The allowability of low-bitrate - stereo streams is influenced by the --enable-strict-iso option to - `configure'. - -Version 0.15.0 (beta) - - * Updated to autoconf 2.57, automake 1.7.5, libtool 1.4.3. - - * Added new mad_f_div() API routine. - - * Added a 64th entry to the Layer I/Layer II scalefactor table, for better - compatibility with existing streams. The --enable-strict-iso option to - `configure' can be used to disable use of this entry. - - * Modified the header decoding routine to allow the reserved emphasis - value, for better compatibility with existing streams. The - --enable-strict-iso option to `configure' can be used to restore the - previous behavior of reporting this value as an error. - - * Added new MAD_EMPHASIS_RESERVED enumeration constant. - - * Fixed a bug in the ARM version of mad_f_scale64() discovered by Andre - McCurdy. - - * Rewrote PowerPC assembly for minor gains. - - * Modified mad_timer_fraction() to avoid the possibility of division by - zero when 0 is passed as the second argument. - - * Fixed a non-fatal problem caused by attempting to designate ancillary - bits in Layer III after a decoding error. - - * Changed to build a shared library by default. - - * Changed to use native Cygwin build by default; give --host=mingw32 to - `configure' to use MinGW (and avoid a dependency on the Cygwin DLL). - -Version 0.14.2 (beta) - - * Changed Cygwin builds to use MinGW; resulting Win32 executables no - longer have a dependency on Cygwin DLLs. - - * Added a new mad_stream_errorstr() API function to libmad for retrieving - a string description of the current error condition. - -Version 0.14.1 (beta) - - * Updated config.guess and config.sub to latest upstream versions. - - * Enabled libtool versioning rather than release numbering. - - * Improved the documentation in minimad.c. - - * Several other small fixes. - -Version 0.14.0 (beta) - - * Added a 64-bit FPM negation operation to improve performance of subband - synthesis on some platforms. - - * Improved MSVC++ portability and added MSVC++ project files. - - * Added rounding to Layer III requantization for slightly better accuracy. - -Version 0.13.0 (beta) - - * Ancillary data is now properly extracted from Layer III streams. - - * Rewrote the Layer III joint stereo decoding routine to correct a major - MPEG-2 problem and a minor MPEG-1 problem decoding intensity stereo. - - * Eliminated the dependency on sign-extending right shifts for Layer I and - Layer II. - - * Renamed `private' field to `private_bits' for better C++ compatibility. - - * Gratuitously renamed `sfreq' field to `samplerate' and - MAD_ERROR_BADSAMPLEFREQ constant to MAD_ERROR_BADSAMPLERATE. - - * Added `samplerate' and `channels' fields to synth.pcm struct to allow - these to be different from the decoded frame, and for simpler access. - - * Added new mad_stream_options() and mad_decoder_options() API entries for - special runtime decoding options. - - * Added new MAD_OPTION_IGNORECRC and MAD_OPTION_HALFSAMPLERATE options. - - * Added new MAD_FLAG_FREEFORMAT indicator flag. - - * Fixed some bugs in the async decoder. - - * Added a new mad_timer_multiply() API routine. - - * Eliminated `+' from asm constraints under Intel for better compatibility - with some compilers. - - * Fixed a PIC-related problem in imdct_l_arm.S. - - * Eliminated a static variable to make libmad thread-safe. - -Version 0.12.5 (beta) - - * Modified Layer III requantization to occur during Huffman decoding for - significant performance gains. - - * Optimized short block IMDCT by eliminating redundant calculations. - - * Made several other Layer III performance improvements; added - ASO_INTERLEAVE1, ASO_INTERLEAVE2, and ASO_ZEROCHECK - architecture-specific options for best performance on various - architectures. - - * Optimized synthesis DCT to store result values as soon as they are - calculated. - -Version 0.12.4 (beta) - - * New PowerPC fixed-point assembly courtesy of David Blythe. - - * Reorganized fixed-point assembly routines for easier maintenance and - better performance. - - * Improved performance of subband synthesis through better indexing and - fewer local variables. - - * Added alias reduction for the lower two subbands of mixed short blocks, - per a report of ambiguity with ISO/IEC 11172-3 and for uniformity with - most other implementations. Also improved alias reduction performance - using multiply/accumulate. - - * Added --enable-strict-iso option to `configure' to override best - accepted practices such as the alias reduction for mixed short blocks. - - * Improved performance of Layer III IMDCT by using longer - multiply/accumulate runs where possible. - -Version 0.12.3 (beta) - - * Added MPEG 2.5 support. - - * Added preliminary support for parameterizing the binary point position - in the fixed-point representation. - - * Added multiply/accumulate optimization to the Layer III IMDCT for long - blocks. - - * Fixed a bug in the handling of Layer III mixed_block_flag. - - * Fixed a configure problem when multiple -O CFLAGS are present. - -Version 0.12.2 (beta) - - * Rearranged the synthesis polyphase filterbank memory vector for better - locality of reference, and rewrote mad_synth_frame() to accommodate, - resulting in improved performance. - - * Discovered a combination of compiler optimization flags that further - improve performance. - - * Changed some array references in layer3.c to pointer derefs. - -Version 0.12.1 (beta) - - * Resolved the intensity + MS joint stereo issue (a simple bug). - OPT_ISKLUGE is no longer considered to be a kluge. - - * Fixed another, hopefully last main_data memory bug. - - * Split part of struct mad_frame into struct mad_header for convenience - and size. - -Version 0.12.0 (alpha) - - * Changed the build environment to use automake and libtool. A libmad - shared library can now be built using the --enable-shared option to - `configure'. - - * Added another callback to MAD's high-level decoder API after the frame - header has been read but before the frame's audio data is decoded. - - * Streamlined header processing so that mad_frame_decode() can be called - with or without having already called mad_frame_header(). - - * Fixed some other header reading miscellany, including CRC handling and - free bitrate detection, and frame length verification with free - bitrates. - - * Fixed a problem with Layer III free bitrates > 320 kbps. The main_data - buffer size should now be large enough to handle any size frame, by - virtue of the maximum possible part2_3_length. - - * Further developed the async API; arbitrary messages can now be passed to - the subsidiary decoding process. - - * Streamlined timer.c and extended its interface. It now has support for - video frame/field lengths, including output support for drop-frame - encoding. - - * Replaced many constant integer preprocessor defines with enums. - -Version 0.11.4 (beta) - - * Fixed free format bitrate discovery. - - * Changed the timer implementation and extended its interface. - - * Integrated Nicolas Pitre's patch for pre-shifting at compile-time and - for better multiply/accumulate code output. - - * Applied Simon Burge's patch to imdct_l_arm.S for a.out compatibility. - - * Added -mtune=strongarm for all ARM targets. - -Version 0.11.3 (beta) - - * Added new --enable-speed and --enable-accuracy options for `configure' - to automatically select appropriate SSO/ASO options, et al. - - * Modified subband synthesis to use multiply/accumulate optimization (if - available) for better speed and/or accuracy. - - * Incorporated Andre McCurdy's changes for further rounding optimizations - in the rest of his code. - -Version 0.11.2 (beta) - - * Incorporated Nicolas Pitre's ARM assembly and parameterized scaling - changes. - - * Incorporated Andre McCurdy's ARM assembly optimization (used only if - --enable-aso is given to `configure' to enable architecture-specific - optimizations.) - - * Reduced FPM_INTEL assembly to two instructions. - - * Fixed accuracy problems with certain FPM modes in synth.c. - - * Improved the accuracy of FPM_APPROX. - - * Improved the accuracy of SSO. - - * Improved sync discovery by checking for a sync word in the following - frame. - - * Minor code clean-up. - - * Added experimental rules for generating a libmad.so shared library. - -Version 0.11.1 (beta) - - * Moved libmad code into a separate directory. - - * Changed SSO to be disabled by default, as output accuracy is deemed to - be more important than speed in the general case. - - * Fixed a bug in Layer III sanity checking that could cause a crash on - certain random data input. - - * Extended the Layer III requantization table from 8191 to 8206 as some - encoders are known to use these values, even though ISO/IEC 11172-3 - suggests the maximum should be 8191. - -Version 0.11.0 (beta) - - * Implemented MPEG-2 extension to Lower Sampling Frequencies. - - * Improved Layer III performance by avoiding IMDCT calculation when all - input samples are zero. - - * Significantly reduced size of Layer II tables. - -Version 0.10.3 (beta) - - * Improved SSO output quality. - - * Made portable to cygwin. - - * Localized memory references in III_huffdecode() for better performance. - -Version 0.10.2 (beta) - - * Rewrote Layer III long block 36-point IMDCT routine for better - performance. - - * Improved subband synthesis fixed-point games somewhat. - -Version 0.10.1 (beta) - - * Added a subband synthesis optimization (SSO) which involves modifying - the fixed-point multiplication method during windowing. This produces - subtle differences in the output but improves performance greatly. - - * Added I_STEREO and MS_STEREO flags to frame struct. - - * Eliminated privately-used CRCFAILED flag. - - * Fixed a bug where Layer III decoding could crash on some badly-formatted - (e.g. non-MPEG) bitstreams. - - * Miscellaneous code clean-up. - -Version 0.10.0 (beta) - - * Added SPARC fixed-point math support. - - * Revamped libmad API for better high- and low-level support. - - * Documented more of the code. - - * Changed sync semantics such that new stream buffers are assumed to be - sync-aligned. - - * Changed Layer III to dynamically allocate static memory so as not to - waste it (about 6.4K) when only decoding Layer I or Layer II. - -=============================================================================== - diff --git a/libmad/src/COPYING b/libmad/src/COPYING deleted file mode 100644 index d60c31a..0000000 --- a/libmad/src/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/libmad/src/COPYRIGHT b/libmad/src/COPYRIGHT deleted file mode 100644 index ed91d2b..0000000 --- a/libmad/src/COPYRIGHT +++ /dev/null @@ -1,21 +0,0 @@ - - libmad - MPEG audio decoder library - Copyright (C) 2000-2004 Underbit Technologies, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - If you would like to negotiate alternate licensing terms, you may do - so by contacting: Underbit Technologies, Inc. - diff --git a/libmad/src/CREDITS b/libmad/src/CREDITS deleted file mode 100644 index 72ec72e..0000000 --- a/libmad/src/CREDITS +++ /dev/null @@ -1,116 +0,0 @@ - - libmad - MPEG audio decoder library - Copyright (C) 2000-2004 Underbit Technologies, Inc. - - $Id: CREDITS,v 1.5 2004/02/17 02:02:03 rob Exp $ - -=============================================================================== - -AUTHOR - - Except where otherwise noted, all code was authored by: - - Robert Leslie - -CONTRIBUTORS - - Significant contributions have been incorporated with thanks to: - - Anonymous - 2002/03/15: frame.c - - Reported problem with use of reserved emphasis value. - 2003/08/31: layer12.c - - Suggested support for certain disallowed bitrate/mode - combinations. - - Niek Albers - 2003/04/21: layer3.c - - Reported runtime uninitialized use of `ptr' in designating - ancillary bits after a decoding error. - - Christian Biere - 2003/02/01: frame.c - - Reported assertion failure in layer3.c due to an - invalid/unsupported Layer III free format bitrate. - - David Blythe - 2001/01/30: fixed.h - - Provided initial PowerPC fixed-point assembly. - - Simon Burge - 2000/09/20: imdct_l_arm.S - - Suggested patch for a.out compatibility. - - Brian Cameron - 2003/07/02: huffman.c - - Suggested changes for improved portability. - - Joshua Haberman - 2001/08/10: decoder.c, huffman.c - - Suggested portability fixes. - - Timothy King - 2002/05/04: sf_table.dat, layer12.c - - Reported problem with use of (missing) scalefactor index 63. - - Felix von Leitner - 2003/01/21: fixed.h - - Suggested Intel scaling alternative for possible speedup. - - Andre McCurdy - 2000/08/10: imdct_l_arm.S - - ARM optimized assembly replacement for III_imdct_l(). - 2000/09/15: imdct_l_arm.S - - Applied Nicolas Pitre's rounding optimisation in all remaining - places. - 2001/02/10: layer3.c - - Inspiration for Huffman decoding and requantization rewrite, and - other miscellany. - 2001/03/24: imdct_l_arm.S - - Corrected PIC unsafe code. - 2002/02/16: fixed.h - - Discovered bug in ARM version of mad_f_scale64(). - - Haruhiko OGASAWARA - 2001/01/28: layer3.c - - Reported discrepancy in alias reduction for mixed short blocks. - - Brett Paterson - 2001/10/28: global.h - - Reported missing et al. under MS Embedded Visual C. - - Sean 'Shaleh' Perry - 2000/04/04: fixed.h - - Suggested use of size-dependent typedefs. - 2001/10/22: config.guess, config.sub - - Keep up to date for proper Debian packaging. - - Bertrand Petit - 2001/11/05: synth.h - - Suggested PCM channel enumeration constants. - 2001/11/05: stream.h - - Suggested MAD_ERROR_NONE enumeration constant. - 2001/11/05: stream.c - - Suggested mad_stream_errorstr() function. - - Nicolas Pitre - 2000/09/09: fixed.h - - Parameterized all scaling for correct use of all multiplication - methods within mad_synth_frame(). - - Rewrote the FPM_ARM version of mad_f_mul() so we have 64-bit - multiplication result, rounding and scaling with 3 instructions. - 2000/09/09: imdct_l_arm.S - - Optimized rounding + scaling operations. - 2000/09/17: synth.c - - Changed D[] run-time shifts to compile-time. - - Modified synthesis for better multiply/accumulate code output. - 2001/08/11: fixed.h, synth.c - - Suggested 64-bit FPM negation and negative term factorization - during synthesis. - 2001/08/11: fixed.h - - Suggested unrounded behavior for FPM_DEFAULT when OPT_SPEED. - 2001/11/19: fixed.c - - Suggested computation of any resampling ratio. - -=============================================================================== - diff --git a/libmad/src/D.dat b/libmad/src/D.dat deleted file mode 100644 index 4a7fa4f..0000000 --- a/libmad/src/D.dat +++ /dev/null @@ -1,607 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: D.dat,v 1.9 2004/01/23 09:41:32 rob Exp $ - */ - -/* - * These are the coefficients for the subband synthesis window. This is a - * reordered version of Table B.3 from ISO/IEC 11172-3. - * - * Every value is parameterized so that shift optimizations can be made at - * compile-time. For example, every value can be right-shifted 12 bits to - * minimize multiply instruction times without any loss of accuracy. - */ - - { PRESHIFT(0x00000000) /* 0.000000000 */, /* 0 */ - -PRESHIFT(0x0001d000) /* -0.000442505 */, - PRESHIFT(0x000d5000) /* 0.003250122 */, - -PRESHIFT(0x001cb000) /* -0.007003784 */, - PRESHIFT(0x007f5000) /* 0.031082153 */, - -PRESHIFT(0x01421000) /* -0.078628540 */, - PRESHIFT(0x019ae000) /* 0.100311279 */, - -PRESHIFT(0x09271000) /* -0.572036743 */, - PRESHIFT(0x1251e000) /* 1.144989014 */, - PRESHIFT(0x09271000) /* 0.572036743 */, - PRESHIFT(0x019ae000) /* 0.100311279 */, - PRESHIFT(0x01421000) /* 0.078628540 */, - PRESHIFT(0x007f5000) /* 0.031082153 */, - PRESHIFT(0x001cb000) /* 0.007003784 */, - PRESHIFT(0x000d5000) /* 0.003250122 */, - PRESHIFT(0x0001d000) /* 0.000442505 */, - - PRESHIFT(0x00000000) /* 0.000000000 */, - -PRESHIFT(0x0001d000) /* -0.000442505 */, - PRESHIFT(0x000d5000) /* 0.003250122 */, - -PRESHIFT(0x001cb000) /* -0.007003784 */, - PRESHIFT(0x007f5000) /* 0.031082153 */, - -PRESHIFT(0x01421000) /* -0.078628540 */, - PRESHIFT(0x019ae000) /* 0.100311279 */, - -PRESHIFT(0x09271000) /* -0.572036743 */, - PRESHIFT(0x1251e000) /* 1.144989014 */, - PRESHIFT(0x09271000) /* 0.572036743 */, - PRESHIFT(0x019ae000) /* 0.100311279 */, - PRESHIFT(0x01421000) /* 0.078628540 */, - PRESHIFT(0x007f5000) /* 0.031082153 */, - PRESHIFT(0x001cb000) /* 0.007003784 */, - PRESHIFT(0x000d5000) /* 0.003250122 */, - PRESHIFT(0x0001d000) /* 0.000442505 */ }, - - { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 1 */ - -PRESHIFT(0x0001f000) /* -0.000473022 */, - PRESHIFT(0x000da000) /* 0.003326416 */, - -PRESHIFT(0x00207000) /* -0.007919312 */, - PRESHIFT(0x007d0000) /* 0.030517578 */, - -PRESHIFT(0x0158d000) /* -0.084182739 */, - PRESHIFT(0x01747000) /* 0.090927124 */, - -PRESHIFT(0x099a8000) /* -0.600219727 */, - PRESHIFT(0x124f0000) /* 1.144287109 */, - PRESHIFT(0x08b38000) /* 0.543823242 */, - PRESHIFT(0x01bde000) /* 0.108856201 */, - PRESHIFT(0x012b4000) /* 0.073059082 */, - PRESHIFT(0x0080f000) /* 0.031478882 */, - PRESHIFT(0x00191000) /* 0.006118774 */, - PRESHIFT(0x000d0000) /* 0.003173828 */, - PRESHIFT(0x0001a000) /* 0.000396729 */, - - -PRESHIFT(0x00001000) /* -0.000015259 */, - -PRESHIFT(0x0001f000) /* -0.000473022 */, - PRESHIFT(0x000da000) /* 0.003326416 */, - -PRESHIFT(0x00207000) /* -0.007919312 */, - PRESHIFT(0x007d0000) /* 0.030517578 */, - -PRESHIFT(0x0158d000) /* -0.084182739 */, - PRESHIFT(0x01747000) /* 0.090927124 */, - -PRESHIFT(0x099a8000) /* -0.600219727 */, - PRESHIFT(0x124f0000) /* 1.144287109 */, - PRESHIFT(0x08b38000) /* 0.543823242 */, - PRESHIFT(0x01bde000) /* 0.108856201 */, - PRESHIFT(0x012b4000) /* 0.073059082 */, - PRESHIFT(0x0080f000) /* 0.031478882 */, - PRESHIFT(0x00191000) /* 0.006118774 */, - PRESHIFT(0x000d0000) /* 0.003173828 */, - PRESHIFT(0x0001a000) /* 0.000396729 */ }, - - { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 2 */ - -PRESHIFT(0x00023000) /* -0.000534058 */, - PRESHIFT(0x000de000) /* 0.003387451 */, - -PRESHIFT(0x00245000) /* -0.008865356 */, - PRESHIFT(0x007a0000) /* 0.029785156 */, - -PRESHIFT(0x016f7000) /* -0.089706421 */, - PRESHIFT(0x014a8000) /* 0.080688477 */, - -PRESHIFT(0x0a0d8000) /* -0.628295898 */, - PRESHIFT(0x12468000) /* 1.142211914 */, - PRESHIFT(0x083ff000) /* 0.515609741 */, - PRESHIFT(0x01dd8000) /* 0.116577148 */, - PRESHIFT(0x01149000) /* 0.067520142 */, - PRESHIFT(0x00820000) /* 0.031738281 */, - PRESHIFT(0x0015b000) /* 0.005294800 */, - PRESHIFT(0x000ca000) /* 0.003082275 */, - PRESHIFT(0x00018000) /* 0.000366211 */, - - -PRESHIFT(0x00001000) /* -0.000015259 */, - -PRESHIFT(0x00023000) /* -0.000534058 */, - PRESHIFT(0x000de000) /* 0.003387451 */, - -PRESHIFT(0x00245000) /* -0.008865356 */, - PRESHIFT(0x007a0000) /* 0.029785156 */, - -PRESHIFT(0x016f7000) /* -0.089706421 */, - PRESHIFT(0x014a8000) /* 0.080688477 */, - -PRESHIFT(0x0a0d8000) /* -0.628295898 */, - PRESHIFT(0x12468000) /* 1.142211914 */, - PRESHIFT(0x083ff000) /* 0.515609741 */, - PRESHIFT(0x01dd8000) /* 0.116577148 */, - PRESHIFT(0x01149000) /* 0.067520142 */, - PRESHIFT(0x00820000) /* 0.031738281 */, - PRESHIFT(0x0015b000) /* 0.005294800 */, - PRESHIFT(0x000ca000) /* 0.003082275 */, - PRESHIFT(0x00018000) /* 0.000366211 */ }, - - { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 3 */ - -PRESHIFT(0x00026000) /* -0.000579834 */, - PRESHIFT(0x000e1000) /* 0.003433228 */, - -PRESHIFT(0x00285000) /* -0.009841919 */, - PRESHIFT(0x00765000) /* 0.028884888 */, - -PRESHIFT(0x0185d000) /* -0.095169067 */, - PRESHIFT(0x011d1000) /* 0.069595337 */, - -PRESHIFT(0x0a7fe000) /* -0.656219482 */, - PRESHIFT(0x12386000) /* 1.138763428 */, - PRESHIFT(0x07ccb000) /* 0.487472534 */, - PRESHIFT(0x01f9c000) /* 0.123474121 */, - PRESHIFT(0x00fdf000) /* 0.061996460 */, - PRESHIFT(0x00827000) /* 0.031845093 */, - PRESHIFT(0x00126000) /* 0.004486084 */, - PRESHIFT(0x000c4000) /* 0.002990723 */, - PRESHIFT(0x00015000) /* 0.000320435 */, - - -PRESHIFT(0x00001000) /* -0.000015259 */, - -PRESHIFT(0x00026000) /* -0.000579834 */, - PRESHIFT(0x000e1000) /* 0.003433228 */, - -PRESHIFT(0x00285000) /* -0.009841919 */, - PRESHIFT(0x00765000) /* 0.028884888 */, - -PRESHIFT(0x0185d000) /* -0.095169067 */, - PRESHIFT(0x011d1000) /* 0.069595337 */, - -PRESHIFT(0x0a7fe000) /* -0.656219482 */, - PRESHIFT(0x12386000) /* 1.138763428 */, - PRESHIFT(0x07ccb000) /* 0.487472534 */, - PRESHIFT(0x01f9c000) /* 0.123474121 */, - PRESHIFT(0x00fdf000) /* 0.061996460 */, - PRESHIFT(0x00827000) /* 0.031845093 */, - PRESHIFT(0x00126000) /* 0.004486084 */, - PRESHIFT(0x000c4000) /* 0.002990723 */, - PRESHIFT(0x00015000) /* 0.000320435 */ }, - - { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 4 */ - -PRESHIFT(0x00029000) /* -0.000625610 */, - PRESHIFT(0x000e3000) /* 0.003463745 */, - -PRESHIFT(0x002c7000) /* -0.010848999 */, - PRESHIFT(0x0071e000) /* 0.027801514 */, - -PRESHIFT(0x019bd000) /* -0.100540161 */, - PRESHIFT(0x00ec0000) /* 0.057617187 */, - -PRESHIFT(0x0af15000) /* -0.683914185 */, - PRESHIFT(0x12249000) /* 1.133926392 */, - PRESHIFT(0x075a0000) /* 0.459472656 */, - PRESHIFT(0x0212c000) /* 0.129577637 */, - PRESHIFT(0x00e79000) /* 0.056533813 */, - PRESHIFT(0x00825000) /* 0.031814575 */, - PRESHIFT(0x000f4000) /* 0.003723145 */, - PRESHIFT(0x000be000) /* 0.002899170 */, - PRESHIFT(0x00013000) /* 0.000289917 */, - - -PRESHIFT(0x00001000) /* -0.000015259 */, - -PRESHIFT(0x00029000) /* -0.000625610 */, - PRESHIFT(0x000e3000) /* 0.003463745 */, - -PRESHIFT(0x002c7000) /* -0.010848999 */, - PRESHIFT(0x0071e000) /* 0.027801514 */, - -PRESHIFT(0x019bd000) /* -0.100540161 */, - PRESHIFT(0x00ec0000) /* 0.057617187 */, - -PRESHIFT(0x0af15000) /* -0.683914185 */, - PRESHIFT(0x12249000) /* 1.133926392 */, - PRESHIFT(0x075a0000) /* 0.459472656 */, - PRESHIFT(0x0212c000) /* 0.129577637 */, - PRESHIFT(0x00e79000) /* 0.056533813 */, - PRESHIFT(0x00825000) /* 0.031814575 */, - PRESHIFT(0x000f4000) /* 0.003723145 */, - PRESHIFT(0x000be000) /* 0.002899170 */, - PRESHIFT(0x00013000) /* 0.000289917 */ }, - - { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 5 */ - -PRESHIFT(0x0002d000) /* -0.000686646 */, - PRESHIFT(0x000e4000) /* 0.003479004 */, - -PRESHIFT(0x0030b000) /* -0.011886597 */, - PRESHIFT(0x006cb000) /* 0.026535034 */, - -PRESHIFT(0x01b17000) /* -0.105819702 */, - PRESHIFT(0x00b77000) /* 0.044784546 */, - -PRESHIFT(0x0b619000) /* -0.711318970 */, - PRESHIFT(0x120b4000) /* 1.127746582 */, - PRESHIFT(0x06e81000) /* 0.431655884 */, - PRESHIFT(0x02288000) /* 0.134887695 */, - PRESHIFT(0x00d17000) /* 0.051132202 */, - PRESHIFT(0x0081b000) /* 0.031661987 */, - PRESHIFT(0x000c5000) /* 0.003005981 */, - PRESHIFT(0x000b7000) /* 0.002792358 */, - PRESHIFT(0x00011000) /* 0.000259399 */, - - -PRESHIFT(0x00001000) /* -0.000015259 */, - -PRESHIFT(0x0002d000) /* -0.000686646 */, - PRESHIFT(0x000e4000) /* 0.003479004 */, - -PRESHIFT(0x0030b000) /* -0.011886597 */, - PRESHIFT(0x006cb000) /* 0.026535034 */, - -PRESHIFT(0x01b17000) /* -0.105819702 */, - PRESHIFT(0x00b77000) /* 0.044784546 */, - -PRESHIFT(0x0b619000) /* -0.711318970 */, - PRESHIFT(0x120b4000) /* 1.127746582 */, - PRESHIFT(0x06e81000) /* 0.431655884 */, - PRESHIFT(0x02288000) /* 0.134887695 */, - PRESHIFT(0x00d17000) /* 0.051132202 */, - PRESHIFT(0x0081b000) /* 0.031661987 */, - PRESHIFT(0x000c5000) /* 0.003005981 */, - PRESHIFT(0x000b7000) /* 0.002792358 */, - PRESHIFT(0x00011000) /* 0.000259399 */ }, - - { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 6 */ - -PRESHIFT(0x00031000) /* -0.000747681 */, - PRESHIFT(0x000e4000) /* 0.003479004 */, - -PRESHIFT(0x00350000) /* -0.012939453 */, - PRESHIFT(0x0066c000) /* 0.025085449 */, - -PRESHIFT(0x01c67000) /* -0.110946655 */, - PRESHIFT(0x007f5000) /* 0.031082153 */, - -PRESHIFT(0x0bd06000) /* -0.738372803 */, - PRESHIFT(0x11ec7000) /* 1.120223999 */, - PRESHIFT(0x06772000) /* 0.404083252 */, - PRESHIFT(0x023b3000) /* 0.139450073 */, - PRESHIFT(0x00bbc000) /* 0.045837402 */, - PRESHIFT(0x00809000) /* 0.031387329 */, - PRESHIFT(0x00099000) /* 0.002334595 */, - PRESHIFT(0x000b0000) /* 0.002685547 */, - PRESHIFT(0x00010000) /* 0.000244141 */, - - -PRESHIFT(0x00001000) /* -0.000015259 */, - -PRESHIFT(0x00031000) /* -0.000747681 */, - PRESHIFT(0x000e4000) /* 0.003479004 */, - -PRESHIFT(0x00350000) /* -0.012939453 */, - PRESHIFT(0x0066c000) /* 0.025085449 */, - -PRESHIFT(0x01c67000) /* -0.110946655 */, - PRESHIFT(0x007f5000) /* 0.031082153 */, - -PRESHIFT(0x0bd06000) /* -0.738372803 */, - PRESHIFT(0x11ec7000) /* 1.120223999 */, - PRESHIFT(0x06772000) /* 0.404083252 */, - PRESHIFT(0x023b3000) /* 0.139450073 */, - PRESHIFT(0x00bbc000) /* 0.045837402 */, - PRESHIFT(0x00809000) /* 0.031387329 */, - PRESHIFT(0x00099000) /* 0.002334595 */, - PRESHIFT(0x000b0000) /* 0.002685547 */, - PRESHIFT(0x00010000) /* 0.000244141 */ }, - - { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 7 */ - -PRESHIFT(0x00035000) /* -0.000808716 */, - PRESHIFT(0x000e3000) /* 0.003463745 */, - -PRESHIFT(0x00397000) /* -0.014022827 */, - PRESHIFT(0x005ff000) /* 0.023422241 */, - -PRESHIFT(0x01dad000) /* -0.115921021 */, - PRESHIFT(0x0043a000) /* 0.016510010 */, - -PRESHIFT(0x0c3d9000) /* -0.765029907 */, - PRESHIFT(0x11c83000) /* 1.111373901 */, - PRESHIFT(0x06076000) /* 0.376800537 */, - PRESHIFT(0x024ad000) /* 0.143264771 */, - PRESHIFT(0x00a67000) /* 0.040634155 */, - PRESHIFT(0x007f0000) /* 0.031005859 */, - PRESHIFT(0x0006f000) /* 0.001693726 */, - PRESHIFT(0x000a9000) /* 0.002578735 */, - PRESHIFT(0x0000e000) /* 0.000213623 */, - - -PRESHIFT(0x00002000) /* -0.000030518 */, - -PRESHIFT(0x00035000) /* -0.000808716 */, - PRESHIFT(0x000e3000) /* 0.003463745 */, - -PRESHIFT(0x00397000) /* -0.014022827 */, - PRESHIFT(0x005ff000) /* 0.023422241 */, - -PRESHIFT(0x01dad000) /* -0.115921021 */, - PRESHIFT(0x0043a000) /* 0.016510010 */, - -PRESHIFT(0x0c3d9000) /* -0.765029907 */, - PRESHIFT(0x11c83000) /* 1.111373901 */, - PRESHIFT(0x06076000) /* 0.376800537 */, - PRESHIFT(0x024ad000) /* 0.143264771 */, - PRESHIFT(0x00a67000) /* 0.040634155 */, - PRESHIFT(0x007f0000) /* 0.031005859 */, - PRESHIFT(0x0006f000) /* 0.001693726 */, - PRESHIFT(0x000a9000) /* 0.002578735 */, - PRESHIFT(0x0000e000) /* 0.000213623 */ }, - - { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 8 */ - -PRESHIFT(0x0003a000) /* -0.000885010 */, - PRESHIFT(0x000e0000) /* 0.003417969 */, - -PRESHIFT(0x003df000) /* -0.015121460 */, - PRESHIFT(0x00586000) /* 0.021575928 */, - -PRESHIFT(0x01ee6000) /* -0.120697021 */, - PRESHIFT(0x00046000) /* 0.001068115 */, - -PRESHIFT(0x0ca8d000) /* -0.791213989 */, - PRESHIFT(0x119e9000) /* 1.101211548 */, - PRESHIFT(0x05991000) /* 0.349868774 */, - PRESHIFT(0x02578000) /* 0.146362305 */, - PRESHIFT(0x0091a000) /* 0.035552979 */, - PRESHIFT(0x007d1000) /* 0.030532837 */, - PRESHIFT(0x00048000) /* 0.001098633 */, - PRESHIFT(0x000a1000) /* 0.002456665 */, - PRESHIFT(0x0000d000) /* 0.000198364 */, - - -PRESHIFT(0x00002000) /* -0.000030518 */, - -PRESHIFT(0x0003a000) /* -0.000885010 */, - PRESHIFT(0x000e0000) /* 0.003417969 */, - -PRESHIFT(0x003df000) /* -0.015121460 */, - PRESHIFT(0x00586000) /* 0.021575928 */, - -PRESHIFT(0x01ee6000) /* -0.120697021 */, - PRESHIFT(0x00046000) /* 0.001068115 */, - -PRESHIFT(0x0ca8d000) /* -0.791213989 */, - PRESHIFT(0x119e9000) /* 1.101211548 */, - PRESHIFT(0x05991000) /* 0.349868774 */, - PRESHIFT(0x02578000) /* 0.146362305 */, - PRESHIFT(0x0091a000) /* 0.035552979 */, - PRESHIFT(0x007d1000) /* 0.030532837 */, - PRESHIFT(0x00048000) /* 0.001098633 */, - PRESHIFT(0x000a1000) /* 0.002456665 */, - PRESHIFT(0x0000d000) /* 0.000198364 */ }, - - { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 9 */ - -PRESHIFT(0x0003f000) /* -0.000961304 */, - PRESHIFT(0x000dd000) /* 0.003372192 */, - -PRESHIFT(0x00428000) /* -0.016235352 */, - PRESHIFT(0x00500000) /* 0.019531250 */, - -PRESHIFT(0x02011000) /* -0.125259399 */, - -PRESHIFT(0x003e6000) /* -0.015228271 */, - -PRESHIFT(0x0d11e000) /* -0.816864014 */, - PRESHIFT(0x116fc000) /* 1.089782715 */, - PRESHIFT(0x052c5000) /* 0.323318481 */, - PRESHIFT(0x02616000) /* 0.148773193 */, - PRESHIFT(0x007d6000) /* 0.030609131 */, - PRESHIFT(0x007aa000) /* 0.029937744 */, - PRESHIFT(0x00024000) /* 0.000549316 */, - PRESHIFT(0x0009a000) /* 0.002349854 */, - PRESHIFT(0x0000b000) /* 0.000167847 */, - - -PRESHIFT(0x00002000) /* -0.000030518 */, - -PRESHIFT(0x0003f000) /* -0.000961304 */, - PRESHIFT(0x000dd000) /* 0.003372192 */, - -PRESHIFT(0x00428000) /* -0.016235352 */, - PRESHIFT(0x00500000) /* 0.019531250 */, - -PRESHIFT(0x02011000) /* -0.125259399 */, - -PRESHIFT(0x003e6000) /* -0.015228271 */, - -PRESHIFT(0x0d11e000) /* -0.816864014 */, - PRESHIFT(0x116fc000) /* 1.089782715 */, - PRESHIFT(0x052c5000) /* 0.323318481 */, - PRESHIFT(0x02616000) /* 0.148773193 */, - PRESHIFT(0x007d6000) /* 0.030609131 */, - PRESHIFT(0x007aa000) /* 0.029937744 */, - PRESHIFT(0x00024000) /* 0.000549316 */, - PRESHIFT(0x0009a000) /* 0.002349854 */, - PRESHIFT(0x0000b000) /* 0.000167847 */ }, - - { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 10 */ - -PRESHIFT(0x00044000) /* -0.001037598 */, - PRESHIFT(0x000d7000) /* 0.003280640 */, - -PRESHIFT(0x00471000) /* -0.017349243 */, - PRESHIFT(0x0046b000) /* 0.017257690 */, - -PRESHIFT(0x0212b000) /* -0.129562378 */, - -PRESHIFT(0x0084a000) /* -0.032379150 */, - -PRESHIFT(0x0d78a000) /* -0.841949463 */, - PRESHIFT(0x113be000) /* 1.077117920 */, - PRESHIFT(0x04c16000) /* 0.297210693 */, - PRESHIFT(0x02687000) /* 0.150497437 */, - PRESHIFT(0x0069c000) /* 0.025817871 */, - PRESHIFT(0x0077f000) /* 0.029281616 */, - PRESHIFT(0x00002000) /* 0.000030518 */, - PRESHIFT(0x00093000) /* 0.002243042 */, - PRESHIFT(0x0000a000) /* 0.000152588 */, - - -PRESHIFT(0x00002000) /* -0.000030518 */, - -PRESHIFT(0x00044000) /* -0.001037598 */, - PRESHIFT(0x000d7000) /* 0.003280640 */, - -PRESHIFT(0x00471000) /* -0.017349243 */, - PRESHIFT(0x0046b000) /* 0.017257690 */, - -PRESHIFT(0x0212b000) /* -0.129562378 */, - -PRESHIFT(0x0084a000) /* -0.032379150 */, - -PRESHIFT(0x0d78a000) /* -0.841949463 */, - PRESHIFT(0x113be000) /* 1.077117920 */, - PRESHIFT(0x04c16000) /* 0.297210693 */, - PRESHIFT(0x02687000) /* 0.150497437 */, - PRESHIFT(0x0069c000) /* 0.025817871 */, - PRESHIFT(0x0077f000) /* 0.029281616 */, - PRESHIFT(0x00002000) /* 0.000030518 */, - PRESHIFT(0x00093000) /* 0.002243042 */, - PRESHIFT(0x0000a000) /* 0.000152588 */ }, - - { -PRESHIFT(0x00003000) /* -0.000045776 */, /* 11 */ - -PRESHIFT(0x00049000) /* -0.001113892 */, - PRESHIFT(0x000d0000) /* 0.003173828 */, - -PRESHIFT(0x004ba000) /* -0.018463135 */, - PRESHIFT(0x003ca000) /* 0.014801025 */, - -PRESHIFT(0x02233000) /* -0.133590698 */, - -PRESHIFT(0x00ce4000) /* -0.050354004 */, - -PRESHIFT(0x0ddca000) /* -0.866363525 */, - PRESHIFT(0x1102f000) /* 1.063217163 */, - PRESHIFT(0x04587000) /* 0.271591187 */, - PRESHIFT(0x026cf000) /* 0.151596069 */, - PRESHIFT(0x0056c000) /* 0.021179199 */, - PRESHIFT(0x0074e000) /* 0.028533936 */, - -PRESHIFT(0x0001d000) /* -0.000442505 */, - PRESHIFT(0x0008b000) /* 0.002120972 */, - PRESHIFT(0x00009000) /* 0.000137329 */, - - -PRESHIFT(0x00003000) /* -0.000045776 */, - -PRESHIFT(0x00049000) /* -0.001113892 */, - PRESHIFT(0x000d0000) /* 0.003173828 */, - -PRESHIFT(0x004ba000) /* -0.018463135 */, - PRESHIFT(0x003ca000) /* 0.014801025 */, - -PRESHIFT(0x02233000) /* -0.133590698 */, - -PRESHIFT(0x00ce4000) /* -0.050354004 */, - -PRESHIFT(0x0ddca000) /* -0.866363525 */, - PRESHIFT(0x1102f000) /* 1.063217163 */, - PRESHIFT(0x04587000) /* 0.271591187 */, - PRESHIFT(0x026cf000) /* 0.151596069 */, - PRESHIFT(0x0056c000) /* 0.021179199 */, - PRESHIFT(0x0074e000) /* 0.028533936 */, - -PRESHIFT(0x0001d000) /* -0.000442505 */, - PRESHIFT(0x0008b000) /* 0.002120972 */, - PRESHIFT(0x00009000) /* 0.000137329 */ }, - - { -PRESHIFT(0x00003000) /* -0.000045776 */, /* 12 */ - -PRESHIFT(0x0004f000) /* -0.001205444 */, - PRESHIFT(0x000c8000) /* 0.003051758 */, - -PRESHIFT(0x00503000) /* -0.019577026 */, - PRESHIFT(0x0031a000) /* 0.012115479 */, - -PRESHIFT(0x02326000) /* -0.137298584 */, - -PRESHIFT(0x011b5000) /* -0.069168091 */, - -PRESHIFT(0x0e3dd000) /* -0.890090942 */, - PRESHIFT(0x10c54000) /* 1.048156738 */, - PRESHIFT(0x03f1b000) /* 0.246505737 */, - PRESHIFT(0x026ee000) /* 0.152069092 */, - PRESHIFT(0x00447000) /* 0.016708374 */, - PRESHIFT(0x00719000) /* 0.027725220 */, - -PRESHIFT(0x00039000) /* -0.000869751 */, - PRESHIFT(0x00084000) /* 0.002014160 */, - PRESHIFT(0x00008000) /* 0.000122070 */, - - -PRESHIFT(0x00003000) /* -0.000045776 */, - -PRESHIFT(0x0004f000) /* -0.001205444 */, - PRESHIFT(0x000c8000) /* 0.003051758 */, - -PRESHIFT(0x00503000) /* -0.019577026 */, - PRESHIFT(0x0031a000) /* 0.012115479 */, - -PRESHIFT(0x02326000) /* -0.137298584 */, - -PRESHIFT(0x011b5000) /* -0.069168091 */, - -PRESHIFT(0x0e3dd000) /* -0.890090942 */, - PRESHIFT(0x10c54000) /* 1.048156738 */, - PRESHIFT(0x03f1b000) /* 0.246505737 */, - PRESHIFT(0x026ee000) /* 0.152069092 */, - PRESHIFT(0x00447000) /* 0.016708374 */, - PRESHIFT(0x00719000) /* 0.027725220 */, - -PRESHIFT(0x00039000) /* -0.000869751 */, - PRESHIFT(0x00084000) /* 0.002014160 */, - PRESHIFT(0x00008000) /* 0.000122070 */ }, - - { -PRESHIFT(0x00004000) /* -0.000061035 */, /* 13 */ - -PRESHIFT(0x00055000) /* -0.001296997 */, - PRESHIFT(0x000bd000) /* 0.002883911 */, - -PRESHIFT(0x0054c000) /* -0.020690918 */, - PRESHIFT(0x0025d000) /* 0.009231567 */, - -PRESHIFT(0x02403000) /* -0.140670776 */, - -PRESHIFT(0x016ba000) /* -0.088775635 */, - -PRESHIFT(0x0e9be000) /* -0.913055420 */, - PRESHIFT(0x1082d000) /* 1.031936646 */, - PRESHIFT(0x038d4000) /* 0.221984863 */, - PRESHIFT(0x026e7000) /* 0.151962280 */, - PRESHIFT(0x0032e000) /* 0.012420654 */, - PRESHIFT(0x006df000) /* 0.026840210 */, - -PRESHIFT(0x00053000) /* -0.001266479 */, - PRESHIFT(0x0007d000) /* 0.001907349 */, - PRESHIFT(0x00007000) /* 0.000106812 */, - - -PRESHIFT(0x00004000) /* -0.000061035 */, - -PRESHIFT(0x00055000) /* -0.001296997 */, - PRESHIFT(0x000bd000) /* 0.002883911 */, - -PRESHIFT(0x0054c000) /* -0.020690918 */, - PRESHIFT(0x0025d000) /* 0.009231567 */, - -PRESHIFT(0x02403000) /* -0.140670776 */, - -PRESHIFT(0x016ba000) /* -0.088775635 */, - -PRESHIFT(0x0e9be000) /* -0.913055420 */, - PRESHIFT(0x1082d000) /* 1.031936646 */, - PRESHIFT(0x038d4000) /* 0.221984863 */, - PRESHIFT(0x026e7000) /* 0.151962280 */, - PRESHIFT(0x0032e000) /* 0.012420654 */, - PRESHIFT(0x006df000) /* 0.026840210 */, - -PRESHIFT(0x00053000) /* -0.001266479 */, - PRESHIFT(0x0007d000) /* 0.001907349 */, - PRESHIFT(0x00007000) /* 0.000106812 */ }, - - { -PRESHIFT(0x00004000) /* -0.000061035 */, /* 14 */ - -PRESHIFT(0x0005b000) /* -0.001388550 */, - PRESHIFT(0x000b1000) /* 0.002700806 */, - -PRESHIFT(0x00594000) /* -0.021789551 */, - PRESHIFT(0x00192000) /* 0.006134033 */, - -PRESHIFT(0x024c8000) /* -0.143676758 */, - -PRESHIFT(0x01bf2000) /* -0.109161377 */, - -PRESHIFT(0x0ef69000) /* -0.935195923 */, - PRESHIFT(0x103be000) /* 1.014617920 */, - PRESHIFT(0x032b4000) /* 0.198059082 */, - PRESHIFT(0x026bc000) /* 0.151306152 */, - PRESHIFT(0x00221000) /* 0.008316040 */, - PRESHIFT(0x006a2000) /* 0.025909424 */, - -PRESHIFT(0x0006a000) /* -0.001617432 */, - PRESHIFT(0x00075000) /* 0.001785278 */, - PRESHIFT(0x00007000) /* 0.000106812 */, - - -PRESHIFT(0x00004000) /* -0.000061035 */, - -PRESHIFT(0x0005b000) /* -0.001388550 */, - PRESHIFT(0x000b1000) /* 0.002700806 */, - -PRESHIFT(0x00594000) /* -0.021789551 */, - PRESHIFT(0x00192000) /* 0.006134033 */, - -PRESHIFT(0x024c8000) /* -0.143676758 */, - -PRESHIFT(0x01bf2000) /* -0.109161377 */, - -PRESHIFT(0x0ef69000) /* -0.935195923 */, - PRESHIFT(0x103be000) /* 1.014617920 */, - PRESHIFT(0x032b4000) /* 0.198059082 */, - PRESHIFT(0x026bc000) /* 0.151306152 */, - PRESHIFT(0x00221000) /* 0.008316040 */, - PRESHIFT(0x006a2000) /* 0.025909424 */, - -PRESHIFT(0x0006a000) /* -0.001617432 */, - PRESHIFT(0x00075000) /* 0.001785278 */, - PRESHIFT(0x00007000) /* 0.000106812 */ }, - - { -PRESHIFT(0x00005000) /* -0.000076294 */, /* 15 */ - -PRESHIFT(0x00061000) /* -0.001480103 */, - PRESHIFT(0x000a3000) /* 0.002487183 */, - -PRESHIFT(0x005da000) /* -0.022857666 */, - PRESHIFT(0x000b9000) /* 0.002822876 */, - -PRESHIFT(0x02571000) /* -0.146255493 */, - -PRESHIFT(0x0215c000) /* -0.130310059 */, - -PRESHIFT(0x0f4dc000) /* -0.956481934 */, - PRESHIFT(0x0ff0a000) /* 0.996246338 */, - PRESHIFT(0x02cbf000) /* 0.174789429 */, - PRESHIFT(0x0266e000) /* 0.150115967 */, - PRESHIFT(0x00120000) /* 0.004394531 */, - PRESHIFT(0x00662000) /* 0.024932861 */, - -PRESHIFT(0x0007f000) /* -0.001937866 */, - PRESHIFT(0x0006f000) /* 0.001693726 */, - PRESHIFT(0x00006000) /* 0.000091553 */, - - -PRESHIFT(0x00005000) /* -0.000076294 */, - -PRESHIFT(0x00061000) /* -0.001480103 */, - PRESHIFT(0x000a3000) /* 0.002487183 */, - -PRESHIFT(0x005da000) /* -0.022857666 */, - PRESHIFT(0x000b9000) /* 0.002822876 */, - -PRESHIFT(0x02571000) /* -0.146255493 */, - -PRESHIFT(0x0215c000) /* -0.130310059 */, - -PRESHIFT(0x0f4dc000) /* -0.956481934 */, - PRESHIFT(0x0ff0a000) /* 0.996246338 */, - PRESHIFT(0x02cbf000) /* 0.174789429 */, - PRESHIFT(0x0266e000) /* 0.150115967 */, - PRESHIFT(0x00120000) /* 0.004394531 */, - PRESHIFT(0x00662000) /* 0.024932861 */, - -PRESHIFT(0x0007f000) /* -0.001937866 */, - PRESHIFT(0x0006f000) /* 0.001693726 */, - PRESHIFT(0x00006000) /* 0.000091553 */ }, - - { -PRESHIFT(0x00005000) /* -0.000076294 */, /* 16 */ - -PRESHIFT(0x00068000) /* -0.001586914 */, - PRESHIFT(0x00092000) /* 0.002227783 */, - -PRESHIFT(0x0061f000) /* -0.023910522 */, - -PRESHIFT(0x0002d000) /* -0.000686646 */, - -PRESHIFT(0x025ff000) /* -0.148422241 */, - -PRESHIFT(0x026f7000) /* -0.152206421 */, - -PRESHIFT(0x0fa13000) /* -0.976852417 */, - PRESHIFT(0x0fa13000) /* 0.976852417 */, - PRESHIFT(0x026f7000) /* 0.152206421 */, - PRESHIFT(0x025ff000) /* 0.148422241 */, - PRESHIFT(0x0002d000) /* 0.000686646 */, - PRESHIFT(0x0061f000) /* 0.023910522 */, - -PRESHIFT(0x00092000) /* -0.002227783 */, - PRESHIFT(0x00068000) /* 0.001586914 */, - PRESHIFT(0x00005000) /* 0.000076294 */, - - -PRESHIFT(0x00005000) /* -0.000076294 */, - -PRESHIFT(0x00068000) /* -0.001586914 */, - PRESHIFT(0x00092000) /* 0.002227783 */, - -PRESHIFT(0x0061f000) /* -0.023910522 */, - -PRESHIFT(0x0002d000) /* -0.000686646 */, - -PRESHIFT(0x025ff000) /* -0.148422241 */, - -PRESHIFT(0x026f7000) /* -0.152206421 */, - -PRESHIFT(0x0fa13000) /* -0.976852417 */, - PRESHIFT(0x0fa13000) /* 0.976852417 */, - PRESHIFT(0x026f7000) /* 0.152206421 */, - PRESHIFT(0x025ff000) /* 0.148422241 */, - PRESHIFT(0x0002d000) /* 0.000686646 */, - PRESHIFT(0x0061f000) /* 0.023910522 */, - -PRESHIFT(0x00092000) /* -0.002227783 */, - PRESHIFT(0x00068000) /* 0.001586914 */, - PRESHIFT(0x00005000) /* 0.000076294 */ } diff --git a/libmad/src/README b/libmad/src/README deleted file mode 100644 index b3f15ea..0000000 --- a/libmad/src/README +++ /dev/null @@ -1,241 +0,0 @@ - - libmad - MPEG audio decoder library - Copyright (C) 2000-2004 Underbit Technologies, Inc. - - $Id: README,v 1.4 2004/01/23 09:41:32 rob Exp $ - -=============================================================================== - -INTRODUCTION - - MAD (libmad) is a high-quality MPEG audio decoder. It currently supports - MPEG-1 and the MPEG-2 extension to Lower Sampling Frequencies, as well as - the so-called MPEG 2.5 format. All three audio layers (Layer I, Layer II, - and Layer III a.k.a. MP3) are fully implemented. - - MAD does not yet support MPEG-2 multichannel audio (although it should be - backward compatible with such streams) nor does it currently support AAC. - - MAD has the following special features: - - - 24-bit PCM output - - 100% fixed-point (integer) computation - - completely new implementation based on the ISO/IEC standards - - distributed under the terms of the GNU General Public License (GPL) - - Because MAD provides full 24-bit PCM output, applications using MAD are - able to produce high quality audio. Even when the output device supports - only 16-bit PCM, applications can use the extra resolution to increase the - audible dynamic range through the use of dithering or noise shaping. - - Because MAD uses integer computation rather than floating point, it is - well suited for architectures without a floating point unit. All - calculations are performed with a 32-bit fixed-point integer - representation. - - Because MAD is a new implementation of the ISO/IEC standards, it is - unencumbered by the errors of other implementations. MAD is NOT a - derivation of the ISO reference source or any other code. Considerable - effort has been expended to ensure a correct implementation, even in cases - where the standards are ambiguous or misleading. - - Because MAD is distributed under the terms of the GPL, its redistribution - is not generally restricted, so long as the terms of the GPL are followed. - This means MAD can be incorporated into other software as long as that - software is also distributed under the GPL. (Should this be undesirable, - alternate arrangements may be possible by contacting Underbit.) - -=============================================================================== - -ABOUT THE CODE - - The code is optimized and performs very well, although specific - improvements can still be made. The output from the decoder library - consists of 32-bit signed linear fixed-point values that can be easily - scaled for any size PCM output, up to 24 bits per sample. - - The API for libmad can be found in the `mad.h' header file. Note that this - file is automatically generated, and will not exist until after you have - built the library. - - There are two APIs available, one high-level, and the other low-level. - With the low-level API, each step of the decoding process must be handled - explicitly, offering the greatest amount of control. With the high-level - API, after callbacks are configured, a single routine will decode an - entire bitstream. - - The high-level API may either be used synchronously or asynchronously. If - used asynchronously, decoding will occur in a separate process. - Communication is possible with the decoding process by passing control - messages. - - The file `minimad.c' contains an example usage of the libmad API that - shows only the bare minimum required to implement a useful decoder. It - expects a regular file to be redirected to standard input, and it sends - decoded 16-bit signed little-endian PCM samples to standard output. If a - decoding error occurs, it is reported to standard error and decoding - continues. Note that the scale() routine in this code is only provided as - an example; it rounds MAD's high-resolution samples down to 16 bits, but - does not perform any dithering or noise shaping. It is therefore not - recommended to use this routine as-is in your own code if sound quality is - important. - -Integer Performance - - To get the best possible performance, it is recommended that an assembly - version of the fixed-point multiply and related routines be selected. - Several such assembly routines have been written for various CPUs. - - If an assembly version is not available, a fast approximation version will - be used. This will result in reduced accuracy of the decoder. - - Alternatively, if 64-bit integers are supported as a datatype by the - compiler, another version can be used that is much more accurate. - However, using an assembly version is generally much faster and just as - accurate. - - More information can be gathered from the `fixed.h' header file. - - MAD's CPU-intensive subband synthesis routine can be further optimized at - the expense of a slight loss in output accuracy due to a modified method - for fixed-point multiplication with a small windowing constant. While this - is helpful for performance and the output accuracy loss is generally - undetectable, it is disabled by default and must be explicitly enabled. - - Under some architectures, other special optimizations may also be - available. - -Audio Quality - - The output from MAD has been found to satisfy the ISO/IEC 11172-4 - computational accuracy requirements for compliance. In most - configurations, MAD is a Full Layer III ISO/IEC 11172-3 audio decoder as - defined by the standard. - - When the approximation version of the fixed-point multiply is used, MAD is - a limited accuracy ISO/IEC 11172-3 audio decoder as defined by the - standard. - - MAD can alternatively be configured to produce output with less or more - accuracy than the default, as a tradeoff with performance. - - MAD produces output samples with a precision greater than 24 bits. Because - most output formats use fewer bits, typically 16, it is recommended that a - dithering algorithm be used (rather than rounding or truncating) to obtain - the highest quality audio. However, dithering may unfavorably affect an - analytic examination of the output (such as compliance testing); you may - therefore wish to use rounding in this case instead. - -Portability Issues - - GCC is preferred to compile the code, but other compilers may also work. - The assembly code in `fixed.h' depends on the inline assembly features of - your compiler. If you're not using GCC or MSVC++, you can either write - your own assembly macros or use the default (low quality output) version. - - The union initialization of `huffman.c' may not be portable to all - platforms when GCC is not used. - - The code should not be sensitive to word sizes or byte ordering, however - it does assume A % B has the same sign as A. - -=============================================================================== - -BUILDING AND INSTALLING - -Windows Platforms - - MAD can be built under Windows using either MSVC++ or Cygwin. A MSVC++ - project file can be found under the `msvc++' subdirectory. - - To build libmad using Cygwin, you will first need to install the Cygwin - tools: - - http://www.cygwin.com/ - - You may then proceed with the following POSIX instructions within the - Cygwin shell. - - Note that by default Cygwin will build a library that depends on the - Cygwin DLL. You can use MinGW to build a library that does not depend on - the Cygwin DLL. To do so, give the option --host=mingw32 to `configure'. - -POSIX Platforms (including Cygwin) - - The code is distributed with a `configure' script that will generate for - you a `Makefile' and a `config.h' for your platform. See the file - `INSTALL' for generic instructions. - - The specific options you may want to give `configure' are: - - --enable-speed optimize for speed over accuracy - - --enable-accuracy optimize for accuracy over speed - - --disable-debugging do not compile with debugging support, and - use more optimizations - - --disable-shared do not build a shared library - - Note that you need not specify one of --enable-speed or --enable-accuracy; - in its default configuration, MAD is optimized for both. You should only - use one of these options if you wish to compromise speed or accuracy for - the other. - - By default the package will build a shared library if possible for your - platform. If you want only a static library, use --disable-shared. - - It is not normally necessary to use the following options, but you may - fine-tune the configuration with them if desired: - - --enable-fpm=ARCH use the ARCH-specific version of the - fixed-point math assembly routines - (current options are: intel, arm, mips, - sparc, ppc; also allowed are: 64bit, approx) - - --enable-sso use the subband synthesis optimization, - with reduced accuracy - - --disable-aso do not use certain architecture-specific - optimizations - - By default an appropriate fixed-point assembly routine will be selected - for the configured host type, if it can be determined. Thus if you are - cross-compiling for another architecture, you should be sure either to - give `configure' a host type argument (--host) or to use an explicit - --enable-fpm option. - - If an appropriate assembly routine cannot be determined, the default - approximation version will be used. In this case, use of an alternate - --enable-fpm is highly recommended. - -Experimenting and Developing - - Further options for `configure' that may be useful to developers and - experimenters are: - - --enable-debugging enable diagnostic debugging support and - debugging symbols - - --enable-profiling generate `gprof' profiling code - - --enable-experimental enable code using the EXPERIMENTAL - preprocessor define - -=============================================================================== - -COPYRIGHT - - Please read the `COPYRIGHT' file for copyright and warranty information. - Also, the file `COPYING' contains the full text of the GNU GPL. - - Send inquiries, comments, bug reports, suggestions, patches, etc. to: - - Underbit Technologies, Inc. - - See also the MAD home page on the Web: - - http://www.underbit.com/products/mad/ - -=============================================================================== - diff --git a/libmad/src/bit.c b/libmad/src/bit.c deleted file mode 100644 index c2bfb24..0000000 --- a/libmad/src/bit.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: bit.c,v 1.12 2004/01/23 09:41:32 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# ifdef HAVE_LIMITS_H -# include -# else -# define CHAR_BIT 8 -# endif - -# include "bit.h" - -/* - * This is the lookup table for computing the CRC-check word. - * As described in section 2.4.3.1 and depicted in Figure A.9 - * of ISO/IEC 11172-3, the generator polynomial is: - * - * G(X) = X^16 + X^15 + X^2 + 1 - */ -static -unsigned short const crc_table[256] = { - 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, - 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, - 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, - 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, - 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, - 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, - 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, - 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, - - 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, - 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, - 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, - 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, - 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, - 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, - 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, - 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, - - 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, - 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, - 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, - 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, - 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, - 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, - 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, - 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, - - 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, - 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, - 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, - 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, - 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, - 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, - 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, - 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 -}; - -# define CRC_POLY 0x8005 - -/* - * NAME: bit->init() - * DESCRIPTION: initialize bit pointer struct - */ -void mad_bit_init(struct mad_bitptr *bitptr, unsigned char const *byte) -{ - bitptr->byte = byte; - bitptr->cache = 0; - bitptr->left = CHAR_BIT; -} - -/* - * NAME: bit->length() - * DESCRIPTION: return number of bits between start and end points - */ -unsigned int mad_bit_length(struct mad_bitptr const *begin, - struct mad_bitptr const *end) -{ - return begin->left + - CHAR_BIT * (end->byte - (begin->byte + 1)) + (CHAR_BIT - end->left); -} - -/* - * NAME: bit->nextbyte() - * DESCRIPTION: return pointer to next unprocessed byte - */ -unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *bitptr) -{ - return bitptr->left == CHAR_BIT ? bitptr->byte : bitptr->byte + 1; -} - -/* - * NAME: bit->skip() - * DESCRIPTION: advance bit pointer - */ -void mad_bit_skip(struct mad_bitptr *bitptr, unsigned int len) -{ - bitptr->byte += len / CHAR_BIT; - bitptr->left -= len % CHAR_BIT; - - if (bitptr->left > CHAR_BIT) { - bitptr->byte++; - bitptr->left += CHAR_BIT; - } - - if (bitptr->left < CHAR_BIT) - bitptr->cache = *bitptr->byte; -} - -/* - * NAME: bit->read() - * DESCRIPTION: read an arbitrary number of bits and return their UIMSBF value - */ -unsigned long mad_bit_read(struct mad_bitptr *bitptr, unsigned int len) -{ - register unsigned long value; - - if (bitptr->left == CHAR_BIT) - bitptr->cache = *bitptr->byte; - - if (len < bitptr->left) { - value = (bitptr->cache & ((1 << bitptr->left) - 1)) >> - (bitptr->left - len); - bitptr->left -= len; - - return value; - } - - /* remaining bits in current byte */ - - value = bitptr->cache & ((1 << bitptr->left) - 1); - len -= bitptr->left; - - bitptr->byte++; - bitptr->left = CHAR_BIT; - - /* more bytes */ - - while (len >= CHAR_BIT) { - value = (value << CHAR_BIT) | *bitptr->byte++; - len -= CHAR_BIT; - } - - if (len > 0) { - bitptr->cache = *bitptr->byte; - - value = (value << len) | (bitptr->cache >> (CHAR_BIT - len)); - bitptr->left -= len; - } - - return value; -} - -# if 0 -/* - * NAME: bit->write() - * DESCRIPTION: write an arbitrary number of bits - */ -void mad_bit_write(struct mad_bitptr *bitptr, unsigned int len, - unsigned long value) -{ - unsigned char *ptr; - - ptr = (unsigned char *) bitptr->byte; - - /* ... */ -} -# endif - -/* - * NAME: bit->crc() - * DESCRIPTION: compute CRC-check word - */ -unsigned short mad_bit_crc(struct mad_bitptr bitptr, unsigned int len, - unsigned short init) -{ - register unsigned int crc; - - for (crc = init; len >= 32; len -= 32) { - register unsigned long data; - - data = mad_bit_read(&bitptr, 32); - - crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 24)) & 0xff]; - crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 16)) & 0xff]; - crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 8)) & 0xff]; - crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 0)) & 0xff]; - } - - switch (len / 8) { - case 3: crc = (crc << 8) ^ - crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff]; - case 2: crc = (crc << 8) ^ - crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff]; - case 1: crc = (crc << 8) ^ - crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff]; - - len %= 8; - - case 0: break; - } - - while (len--) { - register unsigned int msb; - - msb = mad_bit_read(&bitptr, 1) ^ (crc >> 15); - - crc <<= 1; - if (msb & 1) - crc ^= CRC_POLY; - } - - return crc & 0xffff; -} diff --git a/libmad/src/bit.h b/libmad/src/bit.h deleted file mode 100644 index 5a51570..0000000 --- a/libmad/src/bit.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: bit.h,v 1.12 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_BIT_H -# define LIBMAD_BIT_H - -struct mad_bitptr { - unsigned char const *byte; - unsigned short cache; - unsigned short left; -}; - -void mad_bit_init(struct mad_bitptr *, unsigned char const *); - -# define mad_bit_finish(bitptr) /* nothing */ - -unsigned int mad_bit_length(struct mad_bitptr const *, - struct mad_bitptr const *); - -# define mad_bit_bitsleft(bitptr) ((bitptr)->left) -unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *); - -void mad_bit_skip(struct mad_bitptr *, unsigned int); -unsigned long mad_bit_read(struct mad_bitptr *, unsigned int); -void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long); - -unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short); - -# endif diff --git a/libmad/src/decoder.c b/libmad/src/decoder.c deleted file mode 100644 index 6d6df0d..0000000 --- a/libmad/src/decoder.c +++ /dev/null @@ -1,582 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: decoder.c,v 1.22 2004/01/23 09:41:32 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# ifdef HAVE_SYS_TYPES_H -# include -# endif - -# ifdef HAVE_SYS_WAIT_H -# include -# endif - -# ifdef HAVE_UNISTD_H -# include -# endif - -# ifdef HAVE_FCNTL_H -# include -# endif - -# include - -# ifdef HAVE_ERRNO_H -# include -# endif - -# include "stream.h" -# include "frame.h" -# include "synth.h" -# include "decoder.h" - -/* - * NAME: decoder->init() - * DESCRIPTION: initialize a decoder object with callback routines - */ -void mad_decoder_init(struct mad_decoder *decoder, void *data, - enum mad_flow (*input_func)(void *, - struct mad_stream *), - enum mad_flow (*header_func)(void *, - struct mad_header const *), - enum mad_flow (*filter_func)(void *, - struct mad_stream const *, - struct mad_frame *), - enum mad_flow (*output_func)(void *, - struct mad_header const *, - struct mad_pcm *), - enum mad_flow (*error_func)(void *, - struct mad_stream *, - struct mad_frame *), - enum mad_flow (*message_func)(void *, - void *, unsigned int *)) -{ - decoder->mode = -1; - - decoder->options = 0; - - decoder->async.pid = 0; - decoder->async.in = -1; - decoder->async.out = -1; - - decoder->sync = 0; - - decoder->cb_data = data; - - decoder->input_func = input_func; - decoder->header_func = header_func; - decoder->filter_func = filter_func; - decoder->output_func = output_func; - decoder->error_func = error_func; - decoder->message_func = message_func; -} - -int mad_decoder_finish(struct mad_decoder *decoder) -{ -# if defined(USE_ASYNC) - if (decoder->mode == MAD_DECODER_MODE_ASYNC && decoder->async.pid) { - pid_t pid; - int status; - - close(decoder->async.in); - - do - pid = waitpid(decoder->async.pid, &status, 0); - while (pid == -1 && errno == EINTR); - - decoder->mode = -1; - - close(decoder->async.out); - - decoder->async.pid = 0; - decoder->async.in = -1; - decoder->async.out = -1; - - if (pid == -1) - return -1; - - return (!WIFEXITED(status) || WEXITSTATUS(status)) ? -1 : 0; - } -# endif - - return 0; -} - -# if defined(USE_ASYNC) -static -enum mad_flow send_io(int fd, void const *data, size_t len) -{ - char const *ptr = data; - ssize_t count; - - while (len) { - do - count = write(fd, ptr, len); - while (count == -1 && errno == EINTR); - - if (count == -1) - return MAD_FLOW_BREAK; - - len -= count; - ptr += count; - } - - return MAD_FLOW_CONTINUE; -} - -static -enum mad_flow receive_io(int fd, void *buffer, size_t len) -{ - char *ptr = buffer; - ssize_t count; - - while (len) { - do - count = read(fd, ptr, len); - while (count == -1 && errno == EINTR); - - if (count == -1) - return (errno == EAGAIN) ? MAD_FLOW_IGNORE : MAD_FLOW_BREAK; - else if (count == 0) - return MAD_FLOW_STOP; - - len -= count; - ptr += count; - } - - return MAD_FLOW_CONTINUE; -} - -static -enum mad_flow receive_io_blocking(int fd, void *buffer, size_t len) -{ - int flags, blocking; - enum mad_flow result; - - flags = fcntl(fd, F_GETFL); - if (flags == -1) - return MAD_FLOW_BREAK; - - blocking = flags & ~O_NONBLOCK; - - if (blocking != flags && - fcntl(fd, F_SETFL, blocking) == -1) - return MAD_FLOW_BREAK; - - result = receive_io(fd, buffer, len); - - if (flags != blocking && - fcntl(fd, F_SETFL, flags) == -1) - return MAD_FLOW_BREAK; - - return result; -} - -static -enum mad_flow send(int fd, void const *message, unsigned int size) -{ - enum mad_flow result; - - /* send size */ - - result = send_io(fd, &size, sizeof(size)); - - /* send message */ - - if (result == MAD_FLOW_CONTINUE) - result = send_io(fd, message, size); - - return result; -} - -static -enum mad_flow receive(int fd, void **message, unsigned int *size) -{ - enum mad_flow result; - unsigned int actual; - - if (*message == 0) - *size = 0; - - /* receive size */ - - result = receive_io(fd, &actual, sizeof(actual)); - - /* receive message */ - - if (result == MAD_FLOW_CONTINUE) { - if (actual > *size) - actual -= *size; - else { - *size = actual; - actual = 0; - } - - if (*size > 0) { - if (*message == 0) { - *message = malloc(*size); - if (*message == 0) - return MAD_FLOW_BREAK; - } - - result = receive_io_blocking(fd, *message, *size); - } - - /* throw away remainder of message */ - - while (actual && result == MAD_FLOW_CONTINUE) { - char sink[256]; - unsigned int len; - - len = actual > sizeof(sink) ? sizeof(sink) : actual; - - result = receive_io_blocking(fd, sink, len); - - actual -= len; - } - } - - return result; -} - -static -enum mad_flow check_message(struct mad_decoder *decoder) -{ - enum mad_flow result; - void *message = 0; - unsigned int size; - - result = receive(decoder->async.in, &message, &size); - - if (result == MAD_FLOW_CONTINUE) { - if (decoder->message_func == 0) - size = 0; - else { - result = decoder->message_func(decoder->cb_data, message, &size); - - if (result == MAD_FLOW_IGNORE || - result == MAD_FLOW_BREAK) - size = 0; - } - - if (send(decoder->async.out, message, size) != MAD_FLOW_CONTINUE) - result = MAD_FLOW_BREAK; - } - - if (message) - free(message); - - return result; -} -# endif - -static -enum mad_flow error_default(void *data, struct mad_stream *stream, - struct mad_frame *frame) -{ - int *bad_last_frame = data; - - switch (stream->error) { - case MAD_ERROR_BADCRC: - if (*bad_last_frame) - mad_frame_mute(frame); - else - *bad_last_frame = 1; - - return MAD_FLOW_IGNORE; - - default: - return MAD_FLOW_CONTINUE; - } -} - -static -int run_sync(struct mad_decoder *decoder) -{ - enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); - void *error_data; - int bad_last_frame = 0; - struct mad_stream *stream; - struct mad_frame *frame; - struct mad_synth *synth; - int result = 0; - - if (decoder->input_func == 0) - return 0; - - if (decoder->error_func) { - error_func = decoder->error_func; - error_data = decoder->cb_data; - } - else { - error_func = error_default; - error_data = &bad_last_frame; - } - - stream = &decoder->sync->stream; - frame = &decoder->sync->frame; - synth = &decoder->sync->synth; - - mad_stream_init(stream); - mad_frame_init(frame); - mad_synth_init(synth); - - mad_stream_options(stream, decoder->options); - - do { - switch (decoder->input_func(decoder->cb_data, stream)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - continue; - case MAD_FLOW_CONTINUE: - break; - } - - while (1) { -# if defined(USE_ASYNC) - if (decoder->mode == MAD_DECODER_MODE_ASYNC) { - switch (check_message(decoder)) { - case MAD_FLOW_IGNORE: - case MAD_FLOW_CONTINUE: - break; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_STOP: - goto done; - } - } -# endif - - if (decoder->header_func) { - if (mad_header_decode(&frame->header, stream) == -1) { - if (!MAD_RECOVERABLE(stream->error)) - break; - - switch (error_func(error_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - case MAD_FLOW_CONTINUE: - default: - continue; - } - } - - switch (decoder->header_func(decoder->cb_data, &frame->header)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - continue; - case MAD_FLOW_CONTINUE: - break; - } - } - - if (mad_frame_decode(frame, stream) == -1) { - if (!MAD_RECOVERABLE(stream->error)) - break; - - switch (error_func(error_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - break; - case MAD_FLOW_CONTINUE: - default: - continue; - } - } - else - bad_last_frame = 0; - - if (decoder->filter_func) { - switch (decoder->filter_func(decoder->cb_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - continue; - case MAD_FLOW_CONTINUE: - break; - } - } - - mad_synth_frame(synth, frame); - - if (decoder->output_func) { - switch (decoder->output_func(decoder->cb_data, - &frame->header, &synth->pcm)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - case MAD_FLOW_CONTINUE: - break; - } - } - } - } - while (stream->error == MAD_ERROR_BUFLEN); - - fail: - result = -1; - - done: - mad_synth_finish(synth); - mad_frame_finish(frame); - mad_stream_finish(stream); - - return result; -} - -# if defined(USE_ASYNC) -static -int run_async(struct mad_decoder *decoder) -{ - pid_t pid; - int ptoc[2], ctop[2], flags; - - if (pipe(ptoc) == -1) - return -1; - - if (pipe(ctop) == -1) { - close(ptoc[0]); - close(ptoc[1]); - return -1; - } - - flags = fcntl(ptoc[0], F_GETFL); - if (flags == -1 || - fcntl(ptoc[0], F_SETFL, flags | O_NONBLOCK) == -1) { - close(ctop[0]); - close(ctop[1]); - close(ptoc[0]); - close(ptoc[1]); - return -1; - } - - pid = fork(); - if (pid == -1) { - close(ctop[0]); - close(ctop[1]); - close(ptoc[0]); - close(ptoc[1]); - return -1; - } - - decoder->async.pid = pid; - - if (pid) { - /* parent */ - - close(ptoc[0]); - close(ctop[1]); - - decoder->async.in = ctop[0]; - decoder->async.out = ptoc[1]; - - return 0; - } - - /* child */ - - close(ptoc[1]); - close(ctop[0]); - - decoder->async.in = ptoc[0]; - decoder->async.out = ctop[1]; - - _exit(run_sync(decoder)); - - /* not reached */ - return -1; -} -# endif - -/* - * NAME: decoder->run() - * DESCRIPTION: run the decoder thread either synchronously or asynchronously - */ -int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode) -{ - int result; - int (*run)(struct mad_decoder *) = 0; - - switch (decoder->mode = mode) { - case MAD_DECODER_MODE_SYNC: - run = run_sync; - break; - - case MAD_DECODER_MODE_ASYNC: -# if defined(USE_ASYNC) - run = run_async; -# endif - break; - } - - if (run == 0) - return -1; - - decoder->sync = malloc(sizeof(*decoder->sync)); - if (decoder->sync == 0) - return -1; - - result = run(decoder); - - free(decoder->sync); - decoder->sync = 0; - - return result; -} - -/* - * NAME: decoder->message() - * DESCRIPTION: send a message to and receive a reply from the decoder process - */ -int mad_decoder_message(struct mad_decoder *decoder, - void *message, unsigned int *len) -{ -# if defined(USE_ASYNC) - if (decoder->mode != MAD_DECODER_MODE_ASYNC || - send(decoder->async.out, message, *len) != MAD_FLOW_CONTINUE || - receive(decoder->async.in, &message, len) != MAD_FLOW_CONTINUE) - return -1; - - return 0; -# else - return -1; -# endif -} diff --git a/libmad/src/decoder.h b/libmad/src/decoder.h deleted file mode 100644 index f0ad758..0000000 --- a/libmad/src/decoder.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: decoder.h,v 1.17 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_DECODER_H -# define LIBMAD_DECODER_H - -# include "stream.h" -# include "frame.h" -# include "synth.h" - -enum mad_decoder_mode { - MAD_DECODER_MODE_SYNC = 0, - MAD_DECODER_MODE_ASYNC -}; - -enum mad_flow { - MAD_FLOW_CONTINUE = 0x0000, /* continue normally */ - MAD_FLOW_STOP = 0x0010, /* stop decoding normally */ - MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */ - MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */ -}; - -struct mad_decoder { - enum mad_decoder_mode mode; - - int options; - - struct { - long pid; - int in; - int out; - } async; - - struct { - struct mad_stream stream; - struct mad_frame frame; - struct mad_synth synth; - } *sync; - - void *cb_data; - - enum mad_flow (*input_func)(void *, struct mad_stream *); - enum mad_flow (*header_func)(void *, struct mad_header const *); - enum mad_flow (*filter_func)(void *, - struct mad_stream const *, struct mad_frame *); - enum mad_flow (*output_func)(void *, - struct mad_header const *, struct mad_pcm *); - enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); - enum mad_flow (*message_func)(void *, void *, unsigned int *); -}; - -void mad_decoder_init(struct mad_decoder *, void *, - enum mad_flow (*)(void *, struct mad_stream *), - enum mad_flow (*)(void *, struct mad_header const *), - enum mad_flow (*)(void *, - struct mad_stream const *, - struct mad_frame *), - enum mad_flow (*)(void *, - struct mad_header const *, - struct mad_pcm *), - enum mad_flow (*)(void *, - struct mad_stream *, - struct mad_frame *), - enum mad_flow (*)(void *, void *, unsigned int *)); -int mad_decoder_finish(struct mad_decoder *); - -# define mad_decoder_options(decoder, opts) \ - ((void) ((decoder)->options = (opts))) - -int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode); -int mad_decoder_message(struct mad_decoder *, void *, unsigned int *); - -# endif diff --git a/libmad/src/fixed.c b/libmad/src/fixed.c deleted file mode 100644 index 081d3bc..0000000 --- a/libmad/src/fixed.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: fixed.c,v 1.13 2004/01/23 09:41:32 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include "fixed.h" - -# ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4244 4018 4146) -# endif - -/* - * NAME: fixed->abs() - * DESCRIPTION: return absolute value of a fixed-point number - */ -mad_fixed_t mad_f_abs(mad_fixed_t x) -{ - return x < 0 ? -x : x; -} - -/* - * NAME: fixed->div() - * DESCRIPTION: perform division using fixed-point math - */ -mad_fixed_t mad_f_div(mad_fixed_t x, mad_fixed_t y) -{ - mad_fixed_t q, r; - unsigned int bits; - - q = mad_f_abs(x / y); - - if (x < 0) { - x = -x; - y = -y; - } - - r = x % y; - - if (y < 0) { - x = -x; - y = -y; - } - - if (q > mad_f_intpart(MAD_F_MAX) && - !(q == -mad_f_intpart(MAD_F_MIN) && r == 0 && (x < 0) != (y < 0))) - return 0; - - for (bits = MAD_F_FRACBITS; bits && r; --bits) { - q <<= 1, r <<= 1; - if (r >= y) - r -= y, ++q; - } - - /* round */ - if (2 * r >= y) - ++q; - - /* fix sign */ - if ((x < 0) != (y < 0)) - q = -q; - - return q << bits; -} - -# ifdef _MSC_VER -# pragma warning(pop) -# endif diff --git a/libmad/src/fixed.h b/libmad/src/fixed.h deleted file mode 100644 index 4b58abf..0000000 --- a/libmad/src/fixed.h +++ /dev/null @@ -1,499 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: fixed.h,v 1.38 2004/02/17 02:02:03 rob Exp $ - */ - -# ifndef LIBMAD_FIXED_H -# define LIBMAD_FIXED_H - -# if SIZEOF_INT >= 4 -typedef signed int mad_fixed_t; - -typedef signed int mad_fixed64hi_t; -typedef unsigned int mad_fixed64lo_t; -# else -typedef signed long mad_fixed_t; - -typedef signed long mad_fixed64hi_t; -typedef unsigned long mad_fixed64lo_t; -# endif - -# if defined(_MSC_VER) -# define mad_fixed64_t signed __int64 -# elif 1 || defined(__GNUC__) -# define mad_fixed64_t signed long long -# endif - -# if defined(FPM_FLOAT) -typedef double mad_sample_t; -# else -typedef mad_fixed_t mad_sample_t; -# endif - -/* - * Fixed-point format: 0xABBBBBBB - * A == whole part (sign + 3 bits) - * B == fractional part (28 bits) - * - * Values are signed two's complement, so the effective range is: - * 0x80000000 to 0x7fffffff - * -8.0 to +7.9999999962747097015380859375 - * - * The smallest representable value is: - * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) - * - * 28 bits of fractional accuracy represent about - * 8.6 digits of decimal accuracy. - * - * Fixed-point numbers can be added or subtracted as normal - * integers, but multiplication requires shifting the 64-bit result - * from 56 fractional bits back to 28 (and rounding.) - * - * Changing the definition of MAD_F_FRACBITS is only partially - * supported, and must be done with care. - */ - -# define MAD_F_FRACBITS 28 - -# if MAD_F_FRACBITS == 28 -# define MAD_F(x) ((mad_fixed_t) (x##L)) -# else -# if MAD_F_FRACBITS < 28 -# warning "MAD_F_FRACBITS < 28" -# define MAD_F(x) ((mad_fixed_t) \ - (((x##L) + \ - (1L << (28 - MAD_F_FRACBITS - 1))) >> \ - (28 - MAD_F_FRACBITS))) -# elif MAD_F_FRACBITS > 28 -# error "MAD_F_FRACBITS > 28 not currently supported" -# define MAD_F(x) ((mad_fixed_t) \ - ((x##L) << (MAD_F_FRACBITS - 28))) -# endif -# endif - -# define MAD_F_MIN ((mad_fixed_t) -0x80000000L) -# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) - -# define MAD_F_ONE MAD_F(0x10000000) - -# define mad_f_tofixed(x) ((mad_fixed_t) \ - ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) -# define mad_f_todouble(x) ((double) \ - ((x) / (double) (1L << MAD_F_FRACBITS))) - -# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) -# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) - /* (x should be positive) */ - -# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) - -# define mad_f_add(x, y) ((x) + (y)) -# define mad_f_sub(x, y) ((x) - (y)) - -# if defined(FPM_FLOAT) -# error "FPM_FLOAT not yet supported" - -# undef MAD_F -# define MAD_F(x) mad_f_todouble(x) - -# define mad_f_mul(x, y) ((x) * (y)) -# define mad_f_scale64 - -# undef ASO_ZEROCHECK - -# elif defined(FPM_64BIT) - -/* - * This version should be the most accurate if 64-bit types are supported by - * the compiler, although it may not be the most efficient. - */ -# if defined(OPT_ACCURACY) -# define mad_f_mul(x, y) \ - ((mad_fixed_t) \ - ((((mad_fixed64_t) (x) * (y)) + \ - (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) -# else -# define mad_f_mul(x, y) \ - ((mad_fixed_t) (((mad_fixed64_t) (x) * (y)) >> MAD_F_SCALEBITS)) -# endif - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- Intel --------------------------------------------------------------- */ - -# elif defined(FPM_INTEL) - -# if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4035) /* no return value */ -static __forceinline -mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) -{ - enum { - fracbits = MAD_F_FRACBITS - }; - - __asm { - mov eax, x - imul y - shrd eax, edx, fracbits - } - - /* implicit return of eax */ -} -# pragma warning(pop) - -# define mad_f_mul mad_f_mul_inline -# define mad_f_scale64 -# else -/* - * This Intel version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("imull %3" \ - : "=a" (lo), "=d" (hi) \ - : "%a" (x), "rm" (y) \ - : "cc") - -# if defined(OPT_ACCURACY) -/* - * This gives best accuracy but is not very fast. - */ -# define MAD_F_MLA(hi, lo, x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - asm ("addl %2,%0\n\t" \ - "adcl %3,%1" \ - : "=rm" (lo), "=rm" (hi) \ - : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ - : "cc"); \ - }) -# endif /* OPT_ACCURACY */ - -# if defined(OPT_ACCURACY) -/* - * Surprisingly, this is faster than SHRD followed by ADC. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed64hi_t __hi_; \ - mad_fixed64lo_t __lo_; \ - mad_fixed_t __result; \ - asm ("addl %4,%2\n\t" \ - "adcl %5,%3" \ - : "=rm" (__lo_), "=rm" (__hi_) \ - : "0" (lo), "1" (hi), \ - "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ - : "cc"); \ - asm ("shrdl %3,%2,%1" \ - : "=rm" (__result) \ - : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# elif defined(OPT_INTEL) -/* - * Alternate Intel scaling that may or may not perform better. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("shrl %3,%1\n\t" \ - "shll %4,%2\n\t" \ - "orl %2,%1" \ - : "=rm" (__result) \ - : "0" (lo), "r" (hi), \ - "I" (MAD_F_SCALEBITS), "I" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# else -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("shrdl %3,%2,%1" \ - : "=rm" (__result) \ - : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# endif /* OPT_ACCURACY */ - -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* --- ARM ----------------------------------------------------------------- */ - -# elif defined(FPM_ARM) - -/* - * This ARM V4 version is as accurate as FPM_64BIT but much faster. The - * least significant bit is properly rounded at no CPU cycle cost! - */ -# if 1 -/* - * This is faster than the default implementation via MAD_F_MLX() and - * mad_f_scale64(). - */ -# define mad_f_mul(x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - mad_fixed_t __result; \ - asm ("smull %0, %1, %3, %4\n\t" \ - "movs %0, %0, lsr %5\n\t" \ - "adc %2, %0, %1, lsl %6" \ - : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ - : "%r" (x), "r" (y), \ - "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# endif - -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("smull %0, %1, %2, %3" \ - : "=&r" (lo), "=&r" (hi) \ - : "%r" (x), "r" (y)) - -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("smlal %0, %1, %2, %3" \ - : "+r" (lo), "+r" (hi) \ - : "%r" (x), "r" (y)) - -# define MAD_F_MLN(hi, lo) \ - asm ("rsbs %0, %2, #0\n\t" \ - "rsc %1, %3, #0" \ - : "=r" (lo), "=r" (hi) \ - : "0" (lo), "1" (hi) \ - : "cc") - -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("movs %0, %1, lsr %3\n\t" \ - "adc %0, %0, %2, lsl %4" \ - : "=&r" (__result) \ - : "r" (lo), "r" (hi), \ - "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- MIPS ---------------------------------------------------------------- */ - -# elif defined(FPM_MIPS) - -/* - * This MIPS version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" (x), "r" (y)) - -# if defined(HAVE_MADD_ASM) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" (x), "r" (y)) -# elif defined(HAVE_MADD16_ASM) -/* - * This loses significant accuracy due to the 16-bit integer limit in the - * multiply/accumulate instruction. - */ -# define MAD_F_ML0(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd16 %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) -# endif - -# if defined(OPT_SPEED) -# define mad_f_scale64(hi, lo) \ - ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* --- SPARC --------------------------------------------------------------- */ - -# elif defined(FPM_SPARC) - -/* - * This SPARC V8 version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("smul %2, %3, %0\n\t" \ - "rd %%y, %1" \ - : "=r" (lo), "=r" (hi) \ - : "%r" (x), "rI" (y)) - -/* --- PowerPC ------------------------------------------------------------- */ - -# elif defined(FPM_PPC) - -/* - * This PowerPC version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - do { \ - asm ("mullw %0,%1,%2" \ - : "=r" (lo) \ - : "%r" (x), "r" (y)); \ - asm ("mulhw %0,%1,%2" \ - : "=r" (hi) \ - : "%r" (x), "r" (y)); \ - } \ - while (0) - -# if defined(OPT_ACCURACY) -/* - * This gives best accuracy but is not very fast. - */ -# define MAD_F_MLA(hi, lo, x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - asm ("addc %0,%2,%3\n\t" \ - "adde %1,%4,%5" \ - : "=r" (lo), "=r" (hi) \ - : "%r" (lo), "r" (__lo), \ - "%r" (hi), "r" (__hi) \ - : "xer"); \ - }) -# endif - -# if defined(OPT_ACCURACY) -/* - * This is slower than the truncating version below it. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result, __round; \ - asm ("rotrwi %0,%1,%2" \ - : "=r" (__result) \ - : "r" (lo), "i" (MAD_F_SCALEBITS)); \ - asm ("extrwi %0,%1,1,0" \ - : "=r" (__round) \ - : "r" (__result)); \ - asm ("insrwi %0,%1,%2,0" \ - : "+r" (__result) \ - : "r" (hi), "i" (MAD_F_SCALEBITS)); \ - asm ("add %0,%1,%2" \ - : "=r" (__result) \ - : "%r" (__result), "r" (__round)); \ - __result; \ - }) -# else -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("rotrwi %0,%1,%2" \ - : "=r" (__result) \ - : "r" (lo), "i" (MAD_F_SCALEBITS)); \ - asm ("insrwi %0,%1,%2,0" \ - : "+r" (__result) \ - : "r" (hi), "i" (MAD_F_SCALEBITS)); \ - __result; \ - }) -# endif - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- Default ------------------------------------------------------------- */ - -# elif defined(FPM_DEFAULT) - -/* - * This version is the most portable but it loses significant accuracy. - * Furthermore, accuracy is biased against the second argument, so care - * should be taken when ordering operands. - * - * The scale factors are constant as this is not used with SSO. - * - * Pre-rounding is required to stay within the limits of compliance. - */ -# if defined(OPT_SPEED) -# define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16)) -# else -# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ - (((y) + (1L << 15)) >> 16)) -# endif - -/* ------------------------------------------------------------------------- */ - -# else -# error "no FPM selected" -# endif - -/* default implementations */ - -# if !defined(mad_f_mul) -# define mad_f_mul(x, y) \ - ({ register mad_fixed64hi_t __hi; \ - register mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - mad_f_scale64(__hi, __lo); \ - }) -# endif - -# if !defined(MAD_F_MLA) -# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) -# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) -# define MAD_F_MLN(hi, lo) ((lo) = -(lo)) -# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) -# endif - -# if !defined(MAD_F_ML0) -# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) -# endif - -# if !defined(MAD_F_MLN) -# define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi)) -# endif - -# if !defined(MAD_F_MLZ) -# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) -# endif - -# if !defined(mad_f_scale64) -# if defined(OPT_ACCURACY) -# define mad_f_scale64(hi, lo) \ - ((((mad_fixed_t) \ - (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ - ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) -# else -# define mad_f_scale64(hi, lo) \ - ((mad_fixed_t) \ - (((hi) << (32 - MAD_F_SCALEBITS)) | \ - ((lo) >> MAD_F_SCALEBITS))) -# endif -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* C routines */ - -mad_fixed_t mad_f_abs(mad_fixed_t); -mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t); - -# endif diff --git a/libmad/src/frame.c b/libmad/src/frame.c deleted file mode 100644 index 37acbfa..0000000 --- a/libmad/src/frame.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: frame.c,v 1.29 2004/02/04 22:59:19 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include - -# include "bit.h" -# include "stream.h" -# include "frame.h" -# include "timer.h" -# include "layer12.h" -# include "layer3.h" - -# ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4244 4018) -# endif - -static -unsigned long const bitrate_table[5][15] = { - /* MPEG-1 */ - { 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, /* Layer I */ - 256000, 288000, 320000, 352000, 384000, 416000, 448000 }, - { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer II */ - 128000, 160000, 192000, 224000, 256000, 320000, 384000 }, - { 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, /* Layer III */ - 112000, 128000, 160000, 192000, 224000, 256000, 320000 }, - - /* MPEG-2 LSF */ - { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer I */ - 128000, 144000, 160000, 176000, 192000, 224000, 256000 }, - { 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, /* Layers */ - 64000, 80000, 96000, 112000, 128000, 144000, 160000 } /* II & III */ -}; - -static -unsigned int const samplerate_table[3] = { 44100, 48000, 32000 }; - -static -int (*const decoder_table[3])(struct mad_stream *, struct mad_frame *) = { - mad_layer_I, - mad_layer_II, - mad_layer_III -}; - -/* - * NAME: header->init() - * DESCRIPTION: initialize header struct - */ -void mad_header_init(struct mad_header *header) -{ - header->layer = 0; - header->mode = 0; - header->mode_extension = 0; - header->emphasis = 0; - - header->bitrate = 0; - header->samplerate = 0; - - header->crc_check = 0; - header->crc_target = 0; - - header->flags = 0; - header->private_bits = 0; - - header->duration = mad_timer_zero; -} - -/* - * NAME: frame->init() - * DESCRIPTION: initialize frame struct - */ -void mad_frame_init(struct mad_frame *frame) -{ - mad_header_init(&frame->header); - - frame->options = 0; - - frame->overlap = 0; - mad_frame_mute(frame); -} - -/* - * NAME: frame->finish() - * DESCRIPTION: deallocate any dynamic memory associated with frame - */ -void mad_frame_finish(struct mad_frame *frame) -{ - mad_header_finish(&frame->header); - - if (frame->overlap) { - free(frame->overlap); - frame->overlap = 0; - } -} - -/* - * NAME: decode_header() - * DESCRIPTION: read header data and following CRC word - */ -static -int decode_header(struct mad_header *header, struct mad_stream *stream) -{ - unsigned int index; - - header->flags = 0; - header->private_bits = 0; - - /* header() */ - - /* syncword */ - mad_bit_skip(&stream->ptr, 11); - - /* MPEG 2.5 indicator (really part of syncword) */ - if (mad_bit_read(&stream->ptr, 1) == 0) - header->flags |= MAD_FLAG_MPEG_2_5_EXT; - - /* ID */ - if (mad_bit_read(&stream->ptr, 1) == 0) - header->flags |= MAD_FLAG_LSF_EXT; - else if (header->flags & MAD_FLAG_MPEG_2_5_EXT) { - stream->error = MAD_ERROR_LOSTSYNC; - return -1; - } - - /* layer */ - header->layer = 4 - mad_bit_read(&stream->ptr, 2); - - if (header->layer == 4) { - stream->error = MAD_ERROR_BADLAYER; - return -1; - } - - /* protection_bit */ - if (mad_bit_read(&stream->ptr, 1) == 0) { - header->flags |= MAD_FLAG_PROTECTION; - header->crc_check = mad_bit_crc(stream->ptr, 16, 0xffff); - } - - /* bitrate_index */ - index = mad_bit_read(&stream->ptr, 4); - - if (index == 15) { - stream->error = MAD_ERROR_BADBITRATE; - return -1; - } - - if (header->flags & MAD_FLAG_LSF_EXT) - header->bitrate = bitrate_table[3 + (header->layer >> 1)][index]; - else - header->bitrate = bitrate_table[header->layer - 1][index]; - - /* sampling_frequency */ - index = mad_bit_read(&stream->ptr, 2); - - if (index == 3) { - stream->error = MAD_ERROR_BADSAMPLERATE; - return -1; - } - - header->samplerate = samplerate_table[index]; - - if (header->flags & MAD_FLAG_LSF_EXT) { - header->samplerate /= 2; - - if (header->flags & MAD_FLAG_MPEG_2_5_EXT) - header->samplerate /= 2; - } - - /* padding_bit */ - if (mad_bit_read(&stream->ptr, 1)) - header->flags |= MAD_FLAG_PADDING; - - /* private_bit */ - if (mad_bit_read(&stream->ptr, 1)) - header->private_bits |= MAD_PRIVATE_HEADER; - - /* mode */ - header->mode = 3 - mad_bit_read(&stream->ptr, 2); - - /* mode_extension */ - header->mode_extension = mad_bit_read(&stream->ptr, 2); - - /* copyright */ - if (mad_bit_read(&stream->ptr, 1)) - header->flags |= MAD_FLAG_COPYRIGHT; - - /* original/copy */ - if (mad_bit_read(&stream->ptr, 1)) - header->flags |= MAD_FLAG_ORIGINAL; - - /* emphasis */ - header->emphasis = mad_bit_read(&stream->ptr, 2); - -# if defined(OPT_STRICT) - /* - * ISO/IEC 11172-3 says this is a reserved emphasis value, but - * streams exist which use it anyway. Since the value is not important - * to the decoder proper, we allow it unless OPT_STRICT is defined. - */ - if (header->emphasis == MAD_EMPHASIS_RESERVED) { - stream->error = MAD_ERROR_BADEMPHASIS; - return -1; - } -# endif - - /* error_check() */ - - /* crc_check */ - if (header->flags & MAD_FLAG_PROTECTION) - header->crc_target = mad_bit_read(&stream->ptr, 16); - - return 0; -} - -/* - * NAME: free_bitrate() - * DESCRIPTION: attempt to discover the bitstream's free bitrate - */ -static -int free_bitrate(struct mad_stream *stream, struct mad_header const *header) -{ - struct mad_bitptr keep_ptr; - unsigned long rate = 0; - unsigned int pad_slot, slots_per_frame; - unsigned char const *ptr = 0; - - keep_ptr = stream->ptr; - - pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0; - slots_per_frame = (header->layer == MAD_LAYER_III && - (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144; - - while (mad_stream_sync(stream) == 0) { - struct mad_stream peek_stream; - struct mad_header peek_header; - - peek_stream = *stream; - peek_header = *header; - - if (decode_header(&peek_header, &peek_stream) == 0 && - peek_header.layer == header->layer && - peek_header.samplerate == header->samplerate) { - unsigned int N; - - ptr = mad_bit_nextbyte(&stream->ptr); - - N = ptr - stream->this_frame; - - if (header->layer == MAD_LAYER_I) { - rate = (unsigned long) header->samplerate * - (N - 4 * pad_slot + 4) / 48 / 1000; - } - else { - rate = (unsigned long) header->samplerate * - (N - pad_slot + 1) / slots_per_frame / 1000; - } - - if (rate >= 8) - break; - } - - mad_bit_skip(&stream->ptr, 8); - } - - stream->ptr = keep_ptr; - - if (rate < 8 || (header->layer == MAD_LAYER_III && rate > 640)) { - stream->error = MAD_ERROR_LOSTSYNC; - return -1; - } - - stream->freerate = rate * 1000; - - return 0; -} - -/* - * NAME: header->decode() - * DESCRIPTION: read the next frame header from the stream - */ -int mad_header_decode(struct mad_header *header, struct mad_stream *stream) -{ - register unsigned char const *ptr, *end; - unsigned int pad_slot, N; - - ptr = stream->next_frame; - end = stream->bufend; - - if (ptr == 0) { - stream->error = MAD_ERROR_BUFPTR; - goto fail; - } - - /* stream skip */ - if (stream->skiplen) { - if (!stream->sync) - ptr = stream->this_frame; - - if (end - ptr < stream->skiplen) { - stream->skiplen -= end - ptr; - stream->next_frame = end; - - stream->error = MAD_ERROR_BUFLEN; - goto fail; - } - - ptr += stream->skiplen; - stream->skiplen = 0; - - stream->sync = 1; - } - - sync: - /* synchronize */ - if (stream->sync) { - if (end - ptr < MAD_BUFFER_GUARD) { - stream->next_frame = ptr; - - stream->error = MAD_ERROR_BUFLEN; - goto fail; - } - else if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { - /* mark point where frame sync word was expected */ - stream->this_frame = ptr; - stream->next_frame = ptr + 1; - - stream->error = MAD_ERROR_LOSTSYNC; - goto fail; - } - } - else { - mad_bit_init(&stream->ptr, ptr); - - if (mad_stream_sync(stream) == -1) { - if (end - stream->next_frame >= MAD_BUFFER_GUARD) - stream->next_frame = end - MAD_BUFFER_GUARD; - - stream->error = MAD_ERROR_BUFLEN; - goto fail; - } - - ptr = mad_bit_nextbyte(&stream->ptr); - } - - /* begin processing */ - stream->this_frame = ptr; - stream->next_frame = ptr + 1; /* possibly bogus sync word */ - - mad_bit_init(&stream->ptr, stream->this_frame); - - if (decode_header(header, stream) == -1) - goto fail; - - /* calculate frame duration */ - mad_timer_set(&header->duration, 0, - 32 * MAD_NSBSAMPLES(header), header->samplerate); - - /* calculate free bit rate */ - if (header->bitrate == 0) { - if ((stream->freerate == 0 || !stream->sync || - (header->layer == MAD_LAYER_III && stream->freerate > 640000)) && - free_bitrate(stream, header) == -1) - goto fail; - - header->bitrate = stream->freerate; - header->flags |= MAD_FLAG_FREEFORMAT; - } - - /* calculate beginning of next frame */ - pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0; - - if (header->layer == MAD_LAYER_I) - N = ((12 * header->bitrate / header->samplerate) + pad_slot) * 4; - else { - unsigned int slots_per_frame; - - slots_per_frame = (header->layer == MAD_LAYER_III && - (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144; - - N = (slots_per_frame * header->bitrate / header->samplerate) + pad_slot; - } - - /* verify there is enough data left in buffer to decode this frame */ - if (N + MAD_BUFFER_GUARD > end - stream->this_frame) { - stream->next_frame = stream->this_frame; - - stream->error = MAD_ERROR_BUFLEN; - goto fail; - } - - stream->next_frame = stream->this_frame + N; - - if (!stream->sync) { - /* check that a valid frame header follows this frame */ - - ptr = stream->next_frame; - if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { - ptr = stream->next_frame = stream->this_frame + 1; - goto sync; - } - - stream->sync = 1; - } - - header->flags |= MAD_FLAG_INCOMPLETE; - - return 0; - - fail: - stream->sync = 0; - - return -1; -} - -/* - * NAME: frame->decode() - * DESCRIPTION: decode a single frame from a bitstream - */ -int mad_frame_decode(struct mad_frame *frame, struct mad_stream *stream) -{ - frame->options = stream->options; - - /* header() */ - /* error_check() */ - - if (!(frame->header.flags & MAD_FLAG_INCOMPLETE) && - mad_header_decode(&frame->header, stream) == -1) - goto fail; - - /* audio_data() */ - - frame->header.flags &= ~MAD_FLAG_INCOMPLETE; - - if (decoder_table[frame->header.layer - 1](stream, frame) == -1) { - if (!MAD_RECOVERABLE(stream->error)) - stream->next_frame = stream->this_frame; - - goto fail; - } - - /* ancillary_data() */ - - if (frame->header.layer != MAD_LAYER_III) { - struct mad_bitptr next_frame; - - mad_bit_init(&next_frame, stream->next_frame); - - stream->anc_ptr = stream->ptr; - stream->anc_bitlen = mad_bit_length(&stream->ptr, &next_frame); - - mad_bit_finish(&next_frame); - } - - return 0; - - fail: - stream->anc_bitlen = 0; - return -1; -} - -/* - * NAME: frame->mute() - * DESCRIPTION: zero all subband values so the frame becomes silent - */ -void mad_frame_mute(struct mad_frame *frame) -{ - unsigned int s, sb; - - for (s = 0; s < 36; ++s) { - for (sb = 0; sb < 32; ++sb) { - frame->sbsample[0][s][sb] = - frame->sbsample[1][s][sb] = 0; - } - } - - if (frame->overlap) { - for (s = 0; s < 18; ++s) { - for (sb = 0; sb < 32; ++sb) { - (*frame->overlap)[0][sb][s] = - (*frame->overlap)[1][sb][s] = 0; - } - } - } -} - -# ifdef _MSC_VER -# pragma warning(pop) -# endif diff --git a/libmad/src/frame.h b/libmad/src/frame.h deleted file mode 100644 index 3f5bf37..0000000 --- a/libmad/src/frame.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: frame.h,v 1.20 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_FRAME_H -# define LIBMAD_FRAME_H - -# include "fixed.h" -# include "timer.h" -# include "stream.h" - -enum mad_layer { - MAD_LAYER_I = 1, /* Layer I */ - MAD_LAYER_II = 2, /* Layer II */ - MAD_LAYER_III = 3 /* Layer III */ -}; - -enum mad_mode { - MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ - MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ - MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */ - MAD_MODE_STEREO = 3 /* normal LR stereo */ -}; - -enum mad_emphasis { - MAD_EMPHASIS_NONE = 0, /* no emphasis */ - MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */ - MAD_EMPHASIS_CCITT_J_17 = 3, /* CCITT J.17 emphasis */ - MAD_EMPHASIS_RESERVED = 2 /* unknown emphasis */ -}; - -struct mad_header { - enum mad_layer layer; /* audio layer (1, 2, or 3) */ - enum mad_mode mode; /* channel mode (see above) */ - int mode_extension; /* additional mode info */ - enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ - - unsigned long bitrate; /* stream bitrate (bps) */ - unsigned int samplerate; /* sampling frequency (Hz) */ - - unsigned short crc_check; /* frame CRC accumulator */ - unsigned short crc_target; /* final target CRC checksum */ - - int flags; /* flags (see below) */ - int private_bits; /* private bits (see below) */ - - mad_timer_t duration; /* audio playing time of frame */ -}; - -struct mad_frame { - struct mad_header header; /* MPEG audio header */ - - int options; /* decoding options (from stream) */ - - mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ - mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ -}; - -# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1) -# define MAD_NSBSAMPLES(header) \ - ((header)->layer == MAD_LAYER_I ? 12 : \ - (((header)->layer == MAD_LAYER_III && \ - ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36)) - -enum { - MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */ - MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */ - - MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */ - MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */ - MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */ - MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */ - - MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */ - MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */ - MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */ - - MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */ - MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */ - MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */ -}; - -enum { - MAD_PRIVATE_HEADER = 0x0100, /* header private bit */ - MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */ -}; - -void mad_header_init(struct mad_header *); - -# define mad_header_finish(header) /* nothing */ - -int mad_header_decode(struct mad_header *, struct mad_stream *); - -void mad_frame_init(struct mad_frame *); -void mad_frame_finish(struct mad_frame *); - -int mad_frame_decode(struct mad_frame *, struct mad_stream *); - -void mad_frame_mute(struct mad_frame *); - -# endif diff --git a/libmad/src/global.h b/libmad/src/global.h deleted file mode 100644 index a6debfd..0000000 --- a/libmad/src/global.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: global.h,v 1.11 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_GLOBAL_H -# define LIBMAD_GLOBAL_H - -/* conditional debugging */ - -# if defined(DEBUG) && defined(NDEBUG) -# error "cannot define both DEBUG and NDEBUG" -# endif - -# if defined(DEBUG) -# include -# endif - -/* conditional features */ - -# if defined(OPT_SPEED) && defined(OPT_ACCURACY) -# error "cannot optimize for both speed and accuracy" -# endif - -# if defined(OPT_SPEED) && !defined(OPT_SSO) -# define OPT_SSO -# endif - -# if defined(HAVE_UNISTD_H) && defined(HAVE_WAITPID) && \ - defined(HAVE_FCNTL) && defined(HAVE_PIPE) && defined(HAVE_FORK) -# define USE_ASYNC -# endif - -# if !defined(HAVE_ASSERT_H) -# if defined(NDEBUG) -# define assert(x) /* nothing */ -# else -# define assert(x) do { if (!(x)) abort(); } while (0) -# endif -# endif - -# endif diff --git a/libmad/src/huffman.c b/libmad/src/huffman.c deleted file mode 100644 index a230a9c..0000000 --- a/libmad/src/huffman.c +++ /dev/null @@ -1,3109 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: huffman.c,v 1.10 2004/01/23 09:41:32 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include "huffman.h" - -/* - * These are the Huffman code words for Layer III. - * The data for these tables are derived from Table B.7 of ISO/IEC 11172-3. - * - * These tables support decoding up to 4 Huffman code bits at a time. - */ - -# if defined(__GNUC__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) -# define PTR(offs, bits) { .ptr = { 0, bits, offs } } -# define V(v, w, x, y, hlen) { .value = { 1, hlen, v, w, x, y } } -# else -# define PTR(offs, bits) { { 0, bits, offs } } -# if defined(WORDS_BIGENDIAN) -# define V(v, w, x, y, hlen) { { 1, hlen, (v << 11) | (w << 10) | \ - (x << 9) | (y << 8) } } -# else -# define V(v, w, x, y, hlen) { { 1, hlen, (v << 0) | (w << 1) | \ - (x << 2) | (y << 3) } } -# endif -# endif - -static -union huffquad const hufftabA[] = { - /* 0000 */ PTR(16, 2), - /* 0001 */ PTR(20, 2), - /* 0010 */ PTR(24, 1), - /* 0011 */ PTR(26, 1), - /* 0100 */ V(0, 0, 1, 0, 4), - /* 0101 */ V(0, 0, 0, 1, 4), - /* 0110 */ V(0, 1, 0, 0, 4), - /* 0111 */ V(1, 0, 0, 0, 4), - /* 1000 */ V(0, 0, 0, 0, 1), - /* 1001 */ V(0, 0, 0, 0, 1), - /* 1010 */ V(0, 0, 0, 0, 1), - /* 1011 */ V(0, 0, 0, 0, 1), - /* 1100 */ V(0, 0, 0, 0, 1), - /* 1101 */ V(0, 0, 0, 0, 1), - /* 1110 */ V(0, 0, 0, 0, 1), - /* 1111 */ V(0, 0, 0, 0, 1), - - /* 0000 ... */ - /* 00 */ V(1, 0, 1, 1, 2), /* 16 */ - /* 01 */ V(1, 1, 1, 1, 2), - /* 10 */ V(1, 1, 0, 1, 2), - /* 11 */ V(1, 1, 1, 0, 2), - - /* 0001 ... */ - /* 00 */ V(0, 1, 1, 1, 2), /* 20 */ - /* 01 */ V(0, 1, 0, 1, 2), - /* 10 */ V(1, 0, 0, 1, 1), - /* 11 */ V(1, 0, 0, 1, 1), - - /* 0010 ... */ - /* 0 */ V(0, 1, 1, 0, 1), /* 24 */ - /* 1 */ V(0, 0, 1, 1, 1), - - /* 0011 ... */ - /* 0 */ V(1, 0, 1, 0, 1), /* 26 */ - /* 1 */ V(1, 1, 0, 0, 1) -}; - -static -union huffquad const hufftabB[] = { - /* 0000 */ V(1, 1, 1, 1, 4), - /* 0001 */ V(1, 1, 1, 0, 4), - /* 0010 */ V(1, 1, 0, 1, 4), - /* 0011 */ V(1, 1, 0, 0, 4), - /* 0100 */ V(1, 0, 1, 1, 4), - /* 0101 */ V(1, 0, 1, 0, 4), - /* 0110 */ V(1, 0, 0, 1, 4), - /* 0111 */ V(1, 0, 0, 0, 4), - /* 1000 */ V(0, 1, 1, 1, 4), - /* 1001 */ V(0, 1, 1, 0, 4), - /* 1010 */ V(0, 1, 0, 1, 4), - /* 1011 */ V(0, 1, 0, 0, 4), - /* 1100 */ V(0, 0, 1, 1, 4), - /* 1101 */ V(0, 0, 1, 0, 4), - /* 1110 */ V(0, 0, 0, 1, 4), - /* 1111 */ V(0, 0, 0, 0, 4) -}; - -# undef V -# undef PTR - -# if defined(__GNUC__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) -# define PTR(offs, bits) { .ptr = { 0, bits, offs } } -# define V(x, y, hlen) { .value = { 1, hlen, x, y } } -# else -# define PTR(offs, bits) { { 0, bits, offs } } -# if defined(WORDS_BIGENDIAN) -# define V(x, y, hlen) { { 1, hlen, (x << 8) | (y << 4) } } -# else -# define V(x, y, hlen) { { 1, hlen, (x << 0) | (y << 4) } } -# endif -# endif - -static -union huffpair const hufftab0[] = { - /* */ V(0, 0, 0) -}; - -static -union huffpair const hufftab1[] = { - /* 000 */ V(1, 1, 3), - /* 001 */ V(0, 1, 3), - /* 010 */ V(1, 0, 2), - /* 011 */ V(1, 0, 2), - /* 100 */ V(0, 0, 1), - /* 101 */ V(0, 0, 1), - /* 110 */ V(0, 0, 1), - /* 111 */ V(0, 0, 1) -}; - -static -union huffpair const hufftab2[] = { - /* 000 */ PTR(8, 3), - /* 001 */ V(1, 1, 3), - /* 010 */ V(0, 1, 3), - /* 011 */ V(1, 0, 3), - /* 100 */ V(0, 0, 1), - /* 101 */ V(0, 0, 1), - /* 110 */ V(0, 0, 1), - /* 111 */ V(0, 0, 1), - - /* 000 ... */ - /* 000 */ V(2, 2, 3), /* 8 */ - /* 001 */ V(0, 2, 3), - /* 010 */ V(1, 2, 2), - /* 011 */ V(1, 2, 2), - /* 100 */ V(2, 1, 2), - /* 101 */ V(2, 1, 2), - /* 110 */ V(2, 0, 2), - /* 111 */ V(2, 0, 2) -}; - -static -union huffpair const hufftab3[] = { - /* 000 */ PTR(8, 3), - /* 001 */ V(1, 0, 3), - /* 010 */ V(1, 1, 2), - /* 011 */ V(1, 1, 2), - /* 100 */ V(0, 1, 2), - /* 101 */ V(0, 1, 2), - /* 110 */ V(0, 0, 2), - /* 111 */ V(0, 0, 2), - - /* 000 ... */ - /* 000 */ V(2, 2, 3), /* 8 */ - /* 001 */ V(0, 2, 3), - /* 010 */ V(1, 2, 2), - /* 011 */ V(1, 2, 2), - /* 100 */ V(2, 1, 2), - /* 101 */ V(2, 1, 2), - /* 110 */ V(2, 0, 2), - /* 111 */ V(2, 0, 2) -}; - -static -union huffpair const hufftab5[] = { - /* 000 */ PTR(8, 4), - /* 001 */ V(1, 1, 3), - /* 010 */ V(0, 1, 3), - /* 011 */ V(1, 0, 3), - /* 100 */ V(0, 0, 1), - /* 101 */ V(0, 0, 1), - /* 110 */ V(0, 0, 1), - /* 111 */ V(0, 0, 1), - - /* 000 ... */ - /* 0000 */ PTR(24, 1), /* 8 */ - /* 0001 */ V(3, 2, 4), - /* 0010 */ V(3, 1, 3), - /* 0011 */ V(3, 1, 3), - /* 0100 */ V(1, 3, 4), - /* 0101 */ V(0, 3, 4), - /* 0110 */ V(3, 0, 4), - /* 0111 */ V(2, 2, 4), - /* 1000 */ V(1, 2, 3), - /* 1001 */ V(1, 2, 3), - /* 1010 */ V(2, 1, 3), - /* 1011 */ V(2, 1, 3), - /* 1100 */ V(0, 2, 3), - /* 1101 */ V(0, 2, 3), - /* 1110 */ V(2, 0, 3), - /* 1111 */ V(2, 0, 3), - - /* 000 0000 ... */ - /* 0 */ V(3, 3, 1), /* 24 */ - /* 1 */ V(2, 3, 1) -}; - -static -union huffpair const hufftab6[] = { - /* 0000 */ PTR(16, 3), - /* 0001 */ PTR(24, 1), - /* 0010 */ PTR(26, 1), - /* 0011 */ V(1, 2, 4), - /* 0100 */ V(2, 1, 4), - /* 0101 */ V(2, 0, 4), - /* 0110 */ V(0, 1, 3), - /* 0111 */ V(0, 1, 3), - /* 1000 */ V(1, 1, 2), - /* 1001 */ V(1, 1, 2), - /* 1010 */ V(1, 1, 2), - /* 1011 */ V(1, 1, 2), - /* 1100 */ V(1, 0, 3), - /* 1101 */ V(1, 0, 3), - /* 1110 */ V(0, 0, 3), - /* 1111 */ V(0, 0, 3), - - /* 0000 ... */ - /* 000 */ V(3, 3, 3), /* 16 */ - /* 001 */ V(0, 3, 3), - /* 010 */ V(2, 3, 2), - /* 011 */ V(2, 3, 2), - /* 100 */ V(3, 2, 2), - /* 101 */ V(3, 2, 2), - /* 110 */ V(3, 0, 2), - /* 111 */ V(3, 0, 2), - - /* 0001 ... */ - /* 0 */ V(1, 3, 1), /* 24 */ - /* 1 */ V(3, 1, 1), - - /* 0010 ... */ - /* 0 */ V(2, 2, 1), /* 26 */ - /* 1 */ V(0, 2, 1) -}; - -static -union huffpair const hufftab7[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ PTR(48, 2), - /* 0011 */ V(1, 1, 4), - /* 0100 */ V(0, 1, 3), - /* 0101 */ V(0, 1, 3), - /* 0110 */ V(1, 0, 3), - /* 0111 */ V(1, 0, 3), - /* 1000 */ V(0, 0, 1), - /* 1001 */ V(0, 0, 1), - /* 1010 */ V(0, 0, 1), - /* 1011 */ V(0, 0, 1), - /* 1100 */ V(0, 0, 1), - /* 1101 */ V(0, 0, 1), - /* 1110 */ V(0, 0, 1), - /* 1111 */ V(0, 0, 1), - - /* 0000 ... */ - /* 0000 */ PTR(52, 2), /* 16 */ - /* 0001 */ PTR(56, 1), - /* 0010 */ PTR(58, 1), - /* 0011 */ V(1, 5, 4), - /* 0100 */ V(5, 1, 4), - /* 0101 */ PTR(60, 1), - /* 0110 */ V(5, 0, 4), - /* 0111 */ PTR(62, 1), - /* 1000 */ V(2, 4, 4), - /* 1001 */ V(4, 2, 4), - /* 1010 */ V(1, 4, 3), - /* 1011 */ V(1, 4, 3), - /* 1100 */ V(4, 1, 3), - /* 1101 */ V(4, 1, 3), - /* 1110 */ V(4, 0, 3), - /* 1111 */ V(4, 0, 3), - - /* 0001 ... */ - /* 0000 */ V(0, 4, 4), /* 32 */ - /* 0001 */ V(2, 3, 4), - /* 0010 */ V(3, 2, 4), - /* 0011 */ V(0, 3, 4), - /* 0100 */ V(1, 3, 3), - /* 0101 */ V(1, 3, 3), - /* 0110 */ V(3, 1, 3), - /* 0111 */ V(3, 1, 3), - /* 1000 */ V(3, 0, 3), - /* 1001 */ V(3, 0, 3), - /* 1010 */ V(2, 2, 3), - /* 1011 */ V(2, 2, 3), - /* 1100 */ V(1, 2, 2), - /* 1101 */ V(1, 2, 2), - /* 1110 */ V(1, 2, 2), - /* 1111 */ V(1, 2, 2), - - /* 0010 ... */ - /* 00 */ V(2, 1, 1), /* 48 */ - /* 01 */ V(2, 1, 1), - /* 10 */ V(0, 2, 2), - /* 11 */ V(2, 0, 2), - - /* 0000 0000 ... */ - /* 00 */ V(5, 5, 2), /* 52 */ - /* 01 */ V(4, 5, 2), - /* 10 */ V(5, 4, 2), - /* 11 */ V(5, 3, 2), - - /* 0000 0001 ... */ - /* 0 */ V(3, 5, 1), /* 56 */ - /* 1 */ V(4, 4, 1), - - /* 0000 0010 ... */ - /* 0 */ V(2, 5, 1), /* 58 */ - /* 1 */ V(5, 2, 1), - - /* 0000 0101 ... */ - /* 0 */ V(0, 5, 1), /* 60 */ - /* 1 */ V(3, 4, 1), - - /* 0000 0111 ... */ - /* 0 */ V(4, 3, 1), /* 62 */ - /* 1 */ V(3, 3, 1) -}; - -# if 0 -/* this version saves 8 entries (16 bytes) at the expense of - an extra lookup in 4 out of 36 cases */ -static -union huffpair const hufftab8[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 2), - /* 0010 */ V(1, 2, 4), - /* 0011 */ V(2, 1, 4), - /* 0100 */ V(1, 1, 2), - /* 0101 */ V(1, 1, 2), - /* 0110 */ V(1, 1, 2), - /* 0111 */ V(1, 1, 2), - /* 1000 */ V(0, 1, 3), - /* 1001 */ V(0, 1, 3), - /* 1010 */ V(1, 0, 3), - /* 1011 */ V(1, 0, 3), - /* 1100 */ V(0, 0, 2), - /* 1101 */ V(0, 0, 2), - /* 1110 */ V(0, 0, 2), - /* 1111 */ V(0, 0, 2), - - /* 0000 ... */ - /* 0000 */ PTR(36, 3), /* 16 */ - /* 0001 */ PTR(44, 2), - /* 0010 */ PTR(48, 1), - /* 0011 */ V(1, 5, 4), - /* 0100 */ V(5, 1, 4), - /* 0101 */ PTR(50, 1), - /* 0110 */ PTR(52, 1), - /* 0111 */ V(2, 4, 4), - /* 1000 */ V(4, 2, 4), - /* 1001 */ V(1, 4, 4), - /* 1010 */ V(4, 1, 3), - /* 1011 */ V(4, 1, 3), - /* 1100 */ V(0, 4, 4), - /* 1101 */ V(4, 0, 4), - /* 1110 */ V(2, 3, 4), - /* 1111 */ V(3, 2, 4), - - /* 0001 ... */ - /* 00 */ PTR(54, 2), /* 32 */ - /* 01 */ V(2, 2, 2), - /* 10 */ V(0, 2, 2), - /* 11 */ V(2, 0, 2), - - /* 0000 0000 ... */ - /* 000 */ V(5, 5, 3), /* 36 */ - /* 001 */ V(5, 4, 3), - /* 010 */ V(4, 5, 2), - /* 011 */ V(4, 5, 2), - /* 100 */ V(5, 3, 1), - /* 101 */ V(5, 3, 1), - /* 110 */ V(5, 3, 1), - /* 111 */ V(5, 3, 1), - - /* 0000 0001 ... */ - /* 00 */ V(3, 5, 2), /* 44 */ - /* 01 */ V(4, 4, 2), - /* 10 */ V(2, 5, 1), - /* 11 */ V(2, 5, 1), - - /* 0000 0010 ... */ - /* 0 */ V(5, 2, 1), /* 48 */ - /* 1 */ V(0, 5, 1), - - /* 0000 0101 ... */ - /* 0 */ V(3, 4, 1), /* 50 */ - /* 1 */ V(4, 3, 1), - - /* 0000 0110 ... */ - /* 0 */ V(5, 0, 1), /* 52 */ - /* 1 */ V(3, 3, 1), - - /* 0001 00 ... */ - /* 00 */ V(1, 3, 2), /* 54 */ - /* 01 */ V(3, 1, 2), - /* 10 */ V(0, 3, 2), - /* 11 */ V(3, 0, 2), -}; -# else -static -union huffpair const hufftab8[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ V(1, 2, 4), - /* 0011 */ V(2, 1, 4), - /* 0100 */ V(1, 1, 2), - /* 0101 */ V(1, 1, 2), - /* 0110 */ V(1, 1, 2), - /* 0111 */ V(1, 1, 2), - /* 1000 */ V(0, 1, 3), - /* 1001 */ V(0, 1, 3), - /* 1010 */ V(1, 0, 3), - /* 1011 */ V(1, 0, 3), - /* 1100 */ V(0, 0, 2), - /* 1101 */ V(0, 0, 2), - /* 1110 */ V(0, 0, 2), - /* 1111 */ V(0, 0, 2), - - /* 0000 ... */ - /* 0000 */ PTR(48, 3), /* 16 */ - /* 0001 */ PTR(56, 2), - /* 0010 */ PTR(60, 1), - /* 0011 */ V(1, 5, 4), - /* 0100 */ V(5, 1, 4), - /* 0101 */ PTR(62, 1), - /* 0110 */ PTR(64, 1), - /* 0111 */ V(2, 4, 4), - /* 1000 */ V(4, 2, 4), - /* 1001 */ V(1, 4, 4), - /* 1010 */ V(4, 1, 3), - /* 1011 */ V(4, 1, 3), - /* 1100 */ V(0, 4, 4), - /* 1101 */ V(4, 0, 4), - /* 1110 */ V(2, 3, 4), - /* 1111 */ V(3, 2, 4), - - /* 0001 ... */ - /* 0000 */ V(1, 3, 4), /* 32 */ - /* 0001 */ V(3, 1, 4), - /* 0010 */ V(0, 3, 4), - /* 0011 */ V(3, 0, 4), - /* 0100 */ V(2, 2, 2), - /* 0101 */ V(2, 2, 2), - /* 0110 */ V(2, 2, 2), - /* 0111 */ V(2, 2, 2), - /* 1000 */ V(0, 2, 2), - /* 1001 */ V(0, 2, 2), - /* 1010 */ V(0, 2, 2), - /* 1011 */ V(0, 2, 2), - /* 1100 */ V(2, 0, 2), - /* 1101 */ V(2, 0, 2), - /* 1110 */ V(2, 0, 2), - /* 1111 */ V(2, 0, 2), - - /* 0000 0000 ... */ - /* 000 */ V(5, 5, 3), /* 48 */ - /* 001 */ V(5, 4, 3), - /* 010 */ V(4, 5, 2), - /* 011 */ V(4, 5, 2), - /* 100 */ V(5, 3, 1), - /* 101 */ V(5, 3, 1), - /* 110 */ V(5, 3, 1), - /* 111 */ V(5, 3, 1), - - /* 0000 0001 ... */ - /* 00 */ V(3, 5, 2), /* 56 */ - /* 01 */ V(4, 4, 2), - /* 10 */ V(2, 5, 1), - /* 11 */ V(2, 5, 1), - - /* 0000 0010 ... */ - /* 0 */ V(5, 2, 1), /* 60 */ - /* 1 */ V(0, 5, 1), - - /* 0000 0101 ... */ - /* 0 */ V(3, 4, 1), /* 62 */ - /* 1 */ V(4, 3, 1), - - /* 0000 0110 ... */ - /* 0 */ V(5, 0, 1), /* 64 */ - /* 1 */ V(3, 3, 1) -}; -# endif - -static -union huffpair const hufftab9[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 3), - /* 0010 */ PTR(40, 2), - /* 0011 */ PTR(44, 2), - /* 0100 */ PTR(48, 1), - /* 0101 */ V(1, 2, 4), - /* 0110 */ V(2, 1, 4), - /* 0111 */ V(2, 0, 4), - /* 1000 */ V(1, 1, 3), - /* 1001 */ V(1, 1, 3), - /* 1010 */ V(0, 1, 3), - /* 1011 */ V(0, 1, 3), - /* 1100 */ V(1, 0, 3), - /* 1101 */ V(1, 0, 3), - /* 1110 */ V(0, 0, 3), - /* 1111 */ V(0, 0, 3), - - /* 0000 ... */ - /* 0000 */ PTR(50, 1), /* 16 */ - /* 0001 */ V(3, 5, 4), - /* 0010 */ V(5, 3, 4), - /* 0011 */ PTR(52, 1), - /* 0100 */ V(4, 4, 4), - /* 0101 */ V(2, 5, 4), - /* 0110 */ V(5, 2, 4), - /* 0111 */ V(1, 5, 4), - /* 1000 */ V(5, 1, 3), - /* 1001 */ V(5, 1, 3), - /* 1010 */ V(3, 4, 3), - /* 1011 */ V(3, 4, 3), - /* 1100 */ V(4, 3, 3), - /* 1101 */ V(4, 3, 3), - /* 1110 */ V(5, 0, 4), - /* 1111 */ V(0, 4, 4), - - /* 0001 ... */ - /* 000 */ V(2, 4, 3), /* 32 */ - /* 001 */ V(4, 2, 3), - /* 010 */ V(3, 3, 3), - /* 011 */ V(4, 0, 3), - /* 100 */ V(1, 4, 2), - /* 101 */ V(1, 4, 2), - /* 110 */ V(4, 1, 2), - /* 111 */ V(4, 1, 2), - - /* 0010 ... */ - /* 00 */ V(2, 3, 2), /* 40 */ - /* 01 */ V(3, 2, 2), - /* 10 */ V(1, 3, 1), - /* 11 */ V(1, 3, 1), - - /* 0011 ... */ - /* 00 */ V(3, 1, 1), /* 44 */ - /* 01 */ V(3, 1, 1), - /* 10 */ V(0, 3, 2), - /* 11 */ V(3, 0, 2), - - /* 0100 ... */ - /* 0 */ V(2, 2, 1), /* 48 */ - /* 1 */ V(0, 2, 1), - - /* 0000 0000 ... */ - /* 0 */ V(5, 5, 1), /* 50 */ - /* 1 */ V(4, 5, 1), - - /* 0000 0011 ... */ - /* 0 */ V(5, 4, 1), /* 52 */ - /* 1 */ V(0, 5, 1) -}; - -static -union huffpair const hufftab10[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ PTR(48, 2), - /* 0011 */ V(1, 1, 4), - /* 0100 */ V(0, 1, 3), - /* 0101 */ V(0, 1, 3), - /* 0110 */ V(1, 0, 3), - /* 0111 */ V(1, 0, 3), - /* 1000 */ V(0, 0, 1), - /* 1001 */ V(0, 0, 1), - /* 1010 */ V(0, 0, 1), - /* 1011 */ V(0, 0, 1), - /* 1100 */ V(0, 0, 1), - /* 1101 */ V(0, 0, 1), - /* 1110 */ V(0, 0, 1), - /* 1111 */ V(0, 0, 1), - - /* 0000 ... */ - /* 0000 */ PTR(52, 3), /* 16 */ - /* 0001 */ PTR(60, 2), - /* 0010 */ PTR(64, 3), - /* 0011 */ PTR(72, 1), - /* 0100 */ PTR(74, 2), - /* 0101 */ PTR(78, 2), - /* 0110 */ PTR(82, 2), - /* 0111 */ V(1, 7, 4), - /* 1000 */ V(7, 1, 4), - /* 1001 */ PTR(86, 1), - /* 1010 */ PTR(88, 2), - /* 1011 */ PTR(92, 2), - /* 1100 */ V(1, 6, 4), - /* 1101 */ V(6, 1, 4), - /* 1110 */ V(6, 0, 4), - /* 1111 */ PTR(96, 1), - - /* 0001 ... */ - /* 0000 */ PTR(98, 1), /* 32 */ - /* 0001 */ PTR(100, 1), - /* 0010 */ V(1, 4, 4), - /* 0011 */ V(4, 1, 4), - /* 0100 */ V(4, 0, 4), - /* 0101 */ V(2, 3, 4), - /* 0110 */ V(3, 2, 4), - /* 0111 */ V(0, 3, 4), - /* 1000 */ V(1, 3, 3), - /* 1001 */ V(1, 3, 3), - /* 1010 */ V(3, 1, 3), - /* 1011 */ V(3, 1, 3), - /* 1100 */ V(3, 0, 3), - /* 1101 */ V(3, 0, 3), - /* 1110 */ V(2, 2, 3), - /* 1111 */ V(2, 2, 3), - - /* 0010 ... */ - /* 00 */ V(1, 2, 2), /* 48 */ - /* 01 */ V(2, 1, 2), - /* 10 */ V(0, 2, 2), - /* 11 */ V(2, 0, 2), - - /* 0000 0000 ... */ - /* 000 */ V(7, 7, 3), /* 52 */ - /* 001 */ V(6, 7, 3), - /* 010 */ V(7, 6, 3), - /* 011 */ V(5, 7, 3), - /* 100 */ V(7, 5, 3), - /* 101 */ V(6, 6, 3), - /* 110 */ V(4, 7, 2), - /* 111 */ V(4, 7, 2), - - /* 0000 0001 ... */ - /* 00 */ V(7, 4, 2), /* 60 */ - /* 01 */ V(5, 6, 2), - /* 10 */ V(6, 5, 2), - /* 11 */ V(3, 7, 2), - - /* 0000 0010 ... */ - /* 000 */ V(7, 3, 2), /* 64 */ - /* 001 */ V(7, 3, 2), - /* 010 */ V(4, 6, 2), - /* 011 */ V(4, 6, 2), - /* 100 */ V(5, 5, 3), - /* 101 */ V(5, 4, 3), - /* 110 */ V(6, 3, 2), - /* 111 */ V(6, 3, 2), - - /* 0000 0011 ... */ - /* 0 */ V(2, 7, 1), /* 72 */ - /* 1 */ V(7, 2, 1), - - /* 0000 0100 ... */ - /* 00 */ V(6, 4, 2), /* 74 */ - /* 01 */ V(0, 7, 2), - /* 10 */ V(7, 0, 1), - /* 11 */ V(7, 0, 1), - - /* 0000 0101 ... */ - /* 00 */ V(6, 2, 1), /* 78 */ - /* 01 */ V(6, 2, 1), - /* 10 */ V(4, 5, 2), - /* 11 */ V(3, 5, 2), - - /* 0000 0110 ... */ - /* 00 */ V(0, 6, 1), /* 82 */ - /* 01 */ V(0, 6, 1), - /* 10 */ V(5, 3, 2), - /* 11 */ V(4, 4, 2), - - /* 0000 1001 ... */ - /* 0 */ V(3, 6, 1), /* 86 */ - /* 1 */ V(2, 6, 1), - - /* 0000 1010 ... */ - /* 00 */ V(2, 5, 2), /* 88 */ - /* 01 */ V(5, 2, 2), - /* 10 */ V(1, 5, 1), - /* 11 */ V(1, 5, 1), - - /* 0000 1011 ... */ - /* 00 */ V(5, 1, 1), /* 92 */ - /* 01 */ V(5, 1, 1), - /* 10 */ V(3, 4, 2), - /* 11 */ V(4, 3, 2), - - /* 0000 1111 ... */ - /* 0 */ V(0, 5, 1), /* 96 */ - /* 1 */ V(5, 0, 1), - - /* 0001 0000 ... */ - /* 0 */ V(2, 4, 1), /* 98 */ - /* 1 */ V(4, 2, 1), - - /* 0001 0001 ... */ - /* 0 */ V(3, 3, 1), /* 100 */ - /* 1 */ V(0, 4, 1) -}; - -static -union huffpair const hufftab11[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ PTR(48, 4), - /* 0011 */ PTR(64, 3), - /* 0100 */ V(1, 2, 4), - /* 0101 */ PTR(72, 1), - /* 0110 */ V(1, 1, 3), - /* 0111 */ V(1, 1, 3), - /* 1000 */ V(0, 1, 3), - /* 1001 */ V(0, 1, 3), - /* 1010 */ V(1, 0, 3), - /* 1011 */ V(1, 0, 3), - /* 1100 */ V(0, 0, 2), - /* 1101 */ V(0, 0, 2), - /* 1110 */ V(0, 0, 2), - /* 1111 */ V(0, 0, 2), - - /* 0000 ... */ - /* 0000 */ PTR(74, 2), /* 16 */ - /* 0001 */ PTR(78, 3), - /* 0010 */ PTR(86, 2), - /* 0011 */ PTR(90, 1), - /* 0100 */ PTR(92, 2), - /* 0101 */ V(2, 7, 4), - /* 0110 */ V(7, 2, 4), - /* 0111 */ PTR(96, 1), - /* 1000 */ V(7, 1, 3), - /* 1001 */ V(7, 1, 3), - /* 1010 */ V(1, 7, 4), - /* 1011 */ V(7, 0, 4), - /* 1100 */ V(3, 6, 4), - /* 1101 */ V(6, 3, 4), - /* 1110 */ V(6, 0, 4), - /* 1111 */ PTR(98, 1), - - /* 0001 ... */ - /* 0000 */ PTR(100, 1), /* 32 */ - /* 0001 */ V(1, 5, 4), - /* 0010 */ V(6, 2, 3), - /* 0011 */ V(6, 2, 3), - /* 0100 */ V(2, 6, 4), - /* 0101 */ V(0, 6, 4), - /* 0110 */ V(1, 6, 3), - /* 0111 */ V(1, 6, 3), - /* 1000 */ V(6, 1, 3), - /* 1001 */ V(6, 1, 3), - /* 1010 */ V(5, 1, 4), - /* 1011 */ V(3, 4, 4), - /* 1100 */ V(5, 0, 4), - /* 1101 */ PTR(102, 1), - /* 1110 */ V(2, 4, 4), - /* 1111 */ V(4, 2, 4), - - /* 0010 ... */ - /* 0000 */ V(1, 4, 4), /* 48 */ - /* 0001 */ V(4, 1, 4), - /* 0010 */ V(0, 4, 4), - /* 0011 */ V(4, 0, 4), - /* 0100 */ V(2, 3, 3), - /* 0101 */ V(2, 3, 3), - /* 0110 */ V(3, 2, 3), - /* 0111 */ V(3, 2, 3), - /* 1000 */ V(1, 3, 2), - /* 1001 */ V(1, 3, 2), - /* 1010 */ V(1, 3, 2), - /* 1011 */ V(1, 3, 2), - /* 1100 */ V(3, 1, 2), - /* 1101 */ V(3, 1, 2), - /* 1110 */ V(3, 1, 2), - /* 1111 */ V(3, 1, 2), - - /* 0011 ... */ - /* 000 */ V(0, 3, 3), /* 64 */ - /* 001 */ V(3, 0, 3), - /* 010 */ V(2, 2, 2), - /* 011 */ V(2, 2, 2), - /* 100 */ V(2, 1, 1), - /* 101 */ V(2, 1, 1), - /* 110 */ V(2, 1, 1), - /* 111 */ V(2, 1, 1), - - /* 0101 ... */ - /* 0 */ V(0, 2, 1), /* 72 */ - /* 1 */ V(2, 0, 1), - - /* 0000 0000 ... */ - /* 00 */ V(7, 7, 2), /* 74 */ - /* 01 */ V(6, 7, 2), - /* 10 */ V(7, 6, 2), - /* 11 */ V(7, 5, 2), - - /* 0000 0001 ... */ - /* 000 */ V(6, 6, 2), /* 78 */ - /* 001 */ V(6, 6, 2), - /* 010 */ V(4, 7, 2), - /* 011 */ V(4, 7, 2), - /* 100 */ V(7, 4, 2), - /* 101 */ V(7, 4, 2), - /* 110 */ V(5, 7, 3), - /* 111 */ V(5, 5, 3), - - /* 0000 0010 ... */ - /* 00 */ V(5, 6, 2), /* 86 */ - /* 01 */ V(6, 5, 2), - /* 10 */ V(3, 7, 1), - /* 11 */ V(3, 7, 1), - - /* 0000 0011 ... */ - /* 0 */ V(7, 3, 1), /* 90 */ - /* 1 */ V(4, 6, 1), - - /* 0000 0100 ... */ - /* 00 */ V(4, 5, 2), /* 92 */ - /* 01 */ V(5, 4, 2), - /* 10 */ V(3, 5, 2), - /* 11 */ V(5, 3, 2), - - /* 0000 0111 ... */ - /* 0 */ V(6, 4, 1), /* 96 */ - /* 1 */ V(0, 7, 1), - - /* 0000 1111 ... */ - /* 0 */ V(4, 4, 1), /* 98 */ - /* 1 */ V(2, 5, 1), - - /* 0001 0000 ... */ - /* 0 */ V(5, 2, 1), /* 100 */ - /* 1 */ V(0, 5, 1), - - /* 0001 1101 ... */ - /* 0 */ V(4, 3, 1), /* 102 */ - /* 1 */ V(3, 3, 1) -}; - -static -union huffpair const hufftab12[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ PTR(48, 4), - /* 0011 */ PTR(64, 2), - /* 0100 */ PTR(68, 3), - /* 0101 */ PTR(76, 1), - /* 0110 */ V(1, 2, 4), - /* 0111 */ V(2, 1, 4), - /* 1000 */ PTR(78, 1), - /* 1001 */ V(0, 0, 4), - /* 1010 */ V(1, 1, 3), - /* 1011 */ V(1, 1, 3), - /* 1100 */ V(0, 1, 3), - /* 1101 */ V(0, 1, 3), - /* 1110 */ V(1, 0, 3), - /* 1111 */ V(1, 0, 3), - - /* 0000 ... */ - /* 0000 */ PTR(80, 2), /* 16 */ - /* 0001 */ PTR(84, 1), - /* 0010 */ PTR(86, 1), - /* 0011 */ PTR(88, 1), - /* 0100 */ V(5, 6, 4), - /* 0101 */ V(3, 7, 4), - /* 0110 */ PTR(90, 1), - /* 0111 */ V(2, 7, 4), - /* 1000 */ V(7, 2, 4), - /* 1001 */ V(4, 6, 4), - /* 1010 */ V(6, 4, 4), - /* 1011 */ V(1, 7, 4), - /* 1100 */ V(7, 1, 4), - /* 1101 */ PTR(92, 1), - /* 1110 */ V(3, 6, 4), - /* 1111 */ V(6, 3, 4), - - /* 0001 ... */ - /* 0000 */ V(4, 5, 4), /* 32 */ - /* 0001 */ V(5, 4, 4), - /* 0010 */ V(4, 4, 4), - /* 0011 */ PTR(94, 1), - /* 0100 */ V(2, 6, 3), - /* 0101 */ V(2, 6, 3), - /* 0110 */ V(6, 2, 3), - /* 0111 */ V(6, 2, 3), - /* 1000 */ V(6, 1, 3), - /* 1001 */ V(6, 1, 3), - /* 1010 */ V(1, 6, 4), - /* 1011 */ V(6, 0, 4), - /* 1100 */ V(3, 5, 4), - /* 1101 */ V(5, 3, 4), - /* 1110 */ V(2, 5, 4), - /* 1111 */ V(5, 2, 4), - - /* 0010 ... */ - /* 0000 */ V(1, 5, 3), /* 48 */ - /* 0001 */ V(1, 5, 3), - /* 0010 */ V(5, 1, 3), - /* 0011 */ V(5, 1, 3), - /* 0100 */ V(3, 4, 3), - /* 0101 */ V(3, 4, 3), - /* 0110 */ V(4, 3, 3), - /* 0111 */ V(4, 3, 3), - /* 1000 */ V(5, 0, 4), - /* 1001 */ V(0, 4, 4), - /* 1010 */ V(2, 4, 3), - /* 1011 */ V(2, 4, 3), - /* 1100 */ V(4, 2, 3), - /* 1101 */ V(4, 2, 3), - /* 1110 */ V(1, 4, 3), - /* 1111 */ V(1, 4, 3), - - /* 0011 ... */ - /* 00 */ V(3, 3, 2), /* 64 */ - /* 01 */ V(4, 1, 2), - /* 10 */ V(2, 3, 2), - /* 11 */ V(3, 2, 2), - - /* 0100 ... */ - /* 000 */ V(4, 0, 3), /* 68 */ - /* 001 */ V(0, 3, 3), - /* 010 */ V(3, 0, 2), - /* 011 */ V(3, 0, 2), - /* 100 */ V(1, 3, 1), - /* 101 */ V(1, 3, 1), - /* 110 */ V(1, 3, 1), - /* 111 */ V(1, 3, 1), - - /* 0101 ... */ - /* 0 */ V(3, 1, 1), /* 76 */ - /* 1 */ V(2, 2, 1), - - /* 1000 ... */ - /* 0 */ V(0, 2, 1), /* 78 */ - /* 1 */ V(2, 0, 1), - - /* 0000 0000 ... */ - /* 00 */ V(7, 7, 2), /* 80 */ - /* 01 */ V(6, 7, 2), - /* 10 */ V(7, 6, 1), - /* 11 */ V(7, 6, 1), - - /* 0000 0001 ... */ - /* 0 */ V(5, 7, 1), /* 84 */ - /* 1 */ V(7, 5, 1), - - /* 0000 0010 ... */ - /* 0 */ V(6, 6, 1), /* 86 */ - /* 1 */ V(4, 7, 1), - - /* 0000 0011 ... */ - /* 0 */ V(7, 4, 1), /* 88 */ - /* 1 */ V(6, 5, 1), - - /* 0000 0110 ... */ - /* 0 */ V(7, 3, 1), /* 90 */ - /* 1 */ V(5, 5, 1), - - /* 0000 1101 ... */ - /* 0 */ V(0, 7, 1), /* 92 */ - /* 1 */ V(7, 0, 1), - - /* 0001 0011 ... */ - /* 0 */ V(0, 6, 1), /* 94 */ - /* 1 */ V(0, 5, 1) -}; - -static -union huffpair const hufftab13[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ PTR(48, 4), - /* 0011 */ PTR(64, 2), - /* 0100 */ V(1, 1, 4), - /* 0101 */ V(0, 1, 4), - /* 0110 */ V(1, 0, 3), - /* 0111 */ V(1, 0, 3), - /* 1000 */ V(0, 0, 1), - /* 1001 */ V(0, 0, 1), - /* 1010 */ V(0, 0, 1), - /* 1011 */ V(0, 0, 1), - /* 1100 */ V(0, 0, 1), - /* 1101 */ V(0, 0, 1), - /* 1110 */ V(0, 0, 1), - /* 1111 */ V(0, 0, 1), - - /* 0000 ... */ - /* 0000 */ PTR(68, 4), /* 16 */ - /* 0001 */ PTR(84, 4), - /* 0010 */ PTR(100, 4), - /* 0011 */ PTR(116, 4), - /* 0100 */ PTR(132, 4), - /* 0101 */ PTR(148, 4), - /* 0110 */ PTR(164, 3), - /* 0111 */ PTR(172, 3), - /* 1000 */ PTR(180, 3), - /* 1001 */ PTR(188, 3), - /* 1010 */ PTR(196, 3), - /* 1011 */ PTR(204, 3), - /* 1100 */ PTR(212, 1), - /* 1101 */ PTR(214, 2), - /* 1110 */ PTR(218, 3), - /* 1111 */ PTR(226, 1), - - /* 0001 ... */ - /* 0000 */ PTR(228, 2), /* 32 */ - /* 0001 */ PTR(232, 2), - /* 0010 */ PTR(236, 2), - /* 0011 */ PTR(240, 2), - /* 0100 */ V(8, 1, 4), - /* 0101 */ PTR(244, 1), - /* 0110 */ PTR(246, 1), - /* 0111 */ PTR(248, 1), - /* 1000 */ PTR(250, 2), - /* 1001 */ PTR(254, 1), - /* 1010 */ V(1, 5, 4), - /* 1011 */ V(5, 1, 4), - /* 1100 */ PTR(256, 1), - /* 1101 */ PTR(258, 1), - /* 1110 */ PTR(260, 1), - /* 1111 */ V(1, 4, 4), - - /* 0010 ... */ - /* 0000 */ V(4, 1, 3), /* 48 */ - /* 0001 */ V(4, 1, 3), - /* 0010 */ V(0, 4, 4), - /* 0011 */ V(4, 0, 4), - /* 0100 */ V(2, 3, 4), - /* 0101 */ V(3, 2, 4), - /* 0110 */ V(1, 3, 3), - /* 0111 */ V(1, 3, 3), - /* 1000 */ V(3, 1, 3), - /* 1001 */ V(3, 1, 3), - /* 1010 */ V(0, 3, 3), - /* 1011 */ V(0, 3, 3), - /* 1100 */ V(3, 0, 3), - /* 1101 */ V(3, 0, 3), - /* 1110 */ V(2, 2, 3), - /* 1111 */ V(2, 2, 3), - - /* 0011 ... */ - /* 00 */ V(1, 2, 2), /* 64 */ - /* 01 */ V(2, 1, 2), - /* 10 */ V(0, 2, 2), - /* 11 */ V(2, 0, 2), - - /* 0000 0000 ... */ - /* 0000 */ PTR(262, 4), /* 68 */ - /* 0001 */ PTR(278, 4), - /* 0010 */ PTR(294, 4), - /* 0011 */ PTR(310, 3), - /* 0100 */ PTR(318, 2), - /* 0101 */ PTR(322, 2), - /* 0110 */ PTR(326, 3), - /* 0111 */ PTR(334, 2), - /* 1000 */ PTR(338, 1), - /* 1001 */ PTR(340, 2), - /* 1010 */ PTR(344, 2), - /* 1011 */ PTR(348, 2), - /* 1100 */ PTR(352, 2), - /* 1101 */ PTR(356, 2), - /* 1110 */ V(1, 15, 4), - /* 1111 */ V(15, 1, 4), - - /* 0000 0001 ... */ - /* 0000 */ V(15, 0, 4), /* 84 */ - /* 0001 */ PTR(360, 1), - /* 0010 */ PTR(362, 1), - /* 0011 */ PTR(364, 1), - /* 0100 */ V(14, 2, 4), - /* 0101 */ PTR(366, 1), - /* 0110 */ V(1, 14, 4), - /* 0111 */ V(14, 1, 4), - /* 1000 */ PTR(368, 1), - /* 1001 */ PTR(370, 1), - /* 1010 */ PTR(372, 1), - /* 1011 */ PTR(374, 1), - /* 1100 */ PTR(376, 1), - /* 1101 */ PTR(378, 1), - /* 1110 */ V(12, 6, 4), - /* 1111 */ V(3, 13, 4), - - /* 0000 0010 ... */ - /* 0000 */ PTR(380, 1), /* 100 */ - /* 0001 */ V(2, 13, 4), - /* 0010 */ V(13, 2, 4), - /* 0011 */ V(1, 13, 4), - /* 0100 */ V(11, 7, 4), - /* 0101 */ PTR(382, 1), - /* 0110 */ PTR(384, 1), - /* 0111 */ V(12, 3, 4), - /* 1000 */ PTR(386, 1), - /* 1001 */ V(4, 11, 4), - /* 1010 */ V(13, 1, 3), - /* 1011 */ V(13, 1, 3), - /* 1100 */ V(0, 13, 4), - /* 1101 */ V(13, 0, 4), - /* 1110 */ V(8, 10, 4), - /* 1111 */ V(10, 8, 4), - - /* 0000 0011 ... */ - /* 0000 */ V(4, 12, 4), /* 116 */ - /* 0001 */ V(12, 4, 4), - /* 0010 */ V(6, 11, 4), - /* 0011 */ V(11, 6, 4), - /* 0100 */ V(3, 12, 3), - /* 0101 */ V(3, 12, 3), - /* 0110 */ V(2, 12, 3), - /* 0111 */ V(2, 12, 3), - /* 1000 */ V(12, 2, 3), - /* 1001 */ V(12, 2, 3), - /* 1010 */ V(5, 11, 3), - /* 1011 */ V(5, 11, 3), - /* 1100 */ V(11, 5, 4), - /* 1101 */ V(8, 9, 4), - /* 1110 */ V(1, 12, 3), - /* 1111 */ V(1, 12, 3), - - /* 0000 0100 ... */ - /* 0000 */ V(12, 1, 3), /* 132 */ - /* 0001 */ V(12, 1, 3), - /* 0010 */ V(9, 8, 4), - /* 0011 */ V(0, 12, 4), - /* 0100 */ V(12, 0, 3), - /* 0101 */ V(12, 0, 3), - /* 0110 */ V(11, 4, 4), - /* 0111 */ V(6, 10, 4), - /* 1000 */ V(10, 6, 4), - /* 1001 */ V(7, 9, 4), - /* 1010 */ V(3, 11, 3), - /* 1011 */ V(3, 11, 3), - /* 1100 */ V(11, 3, 3), - /* 1101 */ V(11, 3, 3), - /* 1110 */ V(8, 8, 4), - /* 1111 */ V(5, 10, 4), - - /* 0000 0101 ... */ - /* 0000 */ V(2, 11, 3), /* 148 */ - /* 0001 */ V(2, 11, 3), - /* 0010 */ V(10, 5, 4), - /* 0011 */ V(6, 9, 4), - /* 0100 */ V(10, 4, 3), - /* 0101 */ V(10, 4, 3), - /* 0110 */ V(7, 8, 4), - /* 0111 */ V(8, 7, 4), - /* 1000 */ V(9, 4, 3), - /* 1001 */ V(9, 4, 3), - /* 1010 */ V(7, 7, 4), - /* 1011 */ V(7, 6, 4), - /* 1100 */ V(11, 2, 2), - /* 1101 */ V(11, 2, 2), - /* 1110 */ V(11, 2, 2), - /* 1111 */ V(11, 2, 2), - - /* 0000 0110 ... */ - /* 000 */ V(1, 11, 2), /* 164 */ - /* 001 */ V(1, 11, 2), - /* 010 */ V(11, 1, 2), - /* 011 */ V(11, 1, 2), - /* 100 */ V(0, 11, 3), - /* 101 */ V(11, 0, 3), - /* 110 */ V(9, 6, 3), - /* 111 */ V(4, 10, 3), - - /* 0000 0111 ... */ - /* 000 */ V(3, 10, 3), /* 172 */ - /* 001 */ V(10, 3, 3), - /* 010 */ V(5, 9, 3), - /* 011 */ V(9, 5, 3), - /* 100 */ V(2, 10, 2), - /* 101 */ V(2, 10, 2), - /* 110 */ V(10, 2, 2), - /* 111 */ V(10, 2, 2), - - /* 0000 1000 ... */ - /* 000 */ V(1, 10, 2), /* 180 */ - /* 001 */ V(1, 10, 2), - /* 010 */ V(10, 1, 2), - /* 011 */ V(10, 1, 2), - /* 100 */ V(0, 10, 3), - /* 101 */ V(6, 8, 3), - /* 110 */ V(10, 0, 2), - /* 111 */ V(10, 0, 2), - - /* 0000 1001 ... */ - /* 000 */ V(8, 6, 3), /* 188 */ - /* 001 */ V(4, 9, 3), - /* 010 */ V(9, 3, 2), - /* 011 */ V(9, 3, 2), - /* 100 */ V(3, 9, 3), - /* 101 */ V(5, 8, 3), - /* 110 */ V(8, 5, 3), - /* 111 */ V(6, 7, 3), - - /* 0000 1010 ... */ - /* 000 */ V(2, 9, 2), /* 196 */ - /* 001 */ V(2, 9, 2), - /* 010 */ V(9, 2, 2), - /* 011 */ V(9, 2, 2), - /* 100 */ V(5, 7, 3), - /* 101 */ V(7, 5, 3), - /* 110 */ V(3, 8, 2), - /* 111 */ V(3, 8, 2), - - /* 0000 1011 ... */ - /* 000 */ V(8, 3, 2), /* 204 */ - /* 001 */ V(8, 3, 2), - /* 010 */ V(6, 6, 3), - /* 011 */ V(4, 7, 3), - /* 100 */ V(7, 4, 3), - /* 101 */ V(5, 6, 3), - /* 110 */ V(6, 5, 3), - /* 111 */ V(7, 3, 3), - - /* 0000 1100 ... */ - /* 0 */ V(1, 9, 1), /* 212 */ - /* 1 */ V(9, 1, 1), - - /* 0000 1101 ... */ - /* 00 */ V(0, 9, 2), /* 214 */ - /* 01 */ V(9, 0, 2), - /* 10 */ V(4, 8, 2), - /* 11 */ V(8, 4, 2), - - /* 0000 1110 ... */ - /* 000 */ V(7, 2, 2), /* 218 */ - /* 001 */ V(7, 2, 2), - /* 010 */ V(4, 6, 3), - /* 011 */ V(6, 4, 3), - /* 100 */ V(2, 8, 1), - /* 101 */ V(2, 8, 1), - /* 110 */ V(2, 8, 1), - /* 111 */ V(2, 8, 1), - - /* 0000 1111 ... */ - /* 0 */ V(8, 2, 1), /* 226 */ - /* 1 */ V(1, 8, 1), - - /* 0001 0000 ... */ - /* 00 */ V(3, 7, 2), /* 228 */ - /* 01 */ V(2, 7, 2), - /* 10 */ V(1, 7, 1), - /* 11 */ V(1, 7, 1), - - /* 0001 0001 ... */ - /* 00 */ V(7, 1, 1), /* 232 */ - /* 01 */ V(7, 1, 1), - /* 10 */ V(5, 5, 2), - /* 11 */ V(0, 7, 2), - - /* 0001 0010 ... */ - /* 00 */ V(7, 0, 2), /* 236 */ - /* 01 */ V(3, 6, 2), - /* 10 */ V(6, 3, 2), - /* 11 */ V(4, 5, 2), - - /* 0001 0011 ... */ - /* 00 */ V(5, 4, 2), /* 240 */ - /* 01 */ V(2, 6, 2), - /* 10 */ V(6, 2, 2), - /* 11 */ V(3, 5, 2), - - /* 0001 0101 ... */ - /* 0 */ V(0, 8, 1), /* 244 */ - /* 1 */ V(8, 0, 1), - - /* 0001 0110 ... */ - /* 0 */ V(1, 6, 1), /* 246 */ - /* 1 */ V(6, 1, 1), - - /* 0001 0111 ... */ - /* 0 */ V(0, 6, 1), /* 248 */ - /* 1 */ V(6, 0, 1), - - /* 0001 1000 ... */ - /* 00 */ V(5, 3, 2), /* 250 */ - /* 01 */ V(4, 4, 2), - /* 10 */ V(2, 5, 1), - /* 11 */ V(2, 5, 1), - - /* 0001 1001 ... */ - /* 0 */ V(5, 2, 1), /* 254 */ - /* 1 */ V(0, 5, 1), - - /* 0001 1100 ... */ - /* 0 */ V(3, 4, 1), /* 256 */ - /* 1 */ V(4, 3, 1), - - /* 0001 1101 ... */ - /* 0 */ V(5, 0, 1), /* 258 */ - /* 1 */ V(2, 4, 1), - - /* 0001 1110 ... */ - /* 0 */ V(4, 2, 1), /* 260 */ - /* 1 */ V(3, 3, 1), - - /* 0000 0000 0000 ... */ - /* 0000 */ PTR(388, 3), /* 262 */ - /* 0001 */ V(15, 15, 4), - /* 0010 */ V(14, 15, 4), - /* 0011 */ V(13, 15, 4), - /* 0100 */ V(14, 14, 4), - /* 0101 */ V(12, 15, 4), - /* 0110 */ V(13, 14, 4), - /* 0111 */ V(11, 15, 4), - /* 1000 */ V(15, 11, 4), - /* 1001 */ V(12, 14, 4), - /* 1010 */ V(13, 12, 4), - /* 1011 */ PTR(396, 1), - /* 1100 */ V(14, 12, 3), - /* 1101 */ V(14, 12, 3), - /* 1110 */ V(13, 13, 3), - /* 1111 */ V(13, 13, 3), - - /* 0000 0000 0001 ... */ - /* 0000 */ V(15, 10, 4), /* 278 */ - /* 0001 */ V(12, 13, 4), - /* 0010 */ V(11, 14, 3), - /* 0011 */ V(11, 14, 3), - /* 0100 */ V(14, 11, 3), - /* 0101 */ V(14, 11, 3), - /* 0110 */ V(9, 15, 3), - /* 0111 */ V(9, 15, 3), - /* 1000 */ V(15, 9, 3), - /* 1001 */ V(15, 9, 3), - /* 1010 */ V(14, 10, 3), - /* 1011 */ V(14, 10, 3), - /* 1100 */ V(11, 13, 3), - /* 1101 */ V(11, 13, 3), - /* 1110 */ V(13, 11, 3), - /* 1111 */ V(13, 11, 3), - - /* 0000 0000 0010 ... */ - /* 0000 */ V(8, 15, 3), /* 294 */ - /* 0001 */ V(8, 15, 3), - /* 0010 */ V(15, 8, 3), - /* 0011 */ V(15, 8, 3), - /* 0100 */ V(12, 12, 3), - /* 0101 */ V(12, 12, 3), - /* 0110 */ V(10, 14, 4), - /* 0111 */ V(9, 14, 4), - /* 1000 */ V(8, 14, 3), - /* 1001 */ V(8, 14, 3), - /* 1010 */ V(7, 15, 4), - /* 1011 */ V(7, 14, 4), - /* 1100 */ V(15, 7, 2), - /* 1101 */ V(15, 7, 2), - /* 1110 */ V(15, 7, 2), - /* 1111 */ V(15, 7, 2), - - /* 0000 0000 0011 ... */ - /* 000 */ V(13, 10, 2), /* 310 */ - /* 001 */ V(13, 10, 2), - /* 010 */ V(10, 13, 3), - /* 011 */ V(11, 12, 3), - /* 100 */ V(12, 11, 3), - /* 101 */ V(15, 6, 3), - /* 110 */ V(6, 15, 2), - /* 111 */ V(6, 15, 2), - - /* 0000 0000 0100 ... */ - /* 00 */ V(14, 8, 2), /* 318 */ - /* 01 */ V(5, 15, 2), - /* 10 */ V(9, 13, 2), - /* 11 */ V(13, 9, 2), - - /* 0000 0000 0101 ... */ - /* 00 */ V(15, 5, 2), /* 322 */ - /* 01 */ V(14, 7, 2), - /* 10 */ V(10, 12, 2), - /* 11 */ V(11, 11, 2), - - /* 0000 0000 0110 ... */ - /* 000 */ V(4, 15, 2), /* 326 */ - /* 001 */ V(4, 15, 2), - /* 010 */ V(15, 4, 2), - /* 011 */ V(15, 4, 2), - /* 100 */ V(12, 10, 3), - /* 101 */ V(14, 6, 3), - /* 110 */ V(15, 3, 2), - /* 111 */ V(15, 3, 2), - - /* 0000 0000 0111 ... */ - /* 00 */ V(3, 15, 1), /* 334 */ - /* 01 */ V(3, 15, 1), - /* 10 */ V(8, 13, 2), - /* 11 */ V(13, 8, 2), - - /* 0000 0000 1000 ... */ - /* 0 */ V(2, 15, 1), /* 338 */ - /* 1 */ V(15, 2, 1), - - /* 0000 0000 1001 ... */ - /* 00 */ V(6, 14, 2), /* 340 */ - /* 01 */ V(9, 12, 2), - /* 10 */ V(0, 15, 1), - /* 11 */ V(0, 15, 1), - - /* 0000 0000 1010 ... */ - /* 00 */ V(12, 9, 2), /* 344 */ - /* 01 */ V(5, 14, 2), - /* 10 */ V(10, 11, 1), - /* 11 */ V(10, 11, 1), - - /* 0000 0000 1011 ... */ - /* 00 */ V(7, 13, 2), /* 348 */ - /* 01 */ V(13, 7, 2), - /* 10 */ V(4, 14, 1), - /* 11 */ V(4, 14, 1), - - /* 0000 0000 1100 ... */ - /* 00 */ V(12, 8, 2), /* 352 */ - /* 01 */ V(13, 6, 2), - /* 10 */ V(3, 14, 1), - /* 11 */ V(3, 14, 1), - - /* 0000 0000 1101 ... */ - /* 00 */ V(11, 9, 1), /* 356 */ - /* 01 */ V(11, 9, 1), - /* 10 */ V(9, 11, 2), - /* 11 */ V(10, 10, 2), - - /* 0000 0001 0001 ... */ - /* 0 */ V(11, 10, 1), /* 360 */ - /* 1 */ V(14, 5, 1), - - /* 0000 0001 0010 ... */ - /* 0 */ V(14, 4, 1), /* 362 */ - /* 1 */ V(8, 12, 1), - - /* 0000 0001 0011 ... */ - /* 0 */ V(6, 13, 1), /* 364 */ - /* 1 */ V(14, 3, 1), - - /* 0000 0001 0101 ... */ - /* 0 */ V(2, 14, 1), /* 366 */ - /* 1 */ V(0, 14, 1), - - /* 0000 0001 1000 ... */ - /* 0 */ V(14, 0, 1), /* 368 */ - /* 1 */ V(5, 13, 1), - - /* 0000 0001 1001 ... */ - /* 0 */ V(13, 5, 1), /* 370 */ - /* 1 */ V(7, 12, 1), - - /* 0000 0001 1010 ... */ - /* 0 */ V(12, 7, 1), /* 372 */ - /* 1 */ V(4, 13, 1), - - /* 0000 0001 1011 ... */ - /* 0 */ V(8, 11, 1), /* 374 */ - /* 1 */ V(11, 8, 1), - - /* 0000 0001 1100 ... */ - /* 0 */ V(13, 4, 1), /* 376 */ - /* 1 */ V(9, 10, 1), - - /* 0000 0001 1101 ... */ - /* 0 */ V(10, 9, 1), /* 378 */ - /* 1 */ V(6, 12, 1), - - /* 0000 0010 0000 ... */ - /* 0 */ V(13, 3, 1), /* 380 */ - /* 1 */ V(7, 11, 1), - - /* 0000 0010 0101 ... */ - /* 0 */ V(5, 12, 1), /* 382 */ - /* 1 */ V(12, 5, 1), - - /* 0000 0010 0110 ... */ - /* 0 */ V(9, 9, 1), /* 384 */ - /* 1 */ V(7, 10, 1), - - /* 0000 0010 1000 ... */ - /* 0 */ V(10, 7, 1), /* 386 */ - /* 1 */ V(9, 7, 1), - - /* 0000 0000 0000 0000 ... */ - /* 000 */ V(15, 14, 3), /* 388 */ - /* 001 */ V(15, 12, 3), - /* 010 */ V(15, 13, 2), - /* 011 */ V(15, 13, 2), - /* 100 */ V(14, 13, 1), - /* 101 */ V(14, 13, 1), - /* 110 */ V(14, 13, 1), - /* 111 */ V(14, 13, 1), - - /* 0000 0000 0000 1011 ... */ - /* 0 */ V(10, 15, 1), /* 396 */ - /* 1 */ V(14, 9, 1) -}; - -static -union huffpair const hufftab15[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ PTR(48, 4), - /* 0011 */ PTR(64, 4), - /* 0100 */ PTR(80, 4), - /* 0101 */ PTR(96, 3), - /* 0110 */ PTR(104, 3), - /* 0111 */ PTR(112, 2), - /* 1000 */ PTR(116, 1), - /* 1001 */ PTR(118, 1), - /* 1010 */ V(1, 1, 3), - /* 1011 */ V(1, 1, 3), - /* 1100 */ V(0, 1, 4), - /* 1101 */ V(1, 0, 4), - /* 1110 */ V(0, 0, 3), - /* 1111 */ V(0, 0, 3), - - /* 0000 ... */ - /* 0000 */ PTR(120, 4), /* 16 */ - /* 0001 */ PTR(136, 4), - /* 0010 */ PTR(152, 4), - /* 0011 */ PTR(168, 4), - /* 0100 */ PTR(184, 4), - /* 0101 */ PTR(200, 3), - /* 0110 */ PTR(208, 3), - /* 0111 */ PTR(216, 4), - /* 1000 */ PTR(232, 3), - /* 1001 */ PTR(240, 3), - /* 1010 */ PTR(248, 3), - /* 1011 */ PTR(256, 3), - /* 1100 */ PTR(264, 2), - /* 1101 */ PTR(268, 3), - /* 1110 */ PTR(276, 3), - /* 1111 */ PTR(284, 2), - - /* 0001 ... */ - /* 0000 */ PTR(288, 2), /* 32 */ - /* 0001 */ PTR(292, 2), - /* 0010 */ PTR(296, 2), - /* 0011 */ PTR(300, 2), - /* 0100 */ PTR(304, 2), - /* 0101 */ PTR(308, 2), - /* 0110 */ PTR(312, 2), - /* 0111 */ PTR(316, 2), - /* 1000 */ PTR(320, 1), - /* 1001 */ PTR(322, 1), - /* 1010 */ PTR(324, 1), - /* 1011 */ PTR(326, 2), - /* 1100 */ PTR(330, 1), - /* 1101 */ PTR(332, 1), - /* 1110 */ PTR(334, 2), - /* 1111 */ PTR(338, 1), - - /* 0010 ... */ - /* 0000 */ PTR(340, 1), /* 48 */ - /* 0001 */ PTR(342, 1), - /* 0010 */ V(9, 1, 4), - /* 0011 */ PTR(344, 1), - /* 0100 */ PTR(346, 1), - /* 0101 */ PTR(348, 1), - /* 0110 */ PTR(350, 1), - /* 0111 */ PTR(352, 1), - /* 1000 */ V(2, 8, 4), - /* 1001 */ V(8, 2, 4), - /* 1010 */ V(1, 8, 4), - /* 1011 */ V(8, 1, 4), - /* 1100 */ PTR(354, 1), - /* 1101 */ PTR(356, 1), - /* 1110 */ PTR(358, 1), - /* 1111 */ PTR(360, 1), - - /* 0011 ... */ - /* 0000 */ V(2, 7, 4), /* 64 */ - /* 0001 */ V(7, 2, 4), - /* 0010 */ V(6, 4, 4), - /* 0011 */ V(1, 7, 4), - /* 0100 */ V(5, 5, 4), - /* 0101 */ V(7, 1, 4), - /* 0110 */ PTR(362, 1), - /* 0111 */ V(3, 6, 4), - /* 1000 */ V(6, 3, 4), - /* 1001 */ V(4, 5, 4), - /* 1010 */ V(5, 4, 4), - /* 1011 */ V(2, 6, 4), - /* 1100 */ V(6, 2, 4), - /* 1101 */ V(1, 6, 4), - /* 1110 */ PTR(364, 1), - /* 1111 */ V(3, 5, 4), - - /* 0100 ... */ - /* 0000 */ V(6, 1, 3), /* 80 */ - /* 0001 */ V(6, 1, 3), - /* 0010 */ V(5, 3, 4), - /* 0011 */ V(4, 4, 4), - /* 0100 */ V(2, 5, 3), - /* 0101 */ V(2, 5, 3), - /* 0110 */ V(5, 2, 3), - /* 0111 */ V(5, 2, 3), - /* 1000 */ V(1, 5, 3), - /* 1001 */ V(1, 5, 3), - /* 1010 */ V(5, 1, 3), - /* 1011 */ V(5, 1, 3), - /* 1100 */ V(0, 5, 4), - /* 1101 */ V(5, 0, 4), - /* 1110 */ V(3, 4, 3), - /* 1111 */ V(3, 4, 3), - - /* 0101 ... */ - /* 000 */ V(4, 3, 3), /* 96 */ - /* 001 */ V(2, 4, 3), - /* 010 */ V(4, 2, 3), - /* 011 */ V(3, 3, 3), - /* 100 */ V(4, 1, 2), - /* 101 */ V(4, 1, 2), - /* 110 */ V(1, 4, 3), - /* 111 */ V(0, 4, 3), - - /* 0110 ... */ - /* 000 */ V(2, 3, 2), /* 104 */ - /* 001 */ V(2, 3, 2), - /* 010 */ V(3, 2, 2), - /* 011 */ V(3, 2, 2), - /* 100 */ V(4, 0, 3), - /* 101 */ V(0, 3, 3), - /* 110 */ V(1, 3, 2), - /* 111 */ V(1, 3, 2), - - /* 0111 ... */ - /* 00 */ V(3, 1, 2), /* 112 */ - /* 01 */ V(3, 0, 2), - /* 10 */ V(2, 2, 1), - /* 11 */ V(2, 2, 1), - - /* 1000 ... */ - /* 0 */ V(1, 2, 1), /* 116 */ - /* 1 */ V(2, 1, 1), - - /* 1001 ... */ - /* 0 */ V(0, 2, 1), /* 118 */ - /* 1 */ V(2, 0, 1), - - /* 0000 0000 ... */ - /* 0000 */ PTR(366, 1), /* 120 */ - /* 0001 */ PTR(368, 1), - /* 0010 */ V(14, 14, 4), - /* 0011 */ PTR(370, 1), - /* 0100 */ PTR(372, 1), - /* 0101 */ PTR(374, 1), - /* 0110 */ V(15, 11, 4), - /* 0111 */ PTR(376, 1), - /* 1000 */ V(13, 13, 4), - /* 1001 */ V(10, 15, 4), - /* 1010 */ V(15, 10, 4), - /* 1011 */ V(11, 14, 4), - /* 1100 */ V(14, 11, 4), - /* 1101 */ V(12, 13, 4), - /* 1110 */ V(13, 12, 4), - /* 1111 */ V(9, 15, 4), - - /* 0000 0001 ... */ - /* 0000 */ V(15, 9, 4), /* 136 */ - /* 0001 */ V(14, 10, 4), - /* 0010 */ V(11, 13, 4), - /* 0011 */ V(13, 11, 4), - /* 0100 */ V(8, 15, 4), - /* 0101 */ V(15, 8, 4), - /* 0110 */ V(12, 12, 4), - /* 0111 */ V(9, 14, 4), - /* 1000 */ V(14, 9, 4), - /* 1001 */ V(7, 15, 4), - /* 1010 */ V(15, 7, 4), - /* 1011 */ V(10, 13, 4), - /* 1100 */ V(13, 10, 4), - /* 1101 */ V(11, 12, 4), - /* 1110 */ V(6, 15, 4), - /* 1111 */ PTR(378, 1), - - /* 0000 0010 ... */ - /* 0000 */ V(12, 11, 3), /* 152 */ - /* 0001 */ V(12, 11, 3), - /* 0010 */ V(15, 6, 3), - /* 0011 */ V(15, 6, 3), - /* 0100 */ V(8, 14, 4), - /* 0101 */ V(14, 8, 4), - /* 0110 */ V(5, 15, 4), - /* 0111 */ V(9, 13, 4), - /* 1000 */ V(15, 5, 3), - /* 1001 */ V(15, 5, 3), - /* 1010 */ V(7, 14, 3), - /* 1011 */ V(7, 14, 3), - /* 1100 */ V(14, 7, 3), - /* 1101 */ V(14, 7, 3), - /* 1110 */ V(10, 12, 3), - /* 1111 */ V(10, 12, 3), - - /* 0000 0011 ... */ - /* 0000 */ V(12, 10, 3), /* 168 */ - /* 0001 */ V(12, 10, 3), - /* 0010 */ V(11, 11, 3), - /* 0011 */ V(11, 11, 3), - /* 0100 */ V(13, 9, 4), - /* 0101 */ V(8, 13, 4), - /* 0110 */ V(4, 15, 3), - /* 0111 */ V(4, 15, 3), - /* 1000 */ V(15, 4, 3), - /* 1001 */ V(15, 4, 3), - /* 1010 */ V(3, 15, 3), - /* 1011 */ V(3, 15, 3), - /* 1100 */ V(15, 3, 3), - /* 1101 */ V(15, 3, 3), - /* 1110 */ V(13, 8, 3), - /* 1111 */ V(13, 8, 3), - - /* 0000 0100 ... */ - /* 0000 */ V(14, 6, 3), /* 184 */ - /* 0001 */ V(14, 6, 3), - /* 0010 */ V(2, 15, 3), - /* 0011 */ V(2, 15, 3), - /* 0100 */ V(15, 2, 3), - /* 0101 */ V(15, 2, 3), - /* 0110 */ V(6, 14, 4), - /* 0111 */ V(15, 0, 4), - /* 1000 */ V(1, 15, 3), - /* 1001 */ V(1, 15, 3), - /* 1010 */ V(15, 1, 3), - /* 1011 */ V(15, 1, 3), - /* 1100 */ V(9, 12, 3), - /* 1101 */ V(9, 12, 3), - /* 1110 */ V(12, 9, 3), - /* 1111 */ V(12, 9, 3), - - /* 0000 0101 ... */ - /* 000 */ V(5, 14, 3), /* 200 */ - /* 001 */ V(10, 11, 3), - /* 010 */ V(11, 10, 3), - /* 011 */ V(14, 5, 3), - /* 100 */ V(7, 13, 3), - /* 101 */ V(13, 7, 3), - /* 110 */ V(4, 14, 3), - /* 111 */ V(14, 4, 3), - - /* 0000 0110 ... */ - /* 000 */ V(8, 12, 3), /* 208 */ - /* 001 */ V(12, 8, 3), - /* 010 */ V(3, 14, 3), - /* 011 */ V(6, 13, 3), - /* 100 */ V(13, 6, 3), - /* 101 */ V(14, 3, 3), - /* 110 */ V(9, 11, 3), - /* 111 */ V(11, 9, 3), - - /* 0000 0111 ... */ - /* 0000 */ V(2, 14, 3), /* 216 */ - /* 0001 */ V(2, 14, 3), - /* 0010 */ V(10, 10, 3), - /* 0011 */ V(10, 10, 3), - /* 0100 */ V(14, 2, 3), - /* 0101 */ V(14, 2, 3), - /* 0110 */ V(1, 14, 3), - /* 0111 */ V(1, 14, 3), - /* 1000 */ V(14, 1, 3), - /* 1001 */ V(14, 1, 3), - /* 1010 */ V(0, 14, 4), - /* 1011 */ V(14, 0, 4), - /* 1100 */ V(5, 13, 3), - /* 1101 */ V(5, 13, 3), - /* 1110 */ V(13, 5, 3), - /* 1111 */ V(13, 5, 3), - - /* 0000 1000 ... */ - /* 000 */ V(7, 12, 3), /* 232 */ - /* 001 */ V(12, 7, 3), - /* 010 */ V(4, 13, 3), - /* 011 */ V(8, 11, 3), - /* 100 */ V(13, 4, 2), - /* 101 */ V(13, 4, 2), - /* 110 */ V(11, 8, 3), - /* 111 */ V(9, 10, 3), - - /* 0000 1001 ... */ - /* 000 */ V(10, 9, 3), /* 240 */ - /* 001 */ V(6, 12, 3), - /* 010 */ V(12, 6, 3), - /* 011 */ V(3, 13, 3), - /* 100 */ V(13, 3, 2), - /* 101 */ V(13, 3, 2), - /* 110 */ V(13, 2, 2), - /* 111 */ V(13, 2, 2), - - /* 0000 1010 ... */ - /* 000 */ V(2, 13, 3), /* 248 */ - /* 001 */ V(0, 13, 3), - /* 010 */ V(1, 13, 2), - /* 011 */ V(1, 13, 2), - /* 100 */ V(7, 11, 2), - /* 101 */ V(7, 11, 2), - /* 110 */ V(11, 7, 2), - /* 111 */ V(11, 7, 2), - - /* 0000 1011 ... */ - /* 000 */ V(13, 1, 2), /* 256 */ - /* 001 */ V(13, 1, 2), - /* 010 */ V(5, 12, 3), - /* 011 */ V(13, 0, 3), - /* 100 */ V(12, 5, 2), - /* 101 */ V(12, 5, 2), - /* 110 */ V(8, 10, 2), - /* 111 */ V(8, 10, 2), - - /* 0000 1100 ... */ - /* 00 */ V(10, 8, 2), /* 264 */ - /* 01 */ V(4, 12, 2), - /* 10 */ V(12, 4, 2), - /* 11 */ V(6, 11, 2), - - /* 0000 1101 ... */ - /* 000 */ V(11, 6, 2), /* 268 */ - /* 001 */ V(11, 6, 2), - /* 010 */ V(9, 9, 3), - /* 011 */ V(0, 12, 3), - /* 100 */ V(3, 12, 2), - /* 101 */ V(3, 12, 2), - /* 110 */ V(12, 3, 2), - /* 111 */ V(12, 3, 2), - - /* 0000 1110 ... */ - /* 000 */ V(7, 10, 2), /* 276 */ - /* 001 */ V(7, 10, 2), - /* 010 */ V(10, 7, 2), - /* 011 */ V(10, 7, 2), - /* 100 */ V(10, 6, 2), - /* 101 */ V(10, 6, 2), - /* 110 */ V(12, 0, 3), - /* 111 */ V(0, 11, 3), - - /* 0000 1111 ... */ - /* 00 */ V(12, 2, 1), /* 284 */ - /* 01 */ V(12, 2, 1), - /* 10 */ V(2, 12, 2), - /* 11 */ V(5, 11, 2), - - /* 0001 0000 ... */ - /* 00 */ V(11, 5, 2), /* 288 */ - /* 01 */ V(1, 12, 2), - /* 10 */ V(8, 9, 2), - /* 11 */ V(9, 8, 2), - - /* 0001 0001 ... */ - /* 00 */ V(12, 1, 2), /* 292 */ - /* 01 */ V(4, 11, 2), - /* 10 */ V(11, 4, 2), - /* 11 */ V(6, 10, 2), - - /* 0001 0010 ... */ - /* 00 */ V(3, 11, 2), /* 296 */ - /* 01 */ V(7, 9, 2), - /* 10 */ V(11, 3, 1), - /* 11 */ V(11, 3, 1), - - /* 0001 0011 ... */ - /* 00 */ V(9, 7, 2), /* 300 */ - /* 01 */ V(8, 8, 2), - /* 10 */ V(2, 11, 2), - /* 11 */ V(5, 10, 2), - - /* 0001 0100 ... */ - /* 00 */ V(11, 2, 1), /* 304 */ - /* 01 */ V(11, 2, 1), - /* 10 */ V(10, 5, 2), - /* 11 */ V(1, 11, 2), - - /* 0001 0101 ... */ - /* 00 */ V(11, 1, 1), /* 308 */ - /* 01 */ V(11, 1, 1), - /* 10 */ V(11, 0, 2), - /* 11 */ V(6, 9, 2), - - /* 0001 0110 ... */ - /* 00 */ V(9, 6, 2), /* 312 */ - /* 01 */ V(4, 10, 2), - /* 10 */ V(10, 4, 2), - /* 11 */ V(7, 8, 2), - - /* 0001 0111 ... */ - /* 00 */ V(8, 7, 2), /* 316 */ - /* 01 */ V(3, 10, 2), - /* 10 */ V(10, 3, 1), - /* 11 */ V(10, 3, 1), - - /* 0001 1000 ... */ - /* 0 */ V(5, 9, 1), /* 320 */ - /* 1 */ V(9, 5, 1), - - /* 0001 1001 ... */ - /* 0 */ V(2, 10, 1), /* 322 */ - /* 1 */ V(10, 2, 1), - - /* 0001 1010 ... */ - /* 0 */ V(1, 10, 1), /* 324 */ - /* 1 */ V(10, 1, 1), - - /* 0001 1011 ... */ - /* 00 */ V(0, 10, 2), /* 326 */ - /* 01 */ V(10, 0, 2), - /* 10 */ V(6, 8, 1), - /* 11 */ V(6, 8, 1), - - /* 0001 1100 ... */ - /* 0 */ V(8, 6, 1), /* 330 */ - /* 1 */ V(4, 9, 1), - - /* 0001 1101 ... */ - /* 0 */ V(9, 4, 1), /* 332 */ - /* 1 */ V(3, 9, 1), - - /* 0001 1110 ... */ - /* 00 */ V(9, 3, 1), /* 334 */ - /* 01 */ V(9, 3, 1), - /* 10 */ V(7, 7, 2), - /* 11 */ V(0, 9, 2), - - /* 0001 1111 ... */ - /* 0 */ V(5, 8, 1), /* 338 */ - /* 1 */ V(8, 5, 1), - - /* 0010 0000 ... */ - /* 0 */ V(2, 9, 1), /* 340 */ - /* 1 */ V(6, 7, 1), - - /* 0010 0001 ... */ - /* 0 */ V(7, 6, 1), /* 342 */ - /* 1 */ V(9, 2, 1), - - /* 0010 0011 ... */ - /* 0 */ V(1, 9, 1), /* 344 */ - /* 1 */ V(9, 0, 1), - - /* 0010 0100 ... */ - /* 0 */ V(4, 8, 1), /* 346 */ - /* 1 */ V(8, 4, 1), - - /* 0010 0101 ... */ - /* 0 */ V(5, 7, 1), /* 348 */ - /* 1 */ V(7, 5, 1), - - /* 0010 0110 ... */ - /* 0 */ V(3, 8, 1), /* 350 */ - /* 1 */ V(8, 3, 1), - - /* 0010 0111 ... */ - /* 0 */ V(6, 6, 1), /* 352 */ - /* 1 */ V(4, 7, 1), - - /* 0010 1100 ... */ - /* 0 */ V(7, 4, 1), /* 354 */ - /* 1 */ V(0, 8, 1), - - /* 0010 1101 ... */ - /* 0 */ V(8, 0, 1), /* 356 */ - /* 1 */ V(5, 6, 1), - - /* 0010 1110 ... */ - /* 0 */ V(6, 5, 1), /* 358 */ - /* 1 */ V(3, 7, 1), - - /* 0010 1111 ... */ - /* 0 */ V(7, 3, 1), /* 360 */ - /* 1 */ V(4, 6, 1), - - /* 0011 0110 ... */ - /* 0 */ V(0, 7, 1), /* 362 */ - /* 1 */ V(7, 0, 1), - - /* 0011 1110 ... */ - /* 0 */ V(0, 6, 1), /* 364 */ - /* 1 */ V(6, 0, 1), - - /* 0000 0000 0000 ... */ - /* 0 */ V(15, 15, 1), /* 366 */ - /* 1 */ V(14, 15, 1), - - /* 0000 0000 0001 ... */ - /* 0 */ V(15, 14, 1), /* 368 */ - /* 1 */ V(13, 15, 1), - - /* 0000 0000 0011 ... */ - /* 0 */ V(15, 13, 1), /* 370 */ - /* 1 */ V(12, 15, 1), - - /* 0000 0000 0100 ... */ - /* 0 */ V(15, 12, 1), /* 372 */ - /* 1 */ V(13, 14, 1), - - /* 0000 0000 0101 ... */ - /* 0 */ V(14, 13, 1), /* 374 */ - /* 1 */ V(11, 15, 1), - - /* 0000 0000 0111 ... */ - /* 0 */ V(12, 14, 1), /* 376 */ - /* 1 */ V(14, 12, 1), - - /* 0000 0001 1111 ... */ - /* 0 */ V(10, 14, 1), /* 378 */ - /* 1 */ V(0, 15, 1) -}; - -static -union huffpair const hufftab16[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ PTR(48, 4), - /* 0011 */ PTR(64, 2), - /* 0100 */ V(1, 1, 4), - /* 0101 */ V(0, 1, 4), - /* 0110 */ V(1, 0, 3), - /* 0111 */ V(1, 0, 3), - /* 1000 */ V(0, 0, 1), - /* 1001 */ V(0, 0, 1), - /* 1010 */ V(0, 0, 1), - /* 1011 */ V(0, 0, 1), - /* 1100 */ V(0, 0, 1), - /* 1101 */ V(0, 0, 1), - /* 1110 */ V(0, 0, 1), - /* 1111 */ V(0, 0, 1), - - /* 0000 ... */ - /* 0000 */ PTR(68, 3), /* 16 */ - /* 0001 */ PTR(76, 3), - /* 0010 */ PTR(84, 2), - /* 0011 */ V(15, 15, 4), - /* 0100 */ PTR(88, 2), - /* 0101 */ PTR(92, 1), - /* 0110 */ PTR(94, 4), - /* 0111 */ V(15, 2, 4), - /* 1000 */ PTR(110, 1), - /* 1001 */ V(1, 15, 4), - /* 1010 */ V(15, 1, 4), - /* 1011 */ PTR(112, 4), - /* 1100 */ PTR(128, 4), - /* 1101 */ PTR(144, 4), - /* 1110 */ PTR(160, 4), - /* 1111 */ PTR(176, 4), - - /* 0001 ... */ - /* 0000 */ PTR(192, 4), /* 32 */ - /* 0001 */ PTR(208, 3), - /* 0010 */ PTR(216, 3), - /* 0011 */ PTR(224, 3), - /* 0100 */ PTR(232, 3), - /* 0101 */ PTR(240, 3), - /* 0110 */ PTR(248, 3), - /* 0111 */ PTR(256, 3), - /* 1000 */ PTR(264, 2), - /* 1001 */ PTR(268, 2), - /* 1010 */ PTR(272, 1), - /* 1011 */ PTR(274, 2), - /* 1100 */ PTR(278, 2), - /* 1101 */ PTR(282, 1), - /* 1110 */ V(5, 1, 4), - /* 1111 */ PTR(284, 1), - - /* 0010 ... */ - /* 0000 */ PTR(286, 1), /* 48 */ - /* 0001 */ PTR(288, 1), - /* 0010 */ PTR(290, 1), - /* 0011 */ V(1, 4, 4), - /* 0100 */ V(4, 1, 4), - /* 0101 */ PTR(292, 1), - /* 0110 */ V(2, 3, 4), - /* 0111 */ V(3, 2, 4), - /* 1000 */ V(1, 3, 3), - /* 1001 */ V(1, 3, 3), - /* 1010 */ V(3, 1, 3), - /* 1011 */ V(3, 1, 3), - /* 1100 */ V(0, 3, 4), - /* 1101 */ V(3, 0, 4), - /* 1110 */ V(2, 2, 3), - /* 1111 */ V(2, 2, 3), - - /* 0011 ... */ - /* 00 */ V(1, 2, 2), /* 64 */ - /* 01 */ V(2, 1, 2), - /* 10 */ V(0, 2, 2), - /* 11 */ V(2, 0, 2), - - /* 0000 0000 ... */ - /* 000 */ V(14, 15, 3), /* 68 */ - /* 001 */ V(15, 14, 3), - /* 010 */ V(13, 15, 3), - /* 011 */ V(15, 13, 3), - /* 100 */ V(12, 15, 3), - /* 101 */ V(15, 12, 3), - /* 110 */ V(11, 15, 3), - /* 111 */ V(15, 11, 3), - - /* 0000 0001 ... */ - /* 000 */ V(10, 15, 2), /* 76 */ - /* 001 */ V(10, 15, 2), - /* 010 */ V(15, 10, 3), - /* 011 */ V(9, 15, 3), - /* 100 */ V(15, 9, 3), - /* 101 */ V(15, 8, 3), - /* 110 */ V(8, 15, 2), - /* 111 */ V(8, 15, 2), - - /* 0000 0010 ... */ - /* 00 */ V(7, 15, 2), /* 84 */ - /* 01 */ V(15, 7, 2), - /* 10 */ V(6, 15, 2), - /* 11 */ V(15, 6, 2), - - /* 0000 0100 ... */ - /* 00 */ V(5, 15, 2), /* 88 */ - /* 01 */ V(15, 5, 2), - /* 10 */ V(4, 15, 1), - /* 11 */ V(4, 15, 1), - - /* 0000 0101 ... */ - /* 0 */ V(15, 4, 1), /* 92 */ - /* 1 */ V(15, 3, 1), - - /* 0000 0110 ... */ - /* 0000 */ V(15, 0, 1), /* 94 */ - /* 0001 */ V(15, 0, 1), - /* 0010 */ V(15, 0, 1), - /* 0011 */ V(15, 0, 1), - /* 0100 */ V(15, 0, 1), - /* 0101 */ V(15, 0, 1), - /* 0110 */ V(15, 0, 1), - /* 0111 */ V(15, 0, 1), - /* 1000 */ V(3, 15, 2), - /* 1001 */ V(3, 15, 2), - /* 1010 */ V(3, 15, 2), - /* 1011 */ V(3, 15, 2), - /* 1100 */ PTR(294, 4), - /* 1101 */ PTR(310, 3), - /* 1110 */ PTR(318, 3), - /* 1111 */ PTR(326, 3), - - /* 0000 1000 ... */ - /* 0 */ V(2, 15, 1), /* 110 */ - /* 1 */ V(0, 15, 1), - - /* 0000 1011 ... */ - /* 0000 */ PTR(334, 2), /* 112 */ - /* 0001 */ PTR(338, 2), - /* 0010 */ PTR(342, 2), - /* 0011 */ PTR(346, 1), - /* 0100 */ PTR(348, 2), - /* 0101 */ PTR(352, 2), - /* 0110 */ PTR(356, 1), - /* 0111 */ PTR(358, 2), - /* 1000 */ PTR(362, 2), - /* 1001 */ PTR(366, 2), - /* 1010 */ PTR(370, 2), - /* 1011 */ V(14, 3, 4), - /* 1100 */ PTR(374, 1), - /* 1101 */ PTR(376, 1), - /* 1110 */ PTR(378, 1), - /* 1111 */ PTR(380, 1), - - /* 0000 1100 ... */ - /* 0000 */ PTR(382, 1), /* 128 */ - /* 0001 */ PTR(384, 1), - /* 0010 */ PTR(386, 1), - /* 0011 */ V(0, 13, 4), - /* 0100 */ PTR(388, 1), - /* 0101 */ PTR(390, 1), - /* 0110 */ PTR(392, 1), - /* 0111 */ V(3, 12, 4), - /* 1000 */ PTR(394, 1), - /* 1001 */ V(1, 12, 4), - /* 1010 */ V(12, 0, 4), - /* 1011 */ PTR(396, 1), - /* 1100 */ V(14, 2, 3), - /* 1101 */ V(14, 2, 3), - /* 1110 */ V(2, 14, 4), - /* 1111 */ V(1, 14, 4), - - /* 0000 1101 ... */ - /* 0000 */ V(13, 3, 4), /* 144 */ - /* 0001 */ V(2, 13, 4), - /* 0010 */ V(13, 2, 4), - /* 0011 */ V(13, 1, 4), - /* 0100 */ V(3, 11, 4), - /* 0101 */ PTR(398, 1), - /* 0110 */ V(1, 13, 3), - /* 0111 */ V(1, 13, 3), - /* 1000 */ V(12, 4, 4), - /* 1001 */ V(6, 11, 4), - /* 1010 */ V(12, 3, 4), - /* 1011 */ V(10, 7, 4), - /* 1100 */ V(2, 12, 3), - /* 1101 */ V(2, 12, 3), - /* 1110 */ V(12, 2, 4), - /* 1111 */ V(11, 5, 4), - - /* 0000 1110 ... */ - /* 0000 */ V(12, 1, 4), /* 160 */ - /* 0001 */ V(0, 12, 4), - /* 0010 */ V(4, 11, 4), - /* 0011 */ V(11, 4, 4), - /* 0100 */ V(6, 10, 4), - /* 0101 */ V(10, 6, 4), - /* 0110 */ V(11, 3, 3), - /* 0111 */ V(11, 3, 3), - /* 1000 */ V(5, 10, 4), - /* 1001 */ V(10, 5, 4), - /* 1010 */ V(2, 11, 3), - /* 1011 */ V(2, 11, 3), - /* 1100 */ V(11, 2, 3), - /* 1101 */ V(11, 2, 3), - /* 1110 */ V(1, 11, 3), - /* 1111 */ V(1, 11, 3), - - /* 0000 1111 ... */ - /* 0000 */ V(11, 1, 3), /* 176 */ - /* 0001 */ V(11, 1, 3), - /* 0010 */ V(0, 11, 4), - /* 0011 */ V(11, 0, 4), - /* 0100 */ V(6, 9, 4), - /* 0101 */ V(9, 6, 4), - /* 0110 */ V(4, 10, 4), - /* 0111 */ V(10, 4, 4), - /* 1000 */ V(7, 8, 4), - /* 1001 */ V(8, 7, 4), - /* 1010 */ V(10, 3, 3), - /* 1011 */ V(10, 3, 3), - /* 1100 */ V(3, 10, 4), - /* 1101 */ V(5, 9, 4), - /* 1110 */ V(2, 10, 3), - /* 1111 */ V(2, 10, 3), - - /* 0001 0000 ... */ - /* 0000 */ V(9, 5, 4), /* 192 */ - /* 0001 */ V(6, 8, 4), - /* 0010 */ V(10, 1, 3), - /* 0011 */ V(10, 1, 3), - /* 0100 */ V(8, 6, 4), - /* 0101 */ V(7, 7, 4), - /* 0110 */ V(9, 4, 3), - /* 0111 */ V(9, 4, 3), - /* 1000 */ V(4, 9, 4), - /* 1001 */ V(5, 7, 4), - /* 1010 */ V(6, 7, 3), - /* 1011 */ V(6, 7, 3), - /* 1100 */ V(10, 2, 2), - /* 1101 */ V(10, 2, 2), - /* 1110 */ V(10, 2, 2), - /* 1111 */ V(10, 2, 2), - - /* 0001 0001 ... */ - /* 000 */ V(1, 10, 2), /* 208 */ - /* 001 */ V(1, 10, 2), - /* 010 */ V(0, 10, 3), - /* 011 */ V(10, 0, 3), - /* 100 */ V(3, 9, 3), - /* 101 */ V(9, 3, 3), - /* 110 */ V(5, 8, 3), - /* 111 */ V(8, 5, 3), - - /* 0001 0010 ... */ - /* 000 */ V(2, 9, 2), /* 216 */ - /* 001 */ V(2, 9, 2), - /* 010 */ V(9, 2, 2), - /* 011 */ V(9, 2, 2), - /* 100 */ V(7, 6, 3), - /* 101 */ V(0, 9, 3), - /* 110 */ V(1, 9, 2), - /* 111 */ V(1, 9, 2), - - /* 0001 0011 ... */ - /* 000 */ V(9, 1, 2), /* 224 */ - /* 001 */ V(9, 1, 2), - /* 010 */ V(9, 0, 3), - /* 011 */ V(4, 8, 3), - /* 100 */ V(8, 4, 3), - /* 101 */ V(7, 5, 3), - /* 110 */ V(3, 8, 3), - /* 111 */ V(8, 3, 3), - - /* 0001 0100 ... */ - /* 000 */ V(6, 6, 3), /* 232 */ - /* 001 */ V(2, 8, 3), - /* 010 */ V(8, 2, 2), - /* 011 */ V(8, 2, 2), - /* 100 */ V(4, 7, 3), - /* 101 */ V(7, 4, 3), - /* 110 */ V(1, 8, 2), - /* 111 */ V(1, 8, 2), - - /* 0001 0101 ... */ - /* 000 */ V(8, 1, 2), /* 240 */ - /* 001 */ V(8, 1, 2), - /* 010 */ V(8, 0, 2), - /* 011 */ V(8, 0, 2), - /* 100 */ V(0, 8, 3), - /* 101 */ V(5, 6, 3), - /* 110 */ V(3, 7, 2), - /* 111 */ V(3, 7, 2), - - /* 0001 0110 ... */ - /* 000 */ V(7, 3, 2), /* 248 */ - /* 001 */ V(7, 3, 2), - /* 010 */ V(6, 5, 3), - /* 011 */ V(4, 6, 3), - /* 100 */ V(2, 7, 2), - /* 101 */ V(2, 7, 2), - /* 110 */ V(7, 2, 2), - /* 111 */ V(7, 2, 2), - - /* 0001 0111 ... */ - /* 000 */ V(6, 4, 3), /* 256 */ - /* 001 */ V(5, 5, 3), - /* 010 */ V(0, 7, 2), - /* 011 */ V(0, 7, 2), - /* 100 */ V(1, 7, 1), - /* 101 */ V(1, 7, 1), - /* 110 */ V(1, 7, 1), - /* 111 */ V(1, 7, 1), - - /* 0001 1000 ... */ - /* 00 */ V(7, 1, 1), /* 264 */ - /* 01 */ V(7, 1, 1), - /* 10 */ V(7, 0, 2), - /* 11 */ V(3, 6, 2), - - /* 0001 1001 ... */ - /* 00 */ V(6, 3, 2), /* 268 */ - /* 01 */ V(4, 5, 2), - /* 10 */ V(5, 4, 2), - /* 11 */ V(2, 6, 2), - - /* 0001 1010 ... */ - /* 0 */ V(6, 2, 1), /* 272 */ - /* 1 */ V(1, 6, 1), - - /* 0001 1011 ... */ - /* 00 */ V(6, 1, 1), /* 274 */ - /* 01 */ V(6, 1, 1), - /* 10 */ V(0, 6, 2), - /* 11 */ V(6, 0, 2), - - /* 0001 1100 ... */ - /* 00 */ V(5, 3, 1), /* 278 */ - /* 01 */ V(5, 3, 1), - /* 10 */ V(3, 5, 2), - /* 11 */ V(4, 4, 2), - - /* 0001 1101 ... */ - /* 0 */ V(2, 5, 1), /* 282 */ - /* 1 */ V(5, 2, 1), - - /* 0001 1111 ... */ - /* 0 */ V(1, 5, 1), /* 284 */ - /* 1 */ V(0, 5, 1), - - /* 0010 0000 ... */ - /* 0 */ V(3, 4, 1), /* 286 */ - /* 1 */ V(4, 3, 1), - - /* 0010 0001 ... */ - /* 0 */ V(5, 0, 1), /* 288 */ - /* 1 */ V(2, 4, 1), - - /* 0010 0010 ... */ - /* 0 */ V(4, 2, 1), /* 290 */ - /* 1 */ V(3, 3, 1), - - /* 0010 0101 ... */ - /* 0 */ V(0, 4, 1), /* 292 */ - /* 1 */ V(4, 0, 1), - - /* 0000 0110 1100 ... */ - /* 0000 */ V(12, 14, 4), /* 294 */ - /* 0001 */ PTR(400, 1), - /* 0010 */ V(13, 14, 3), - /* 0011 */ V(13, 14, 3), - /* 0100 */ V(14, 9, 3), - /* 0101 */ V(14, 9, 3), - /* 0110 */ V(14, 10, 4), - /* 0111 */ V(13, 9, 4), - /* 1000 */ V(14, 14, 2), - /* 1001 */ V(14, 14, 2), - /* 1010 */ V(14, 14, 2), - /* 1011 */ V(14, 14, 2), - /* 1100 */ V(14, 13, 3), - /* 1101 */ V(14, 13, 3), - /* 1110 */ V(14, 11, 3), - /* 1111 */ V(14, 11, 3), - - /* 0000 0110 1101 ... */ - /* 000 */ V(11, 14, 2), /* 310 */ - /* 001 */ V(11, 14, 2), - /* 010 */ V(12, 13, 2), - /* 011 */ V(12, 13, 2), - /* 100 */ V(13, 12, 3), - /* 101 */ V(13, 11, 3), - /* 110 */ V(10, 14, 2), - /* 111 */ V(10, 14, 2), - - /* 0000 0110 1110 ... */ - /* 000 */ V(12, 12, 2), /* 318 */ - /* 001 */ V(12, 12, 2), - /* 010 */ V(10, 13, 3), - /* 011 */ V(13, 10, 3), - /* 100 */ V(7, 14, 3), - /* 101 */ V(10, 12, 3), - /* 110 */ V(12, 10, 2), - /* 111 */ V(12, 10, 2), - - /* 0000 0110 1111 ... */ - /* 000 */ V(12, 9, 3), /* 326 */ - /* 001 */ V(7, 13, 3), - /* 010 */ V(5, 14, 2), - /* 011 */ V(5, 14, 2), - /* 100 */ V(11, 13, 1), - /* 101 */ V(11, 13, 1), - /* 110 */ V(11, 13, 1), - /* 111 */ V(11, 13, 1), - - /* 0000 1011 0000 ... */ - /* 00 */ V(9, 14, 1), /* 334 */ - /* 01 */ V(9, 14, 1), - /* 10 */ V(11, 12, 2), - /* 11 */ V(12, 11, 2), - - /* 0000 1011 0001 ... */ - /* 00 */ V(8, 14, 2), /* 338 */ - /* 01 */ V(14, 8, 2), - /* 10 */ V(9, 13, 2), - /* 11 */ V(14, 7, 2), - - /* 0000 1011 0010 ... */ - /* 00 */ V(11, 11, 2), /* 342 */ - /* 01 */ V(8, 13, 2), - /* 10 */ V(13, 8, 2), - /* 11 */ V(6, 14, 2), - - /* 0000 1011 0011 ... */ - /* 0 */ V(14, 6, 1), /* 346 */ - /* 1 */ V(9, 12, 1), - - /* 0000 1011 0100 ... */ - /* 00 */ V(10, 11, 2), /* 348 */ - /* 01 */ V(11, 10, 2), - /* 10 */ V(14, 5, 2), - /* 11 */ V(13, 7, 2), - - /* 0000 1011 0101 ... */ - /* 00 */ V(4, 14, 1), /* 352 */ - /* 01 */ V(4, 14, 1), - /* 10 */ V(14, 4, 2), - /* 11 */ V(8, 12, 2), - - /* 0000 1011 0110 ... */ - /* 0 */ V(12, 8, 1), /* 356 */ - /* 1 */ V(3, 14, 1), - - /* 0000 1011 0111 ... */ - /* 00 */ V(6, 13, 1), /* 358 */ - /* 01 */ V(6, 13, 1), - /* 10 */ V(13, 6, 2), - /* 11 */ V(9, 11, 2), - - /* 0000 1011 1000 ... */ - /* 00 */ V(11, 9, 2), /* 362 */ - /* 01 */ V(10, 10, 2), - /* 10 */ V(14, 1, 1), - /* 11 */ V(14, 1, 1), - - /* 0000 1011 1001 ... */ - /* 00 */ V(13, 4, 1), /* 366 */ - /* 01 */ V(13, 4, 1), - /* 10 */ V(11, 8, 2), - /* 11 */ V(10, 9, 2), - - /* 0000 1011 1010 ... */ - /* 00 */ V(7, 11, 1), /* 370 */ - /* 01 */ V(7, 11, 1), - /* 10 */ V(11, 7, 2), - /* 11 */ V(13, 0, 2), - - /* 0000 1011 1100 ... */ - /* 0 */ V(0, 14, 1), /* 374 */ - /* 1 */ V(14, 0, 1), - - /* 0000 1011 1101 ... */ - /* 0 */ V(5, 13, 1), /* 376 */ - /* 1 */ V(13, 5, 1), - - /* 0000 1011 1110 ... */ - /* 0 */ V(7, 12, 1), /* 378 */ - /* 1 */ V(12, 7, 1), - - /* 0000 1011 1111 ... */ - /* 0 */ V(4, 13, 1), /* 380 */ - /* 1 */ V(8, 11, 1), - - /* 0000 1100 0000 ... */ - /* 0 */ V(9, 10, 1), /* 382 */ - /* 1 */ V(6, 12, 1), - - /* 0000 1100 0001 ... */ - /* 0 */ V(12, 6, 1), /* 384 */ - /* 1 */ V(3, 13, 1), - - /* 0000 1100 0010 ... */ - /* 0 */ V(5, 12, 1), /* 386 */ - /* 1 */ V(12, 5, 1), - - /* 0000 1100 0100 ... */ - /* 0 */ V(8, 10, 1), /* 388 */ - /* 1 */ V(10, 8, 1), - - /* 0000 1100 0101 ... */ - /* 0 */ V(9, 9, 1), /* 390 */ - /* 1 */ V(4, 12, 1), - - /* 0000 1100 0110 ... */ - /* 0 */ V(11, 6, 1), /* 392 */ - /* 1 */ V(7, 10, 1), - - /* 0000 1100 1000 ... */ - /* 0 */ V(5, 11, 1), /* 394 */ - /* 1 */ V(8, 9, 1), - - /* 0000 1100 1011 ... */ - /* 0 */ V(9, 8, 1), /* 396 */ - /* 1 */ V(7, 9, 1), - - /* 0000 1101 0101 ... */ - /* 0 */ V(9, 7, 1), /* 398 */ - /* 1 */ V(8, 8, 1), - - /* 0000 0110 1100 0001 ... */ - /* 0 */ V(14, 12, 1), /* 400 */ - /* 1 */ V(13, 13, 1) -}; - -static -union huffpair const hufftab24[] = { - /* 0000 */ PTR(16, 4), - /* 0001 */ PTR(32, 4), - /* 0010 */ PTR(48, 4), - /* 0011 */ V(15, 15, 4), - /* 0100 */ PTR(64, 4), - /* 0101 */ PTR(80, 4), - /* 0110 */ PTR(96, 4), - /* 0111 */ PTR(112, 4), - /* 1000 */ PTR(128, 4), - /* 1001 */ PTR(144, 4), - /* 1010 */ PTR(160, 3), - /* 1011 */ PTR(168, 2), - /* 1100 */ V(1, 1, 4), - /* 1101 */ V(0, 1, 4), - /* 1110 */ V(1, 0, 4), - /* 1111 */ V(0, 0, 4), - - /* 0000 ... */ - /* 0000 */ V(14, 15, 4), /* 16 */ - /* 0001 */ V(15, 14, 4), - /* 0010 */ V(13, 15, 4), - /* 0011 */ V(15, 13, 4), - /* 0100 */ V(12, 15, 4), - /* 0101 */ V(15, 12, 4), - /* 0110 */ V(11, 15, 4), - /* 0111 */ V(15, 11, 4), - /* 1000 */ V(15, 10, 3), - /* 1001 */ V(15, 10, 3), - /* 1010 */ V(10, 15, 4), - /* 1011 */ V(9, 15, 4), - /* 1100 */ V(15, 9, 3), - /* 1101 */ V(15, 9, 3), - /* 1110 */ V(15, 8, 3), - /* 1111 */ V(15, 8, 3), - - /* 0001 ... */ - /* 0000 */ V(8, 15, 4), /* 32 */ - /* 0001 */ V(7, 15, 4), - /* 0010 */ V(15, 7, 3), - /* 0011 */ V(15, 7, 3), - /* 0100 */ V(6, 15, 3), - /* 0101 */ V(6, 15, 3), - /* 0110 */ V(15, 6, 3), - /* 0111 */ V(15, 6, 3), - /* 1000 */ V(5, 15, 3), - /* 1001 */ V(5, 15, 3), - /* 1010 */ V(15, 5, 3), - /* 1011 */ V(15, 5, 3), - /* 1100 */ V(4, 15, 3), - /* 1101 */ V(4, 15, 3), - /* 1110 */ V(15, 4, 3), - /* 1111 */ V(15, 4, 3), - - /* 0010 ... */ - /* 0000 */ V(3, 15, 3), /* 48 */ - /* 0001 */ V(3, 15, 3), - /* 0010 */ V(15, 3, 3), - /* 0011 */ V(15, 3, 3), - /* 0100 */ V(2, 15, 3), - /* 0101 */ V(2, 15, 3), - /* 0110 */ V(15, 2, 3), - /* 0111 */ V(15, 2, 3), - /* 1000 */ V(15, 1, 3), - /* 1001 */ V(15, 1, 3), - /* 1010 */ V(1, 15, 4), - /* 1011 */ V(15, 0, 4), - /* 1100 */ PTR(172, 3), - /* 1101 */ PTR(180, 3), - /* 1110 */ PTR(188, 3), - /* 1111 */ PTR(196, 3), - - /* 0100 ... */ - /* 0000 */ PTR(204, 4), /* 64 */ - /* 0001 */ PTR(220, 3), - /* 0010 */ PTR(228, 3), - /* 0011 */ PTR(236, 3), - /* 0100 */ PTR(244, 2), - /* 0101 */ PTR(248, 2), - /* 0110 */ PTR(252, 2), - /* 0111 */ PTR(256, 2), - /* 1000 */ PTR(260, 2), - /* 1001 */ PTR(264, 2), - /* 1010 */ PTR(268, 2), - /* 1011 */ PTR(272, 2), - /* 1100 */ PTR(276, 2), - /* 1101 */ PTR(280, 3), - /* 1110 */ PTR(288, 2), - /* 1111 */ PTR(292, 2), - - /* 0101 ... */ - /* 0000 */ PTR(296, 2), /* 80 */ - /* 0001 */ PTR(300, 3), - /* 0010 */ PTR(308, 2), - /* 0011 */ PTR(312, 3), - /* 0100 */ PTR(320, 1), - /* 0101 */ PTR(322, 2), - /* 0110 */ PTR(326, 2), - /* 0111 */ PTR(330, 1), - /* 1000 */ PTR(332, 2), - /* 1001 */ PTR(336, 1), - /* 1010 */ PTR(338, 1), - /* 1011 */ PTR(340, 1), - /* 1100 */ PTR(342, 1), - /* 1101 */ PTR(344, 1), - /* 1110 */ PTR(346, 1), - /* 1111 */ PTR(348, 1), - - /* 0110 ... */ - /* 0000 */ PTR(350, 1), /* 96 */ - /* 0001 */ PTR(352, 1), - /* 0010 */ PTR(354, 1), - /* 0011 */ PTR(356, 1), - /* 0100 */ PTR(358, 1), - /* 0101 */ PTR(360, 1), - /* 0110 */ PTR(362, 1), - /* 0111 */ PTR(364, 1), - /* 1000 */ PTR(366, 1), - /* 1001 */ PTR(368, 1), - /* 1010 */ PTR(370, 2), - /* 1011 */ PTR(374, 1), - /* 1100 */ PTR(376, 2), - /* 1101 */ V(7, 3, 4), - /* 1110 */ PTR(380, 1), - /* 1111 */ V(7, 2, 4), - - /* 0111 ... */ - /* 0000 */ V(4, 6, 4), /* 112 */ - /* 0001 */ V(6, 4, 4), - /* 0010 */ V(5, 5, 4), - /* 0011 */ V(7, 1, 4), - /* 0100 */ V(3, 6, 4), - /* 0101 */ V(6, 3, 4), - /* 0110 */ V(4, 5, 4), - /* 0111 */ V(5, 4, 4), - /* 1000 */ V(2, 6, 4), - /* 1001 */ V(6, 2, 4), - /* 1010 */ V(1, 6, 4), - /* 1011 */ V(6, 1, 4), - /* 1100 */ PTR(382, 1), - /* 1101 */ V(3, 5, 4), - /* 1110 */ V(5, 3, 4), - /* 1111 */ V(4, 4, 4), - - /* 1000 ... */ - /* 0000 */ V(2, 5, 4), /* 128 */ - /* 0001 */ V(5, 2, 4), - /* 0010 */ V(1, 5, 4), - /* 0011 */ PTR(384, 1), - /* 0100 */ V(5, 1, 3), - /* 0101 */ V(5, 1, 3), - /* 0110 */ V(3, 4, 4), - /* 0111 */ V(4, 3, 4), - /* 1000 */ V(2, 4, 3), - /* 1001 */ V(2, 4, 3), - /* 1010 */ V(4, 2, 3), - /* 1011 */ V(4, 2, 3), - /* 1100 */ V(3, 3, 3), - /* 1101 */ V(3, 3, 3), - /* 1110 */ V(1, 4, 3), - /* 1111 */ V(1, 4, 3), - - /* 1001 ... */ - /* 0000 */ V(4, 1, 3), /* 144 */ - /* 0001 */ V(4, 1, 3), - /* 0010 */ V(0, 4, 4), - /* 0011 */ V(4, 0, 4), - /* 0100 */ V(2, 3, 3), - /* 0101 */ V(2, 3, 3), - /* 0110 */ V(3, 2, 3), - /* 0111 */ V(3, 2, 3), - /* 1000 */ V(1, 3, 2), - /* 1001 */ V(1, 3, 2), - /* 1010 */ V(1, 3, 2), - /* 1011 */ V(1, 3, 2), - /* 1100 */ V(3, 1, 2), - /* 1101 */ V(3, 1, 2), - /* 1110 */ V(3, 1, 2), - /* 1111 */ V(3, 1, 2), - - /* 1010 ... */ - /* 000 */ V(0, 3, 3), /* 160 */ - /* 001 */ V(3, 0, 3), - /* 010 */ V(2, 2, 2), - /* 011 */ V(2, 2, 2), - /* 100 */ V(1, 2, 1), - /* 101 */ V(1, 2, 1), - /* 110 */ V(1, 2, 1), - /* 111 */ V(1, 2, 1), - - /* 1011 ... */ - /* 00 */ V(2, 1, 1), /* 168 */ - /* 01 */ V(2, 1, 1), - /* 10 */ V(0, 2, 2), - /* 11 */ V(2, 0, 2), - - /* 0010 1100 ... */ - /* 000 */ V(0, 15, 1), /* 172 */ - /* 001 */ V(0, 15, 1), - /* 010 */ V(0, 15, 1), - /* 011 */ V(0, 15, 1), - /* 100 */ V(14, 14, 3), - /* 101 */ V(13, 14, 3), - /* 110 */ V(14, 13, 3), - /* 111 */ V(12, 14, 3), - - /* 0010 1101 ... */ - /* 000 */ V(14, 12, 3), /* 180 */ - /* 001 */ V(13, 13, 3), - /* 010 */ V(11, 14, 3), - /* 011 */ V(14, 11, 3), - /* 100 */ V(12, 13, 3), - /* 101 */ V(13, 12, 3), - /* 110 */ V(10, 14, 3), - /* 111 */ V(14, 10, 3), - - /* 0010 1110 ... */ - /* 000 */ V(11, 13, 3), /* 188 */ - /* 001 */ V(13, 11, 3), - /* 010 */ V(12, 12, 3), - /* 011 */ V(9, 14, 3), - /* 100 */ V(14, 9, 3), - /* 101 */ V(10, 13, 3), - /* 110 */ V(13, 10, 3), - /* 111 */ V(11, 12, 3), - - /* 0010 1111 ... */ - /* 000 */ V(12, 11, 3), /* 196 */ - /* 001 */ V(8, 14, 3), - /* 010 */ V(14, 8, 3), - /* 011 */ V(9, 13, 3), - /* 100 */ V(13, 9, 3), - /* 101 */ V(7, 14, 3), - /* 110 */ V(14, 7, 3), - /* 111 */ V(10, 12, 3), - - /* 0100 0000 ... */ - /* 0000 */ V(12, 10, 3), /* 204 */ - /* 0001 */ V(12, 10, 3), - /* 0010 */ V(11, 11, 3), - /* 0011 */ V(11, 11, 3), - /* 0100 */ V(8, 13, 3), - /* 0101 */ V(8, 13, 3), - /* 0110 */ V(13, 8, 3), - /* 0111 */ V(13, 8, 3), - /* 1000 */ V(0, 14, 4), - /* 1001 */ V(14, 0, 4), - /* 1010 */ V(0, 13, 3), - /* 1011 */ V(0, 13, 3), - /* 1100 */ V(14, 6, 2), - /* 1101 */ V(14, 6, 2), - /* 1110 */ V(14, 6, 2), - /* 1111 */ V(14, 6, 2), - - /* 0100 0001 ... */ - /* 000 */ V(6, 14, 3), /* 220 */ - /* 001 */ V(9, 12, 3), - /* 010 */ V(12, 9, 2), - /* 011 */ V(12, 9, 2), - /* 100 */ V(5, 14, 2), - /* 101 */ V(5, 14, 2), - /* 110 */ V(11, 10, 2), - /* 111 */ V(11, 10, 2), - - /* 0100 0010 ... */ - /* 000 */ V(14, 5, 2), /* 228 */ - /* 001 */ V(14, 5, 2), - /* 010 */ V(10, 11, 3), - /* 011 */ V(7, 13, 3), - /* 100 */ V(13, 7, 2), - /* 101 */ V(13, 7, 2), - /* 110 */ V(14, 4, 2), - /* 111 */ V(14, 4, 2), - - /* 0100 0011 ... */ - /* 000 */ V(8, 12, 2), /* 236 */ - /* 001 */ V(8, 12, 2), - /* 010 */ V(12, 8, 2), - /* 011 */ V(12, 8, 2), - /* 100 */ V(4, 14, 3), - /* 101 */ V(2, 14, 3), - /* 110 */ V(3, 14, 2), - /* 111 */ V(3, 14, 2), - - /* 0100 0100 ... */ - /* 00 */ V(6, 13, 2), /* 244 */ - /* 01 */ V(13, 6, 2), - /* 10 */ V(14, 3, 2), - /* 11 */ V(9, 11, 2), - - /* 0100 0101 ... */ - /* 00 */ V(11, 9, 2), /* 248 */ - /* 01 */ V(10, 10, 2), - /* 10 */ V(14, 2, 2), - /* 11 */ V(1, 14, 2), - - /* 0100 0110 ... */ - /* 00 */ V(14, 1, 2), /* 252 */ - /* 01 */ V(5, 13, 2), - /* 10 */ V(13, 5, 2), - /* 11 */ V(7, 12, 2), - - /* 0100 0111 ... */ - /* 00 */ V(12, 7, 2), /* 256 */ - /* 01 */ V(4, 13, 2), - /* 10 */ V(8, 11, 2), - /* 11 */ V(11, 8, 2), - - /* 0100 1000 ... */ - /* 00 */ V(13, 4, 2), /* 260 */ - /* 01 */ V(9, 10, 2), - /* 10 */ V(10, 9, 2), - /* 11 */ V(6, 12, 2), - - /* 0100 1001 ... */ - /* 00 */ V(12, 6, 2), /* 264 */ - /* 01 */ V(3, 13, 2), - /* 10 */ V(13, 3, 2), - /* 11 */ V(2, 13, 2), - - /* 0100 1010 ... */ - /* 00 */ V(13, 2, 2), /* 268 */ - /* 01 */ V(1, 13, 2), - /* 10 */ V(7, 11, 2), - /* 11 */ V(11, 7, 2), - - /* 0100 1011 ... */ - /* 00 */ V(13, 1, 2), /* 272 */ - /* 01 */ V(5, 12, 2), - /* 10 */ V(12, 5, 2), - /* 11 */ V(8, 10, 2), - - /* 0100 1100 ... */ - /* 00 */ V(10, 8, 2), /* 276 */ - /* 01 */ V(9, 9, 2), - /* 10 */ V(4, 12, 2), - /* 11 */ V(12, 4, 2), - - /* 0100 1101 ... */ - /* 000 */ V(6, 11, 2), /* 280 */ - /* 001 */ V(6, 11, 2), - /* 010 */ V(11, 6, 2), - /* 011 */ V(11, 6, 2), - /* 100 */ V(13, 0, 3), - /* 101 */ V(0, 12, 3), - /* 110 */ V(3, 12, 2), - /* 111 */ V(3, 12, 2), - - /* 0100 1110 ... */ - /* 00 */ V(12, 3, 2), /* 288 */ - /* 01 */ V(7, 10, 2), - /* 10 */ V(10, 7, 2), - /* 11 */ V(2, 12, 2), - - /* 0100 1111 ... */ - /* 00 */ V(12, 2, 2), /* 292 */ - /* 01 */ V(5, 11, 2), - /* 10 */ V(11, 5, 2), - /* 11 */ V(1, 12, 2), - - /* 0101 0000 ... */ - /* 00 */ V(8, 9, 2), /* 296 */ - /* 01 */ V(9, 8, 2), - /* 10 */ V(12, 1, 2), - /* 11 */ V(4, 11, 2), - - /* 0101 0001 ... */ - /* 000 */ V(12, 0, 3), /* 300 */ - /* 001 */ V(0, 11, 3), - /* 010 */ V(3, 11, 2), - /* 011 */ V(3, 11, 2), - /* 100 */ V(11, 0, 3), - /* 101 */ V(0, 10, 3), - /* 110 */ V(1, 10, 2), - /* 111 */ V(1, 10, 2), - - /* 0101 0010 ... */ - /* 00 */ V(11, 4, 1), /* 308 */ - /* 01 */ V(11, 4, 1), - /* 10 */ V(6, 10, 2), - /* 11 */ V(10, 6, 2), - - /* 0101 0011 ... */ - /* 000 */ V(7, 9, 2), /* 312 */ - /* 001 */ V(7, 9, 2), - /* 010 */ V(9, 7, 2), - /* 011 */ V(9, 7, 2), - /* 100 */ V(10, 0, 3), - /* 101 */ V(0, 9, 3), - /* 110 */ V(9, 0, 2), - /* 111 */ V(9, 0, 2), - - /* 0101 0100 ... */ - /* 0 */ V(11, 3, 1), /* 320 */ - /* 1 */ V(8, 8, 1), - - /* 0101 0101 ... */ - /* 00 */ V(2, 11, 2), /* 322 */ - /* 01 */ V(5, 10, 2), - /* 10 */ V(11, 2, 1), - /* 11 */ V(11, 2, 1), - - /* 0101 0110 ... */ - /* 00 */ V(10, 5, 2), /* 326 */ - /* 01 */ V(1, 11, 2), - /* 10 */ V(11, 1, 2), - /* 11 */ V(6, 9, 2), - - /* 0101 0111 ... */ - /* 0 */ V(9, 6, 1), /* 330 */ - /* 1 */ V(10, 4, 1), - - /* 0101 1000 ... */ - /* 00 */ V(4, 10, 2), /* 332 */ - /* 01 */ V(7, 8, 2), - /* 10 */ V(8, 7, 1), - /* 11 */ V(8, 7, 1), - - /* 0101 1001 ... */ - /* 0 */ V(3, 10, 1), /* 336 */ - /* 1 */ V(10, 3, 1), - - /* 0101 1010 ... */ - /* 0 */ V(5, 9, 1), /* 338 */ - /* 1 */ V(9, 5, 1), - - /* 0101 1011 ... */ - /* 0 */ V(2, 10, 1), /* 340 */ - /* 1 */ V(10, 2, 1), - - /* 0101 1100 ... */ - /* 0 */ V(10, 1, 1), /* 342 */ - /* 1 */ V(6, 8, 1), - - /* 0101 1101 ... */ - /* 0 */ V(8, 6, 1), /* 344 */ - /* 1 */ V(7, 7, 1), - - /* 0101 1110 ... */ - /* 0 */ V(4, 9, 1), /* 346 */ - /* 1 */ V(9, 4, 1), - - /* 0101 1111 ... */ - /* 0 */ V(3, 9, 1), /* 348 */ - /* 1 */ V(9, 3, 1), - - /* 0110 0000 ... */ - /* 0 */ V(5, 8, 1), /* 350 */ - /* 1 */ V(8, 5, 1), - - /* 0110 0001 ... */ - /* 0 */ V(2, 9, 1), /* 352 */ - /* 1 */ V(6, 7, 1), - - /* 0110 0010 ... */ - /* 0 */ V(7, 6, 1), /* 354 */ - /* 1 */ V(9, 2, 1), - - /* 0110 0011 ... */ - /* 0 */ V(1, 9, 1), /* 356 */ - /* 1 */ V(9, 1, 1), - - /* 0110 0100 ... */ - /* 0 */ V(4, 8, 1), /* 358 */ - /* 1 */ V(8, 4, 1), - - /* 0110 0101 ... */ - /* 0 */ V(5, 7, 1), /* 360 */ - /* 1 */ V(7, 5, 1), - - /* 0110 0110 ... */ - /* 0 */ V(3, 8, 1), /* 362 */ - /* 1 */ V(8, 3, 1), - - /* 0110 0111 ... */ - /* 0 */ V(6, 6, 1), /* 364 */ - /* 1 */ V(2, 8, 1), - - /* 0110 1000 ... */ - /* 0 */ V(8, 2, 1), /* 366 */ - /* 1 */ V(1, 8, 1), - - /* 0110 1001 ... */ - /* 0 */ V(4, 7, 1), /* 368 */ - /* 1 */ V(7, 4, 1), - - /* 0110 1010 ... */ - /* 00 */ V(8, 1, 1), /* 370 */ - /* 01 */ V(8, 1, 1), - /* 10 */ V(0, 8, 2), - /* 11 */ V(8, 0, 2), - - /* 0110 1011 ... */ - /* 0 */ V(5, 6, 1), /* 374 */ - /* 1 */ V(6, 5, 1), - - /* 0110 1100 ... */ - /* 00 */ V(1, 7, 1), /* 376 */ - /* 01 */ V(1, 7, 1), - /* 10 */ V(0, 7, 2), - /* 11 */ V(7, 0, 2), - - /* 0110 1110 ... */ - /* 0 */ V(3, 7, 1), /* 380 */ - /* 1 */ V(2, 7, 1), - - /* 0111 1100 ... */ - /* 0 */ V(0, 6, 1), /* 382 */ - /* 1 */ V(6, 0, 1), - - /* 1000 0011 ... */ - /* 0 */ V(0, 5, 1), /* 384 */ - /* 1 */ V(5, 0, 1) -}; - -# undef V -# undef PTR - -/* external tables */ - -union huffquad const *const mad_huff_quad_table[2] = { hufftabA, hufftabB }; - -struct hufftable const mad_huff_pair_table[32] = { - /* 0 */ { hufftab0, 0, 0 }, - /* 1 */ { hufftab1, 0, 3 }, - /* 2 */ { hufftab2, 0, 3 }, - /* 3 */ { hufftab3, 0, 3 }, - /* 4 */ { 0 /* not used */ }, - /* 5 */ { hufftab5, 0, 3 }, - /* 6 */ { hufftab6, 0, 4 }, - /* 7 */ { hufftab7, 0, 4 }, - /* 8 */ { hufftab8, 0, 4 }, - /* 9 */ { hufftab9, 0, 4 }, - /* 10 */ { hufftab10, 0, 4 }, - /* 11 */ { hufftab11, 0, 4 }, - /* 12 */ { hufftab12, 0, 4 }, - /* 13 */ { hufftab13, 0, 4 }, - /* 14 */ { 0 /* not used */ }, - /* 15 */ { hufftab15, 0, 4 }, - /* 16 */ { hufftab16, 1, 4 }, - /* 17 */ { hufftab16, 2, 4 }, - /* 18 */ { hufftab16, 3, 4 }, - /* 19 */ { hufftab16, 4, 4 }, - /* 20 */ { hufftab16, 6, 4 }, - /* 21 */ { hufftab16, 8, 4 }, - /* 22 */ { hufftab16, 10, 4 }, - /* 23 */ { hufftab16, 13, 4 }, - /* 24 */ { hufftab24, 4, 4 }, - /* 25 */ { hufftab24, 5, 4 }, - /* 26 */ { hufftab24, 6, 4 }, - /* 27 */ { hufftab24, 7, 4 }, - /* 28 */ { hufftab24, 8, 4 }, - /* 29 */ { hufftab24, 9, 4 }, - /* 30 */ { hufftab24, 11, 4 }, - /* 31 */ { hufftab24, 13, 4 } -}; diff --git a/libmad/src/huffman.h b/libmad/src/huffman.h deleted file mode 100644 index 6325db4..0000000 --- a/libmad/src/huffman.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: huffman.h,v 1.11 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_HUFFMAN_H -# define LIBMAD_HUFFMAN_H - -union huffquad { - struct { - unsigned short final : 1; - unsigned short bits : 3; - unsigned short offset : 12; - } ptr; - struct { - unsigned short final : 1; - unsigned short hlen : 3; - unsigned short v : 1; - unsigned short w : 1; - unsigned short x : 1; - unsigned short y : 1; - } value; - unsigned short final : 1; -}; - -union huffpair { - struct { - unsigned short final : 1; - unsigned short bits : 3; - unsigned short offset : 12; - } ptr; - struct { - unsigned short final : 1; - unsigned short hlen : 3; - unsigned short x : 4; - unsigned short y : 4; - } value; - unsigned short final : 1; -}; - -struct hufftable { - union huffpair const *table; - unsigned short linbits; - unsigned short startbits; -}; - -extern union huffquad const *const mad_huff_quad_table[2]; -extern struct hufftable const mad_huff_pair_table[32]; - -# endif diff --git a/libmad/src/imdct_s.dat b/libmad/src/imdct_s.dat deleted file mode 100644 index 476710e..0000000 --- a/libmad/src/imdct_s.dat +++ /dev/null @@ -1,62 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: imdct_s.dat,v 1.8 2004/01/23 09:41:32 rob Exp $ - */ - - /* 0 */ { MAD_F(0x09bd7ca0) /* 0.608761429 */, - -MAD_F(0x0ec835e8) /* -0.923879533 */, - -MAD_F(0x0216a2a2) /* -0.130526192 */, - MAD_F(0x0fdcf549) /* 0.991444861 */, - -MAD_F(0x061f78aa) /* -0.382683432 */, - -MAD_F(0x0cb19346) /* -0.793353340 */ }, - - /* 6 */ { -MAD_F(0x0cb19346) /* -0.793353340 */, - MAD_F(0x061f78aa) /* 0.382683432 */, - MAD_F(0x0fdcf549) /* 0.991444861 */, - MAD_F(0x0216a2a2) /* 0.130526192 */, - -MAD_F(0x0ec835e8) /* -0.923879533 */, - -MAD_F(0x09bd7ca0) /* -0.608761429 */ }, - - /* 1 */ { MAD_F(0x061f78aa) /* 0.382683432 */, - -MAD_F(0x0ec835e8) /* -0.923879533 */, - MAD_F(0x0ec835e8) /* 0.923879533 */, - -MAD_F(0x061f78aa) /* -0.382683432 */, - -MAD_F(0x061f78aa) /* -0.382683432 */, - MAD_F(0x0ec835e8) /* 0.923879533 */ }, - - /* 7 */ { -MAD_F(0x0ec835e8) /* -0.923879533 */, - -MAD_F(0x061f78aa) /* -0.382683432 */, - MAD_F(0x061f78aa) /* 0.382683432 */, - MAD_F(0x0ec835e8) /* 0.923879533 */, - MAD_F(0x0ec835e8) /* 0.923879533 */, - MAD_F(0x061f78aa) /* 0.382683432 */ }, - - /* 2 */ { MAD_F(0x0216a2a2) /* 0.130526192 */, - -MAD_F(0x061f78aa) /* -0.382683432 */, - MAD_F(0x09bd7ca0) /* 0.608761429 */, - -MAD_F(0x0cb19346) /* -0.793353340 */, - MAD_F(0x0ec835e8) /* 0.923879533 */, - -MAD_F(0x0fdcf549) /* -0.991444861 */ }, - - /* 8 */ { -MAD_F(0x0fdcf549) /* -0.991444861 */, - -MAD_F(0x0ec835e8) /* -0.923879533 */, - -MAD_F(0x0cb19346) /* -0.793353340 */, - -MAD_F(0x09bd7ca0) /* -0.608761429 */, - -MAD_F(0x061f78aa) /* -0.382683432 */, - -MAD_F(0x0216a2a2) /* -0.130526192 */ } diff --git a/libmad/src/layer12.c b/libmad/src/layer12.c deleted file mode 100644 index 62be832..0000000 --- a/libmad/src/layer12.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: layer12.c,v 1.17 2004/02/05 09:02:39 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# ifdef HAVE_LIMITS_H -# include -# else -# define CHAR_BIT 8 -# endif - -# include "fixed.h" -# include "bit.h" -# include "stream.h" -# include "frame.h" -# include "layer12.h" - -# ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4244 4018) -# endif - -/* - * scalefactor table - * used in both Layer I and Layer II decoding - */ -static -mad_fixed_t const sf_table[64] = { -# include "sf_table.dat" -}; - -/* --- Layer I ------------------------------------------------------------- */ - -/* linear scaling table */ -static -mad_fixed_t const linear_table[14] = { - MAD_F(0x15555555), /* 2^2 / (2^2 - 1) == 1.33333333333333 */ - MAD_F(0x12492492), /* 2^3 / (2^3 - 1) == 1.14285714285714 */ - MAD_F(0x11111111), /* 2^4 / (2^4 - 1) == 1.06666666666667 */ - MAD_F(0x10842108), /* 2^5 / (2^5 - 1) == 1.03225806451613 */ - MAD_F(0x10410410), /* 2^6 / (2^6 - 1) == 1.01587301587302 */ - MAD_F(0x10204081), /* 2^7 / (2^7 - 1) == 1.00787401574803 */ - MAD_F(0x10101010), /* 2^8 / (2^8 - 1) == 1.00392156862745 */ - MAD_F(0x10080402), /* 2^9 / (2^9 - 1) == 1.00195694716243 */ - MAD_F(0x10040100), /* 2^10 / (2^10 - 1) == 1.00097751710655 */ - MAD_F(0x10020040), /* 2^11 / (2^11 - 1) == 1.00048851978505 */ - MAD_F(0x10010010), /* 2^12 / (2^12 - 1) == 1.00024420024420 */ - MAD_F(0x10008004), /* 2^13 / (2^13 - 1) == 1.00012208521548 */ - MAD_F(0x10004001), /* 2^14 / (2^14 - 1) == 1.00006103888177 */ - MAD_F(0x10002000) /* 2^15 / (2^15 - 1) == 1.00003051850948 */ -}; - -/* - * NAME: I_sample() - * DESCRIPTION: decode one requantized Layer I sample from a bitstream - */ -static -mad_fixed_t I_sample(struct mad_bitptr *ptr, unsigned int nb) -{ - mad_fixed_t sample; - - sample = mad_bit_read(ptr, nb); - - /* invert most significant bit, extend sign, then scale to fixed format */ - - sample ^= 1 << (nb - 1); - sample |= -(sample & (1 << (nb - 1))); - - sample <<= MAD_F_FRACBITS - (nb - 1); - - /* requantize the sample */ - - /* s'' = (2^nb / (2^nb - 1)) * (s''' + 2^(-nb + 1)) */ - - sample += MAD_F_ONE >> (nb - 1); - - return mad_f_mul(sample, linear_table[nb - 2]); - - /* s' = factor * s'' */ - /* (to be performed by caller) */ -} - -/* - * NAME: layer->I() - * DESCRIPTION: decode a single Layer I frame - */ -int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) -{ - struct mad_header *header = &frame->header; - unsigned int nch, bound, ch, s, sb, nb; - unsigned char allocation[2][32], scalefactor[2][32]; - - nch = MAD_NCHANNELS(header); - - bound = 32; - if (header->mode == MAD_MODE_JOINT_STEREO) { - header->flags |= MAD_FLAG_I_STEREO; - bound = 4 + header->mode_extension * 4; - } - - /* check CRC word */ - - if (header->flags & MAD_FLAG_PROTECTION) { - header->crc_check = - mad_bit_crc(stream->ptr, 4 * (bound * nch + (32 - bound)), - header->crc_check); - - if (header->crc_check != header->crc_target && - !(frame->options & MAD_OPTION_IGNORECRC)) { - stream->error = MAD_ERROR_BADCRC; - return -1; - } - } - - /* decode bit allocations */ - - for (sb = 0; sb < bound; ++sb) { - for (ch = 0; ch < nch; ++ch) { - nb = mad_bit_read(&stream->ptr, 4); - - if (nb == 15) { - stream->error = MAD_ERROR_BADBITALLOC; - return -1; - } - - allocation[ch][sb] = nb ? nb + 1 : 0; - } - } - - for (sb = bound; sb < 32; ++sb) { - nb = mad_bit_read(&stream->ptr, 4); - - if (nb == 15) { - stream->error = MAD_ERROR_BADBITALLOC; - return -1; - } - - allocation[0][sb] = - allocation[1][sb] = nb ? nb + 1 : 0; - } - - /* decode scalefactors */ - - for (sb = 0; sb < 32; ++sb) { - for (ch = 0; ch < nch; ++ch) { - if (allocation[ch][sb]) { - scalefactor[ch][sb] = mad_bit_read(&stream->ptr, 6); - -# if defined(OPT_STRICT) - /* - * Scalefactor index 63 does not appear in Table B.1 of - * ISO/IEC 11172-3. Nonetheless, other implementations accept it, - * so we only reject it if OPT_STRICT is defined. - */ - if (scalefactor[ch][sb] == 63) { - stream->error = MAD_ERROR_BADSCALEFACTOR; - return -1; - } -# endif - } - } - } - - /* decode samples */ - - for (s = 0; s < 12; ++s) { - for (sb = 0; sb < bound; ++sb) { - for (ch = 0; ch < nch; ++ch) { - nb = allocation[ch][sb]; - frame->sbsample[ch][s][sb] = nb ? - mad_f_mul(I_sample(&stream->ptr, nb), - sf_table[scalefactor[ch][sb]]) : 0; - } - } - - for (sb = bound; sb < 32; ++sb) { - if ((nb = allocation[0][sb])) { - mad_fixed_t sample; - - sample = I_sample(&stream->ptr, nb); - - for (ch = 0; ch < nch; ++ch) { - frame->sbsample[ch][s][sb] = - mad_f_mul(sample, sf_table[scalefactor[ch][sb]]); - } - } - else { - for (ch = 0; ch < nch; ++ch) - frame->sbsample[ch][s][sb] = 0; - } - } - } - - return 0; -} - -/* --- Layer II ------------------------------------------------------------ */ - -/* possible quantization per subband table */ -static -struct { - unsigned int sblimit; - unsigned char const offsets[30]; -} const sbquant_table[5] = { - /* ISO/IEC 11172-3 Table B.2a */ - { 27, { 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, /* 0 */ - 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 } }, - /* ISO/IEC 11172-3 Table B.2b */ - { 30, { 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, /* 1 */ - 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0 } }, - /* ISO/IEC 11172-3 Table B.2c */ - { 8, { 5, 5, 2, 2, 2, 2, 2, 2 } }, /* 2 */ - /* ISO/IEC 11172-3 Table B.2d */ - { 12, { 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 } }, /* 3 */ - /* ISO/IEC 13818-3 Table B.1 */ - { 30, { 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, /* 4 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } } -}; - -/* bit allocation table */ -static -struct { - unsigned short nbal; - unsigned short offset; -} const bitalloc_table[8] = { - { 2, 0 }, /* 0 */ - { 2, 3 }, /* 1 */ - { 3, 3 }, /* 2 */ - { 3, 1 }, /* 3 */ - { 4, 2 }, /* 4 */ - { 4, 3 }, /* 5 */ - { 4, 4 }, /* 6 */ - { 4, 5 } /* 7 */ -}; - -/* offsets into quantization class table */ -static -unsigned char const offset_table[6][15] = { - { 0, 1, 16 }, /* 0 */ - { 0, 1, 2, 3, 4, 5, 16 }, /* 1 */ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, /* 2 */ - { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* 3 */ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 }, /* 4 */ - { 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } /* 5 */ -}; - -/* quantization class table */ -static -struct quantclass { - unsigned short nlevels; - unsigned char group; - unsigned char bits; - mad_fixed_t C; - mad_fixed_t D; -} const qc_table[17] = { -# include "qc_table.dat" -}; - -/* - * NAME: II_samples() - * DESCRIPTION: decode three requantized Layer II samples from a bitstream - */ -static -void II_samples(struct mad_bitptr *ptr, - struct quantclass const *quantclass, - mad_fixed_t output[3]) -{ - unsigned int nb, s, sample[3]; - - if ((nb = quantclass->group)) { - unsigned int c, nlevels; - - /* degrouping */ - c = mad_bit_read(ptr, quantclass->bits); - nlevels = quantclass->nlevels; - - for (s = 0; s < 3; ++s) { - sample[s] = c % nlevels; - c /= nlevels; - } - } - else { - nb = quantclass->bits; - - for (s = 0; s < 3; ++s) - sample[s] = mad_bit_read(ptr, nb); - } - - for (s = 0; s < 3; ++s) { - mad_fixed_t requantized; - - /* invert most significant bit, extend sign, then scale to fixed format */ - - requantized = sample[s] ^ (1 << (nb - 1)); - requantized |= -(requantized & (1 << (nb - 1))); - - requantized <<= MAD_F_FRACBITS - (nb - 1); - - /* requantize the sample */ - - /* s'' = C * (s''' + D) */ - - output[s] = mad_f_mul(requantized + quantclass->D, quantclass->C); - - /* s' = factor * s'' */ - /* (to be performed by caller) */ - } -} - -/* - * NAME: layer->II() - * DESCRIPTION: decode a single Layer II frame - */ -int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) -{ - struct mad_header *header = &frame->header; - struct mad_bitptr start; - unsigned int index, sblimit, nbal, nch, bound, gr, ch, s, sb; - unsigned char const *offsets; - unsigned char allocation[2][32], scfsi[2][32], scalefactor[2][32][3]; - mad_fixed_t samples[3]; - - nch = MAD_NCHANNELS(header); - - if (header->flags & MAD_FLAG_LSF_EXT) - index = 4; - else if (header->flags & MAD_FLAG_FREEFORMAT) - goto freeformat; - else { - unsigned long bitrate_per_channel; - - bitrate_per_channel = header->bitrate; - if (nch == 2) { - bitrate_per_channel /= 2; - -# if defined(OPT_STRICT) - /* - * ISO/IEC 11172-3 allows only single channel mode for 32, 48, 56, and - * 80 kbps bitrates in Layer II, but some encoders ignore this - * restriction. We enforce it if OPT_STRICT is defined. - */ - if (bitrate_per_channel <= 28000 || bitrate_per_channel == 40000) { - stream->error = MAD_ERROR_BADMODE; - return -1; - } -# endif - } - else { /* nch == 1 */ - if (bitrate_per_channel > 192000) { - /* - * ISO/IEC 11172-3 does not allow single channel mode for 224, 256, - * 320, or 384 kbps bitrates in Layer II. - */ - stream->error = MAD_ERROR_BADMODE; - return -1; - } - } - - if (bitrate_per_channel <= 48000) - index = (header->samplerate == 32000) ? 3 : 2; - else if (bitrate_per_channel <= 80000) - index = 0; - else { - freeformat: - index = (header->samplerate == 48000) ? 0 : 1; - } - } - - sblimit = sbquant_table[index].sblimit; - offsets = sbquant_table[index].offsets; - - bound = 32; - if (header->mode == MAD_MODE_JOINT_STEREO) { - header->flags |= MAD_FLAG_I_STEREO; - bound = 4 + header->mode_extension * 4; - } - - if (bound > sblimit) - bound = sblimit; - - start = stream->ptr; - - /* decode bit allocations */ - - for (sb = 0; sb < bound; ++sb) { - nbal = bitalloc_table[offsets[sb]].nbal; - - for (ch = 0; ch < nch; ++ch) - allocation[ch][sb] = mad_bit_read(&stream->ptr, nbal); - } - - for (sb = bound; sb < sblimit; ++sb) { - nbal = bitalloc_table[offsets[sb]].nbal; - - allocation[0][sb] = - allocation[1][sb] = mad_bit_read(&stream->ptr, nbal); - } - - /* decode scalefactor selection info */ - - for (sb = 0; sb < sblimit; ++sb) { - for (ch = 0; ch < nch; ++ch) { - if (allocation[ch][sb]) - scfsi[ch][sb] = mad_bit_read(&stream->ptr, 2); - } - } - - /* check CRC word */ - - if (header->flags & MAD_FLAG_PROTECTION) { - header->crc_check = - mad_bit_crc(start, mad_bit_length(&start, &stream->ptr), - header->crc_check); - - if (header->crc_check != header->crc_target && - !(frame->options & MAD_OPTION_IGNORECRC)) { - stream->error = MAD_ERROR_BADCRC; - return -1; - } - } - - /* decode scalefactors */ - - for (sb = 0; sb < sblimit; ++sb) { - for (ch = 0; ch < nch; ++ch) { - if (allocation[ch][sb]) { - scalefactor[ch][sb][0] = mad_bit_read(&stream->ptr, 6); - - switch (scfsi[ch][sb]) { - case 2: - scalefactor[ch][sb][2] = - scalefactor[ch][sb][1] = - scalefactor[ch][sb][0]; - break; - - case 0: - scalefactor[ch][sb][1] = mad_bit_read(&stream->ptr, 6); - /* fall through */ - - case 1: - case 3: - scalefactor[ch][sb][2] = mad_bit_read(&stream->ptr, 6); - } - - if (scfsi[ch][sb] & 1) - scalefactor[ch][sb][1] = scalefactor[ch][sb][scfsi[ch][sb] - 1]; - -# if defined(OPT_STRICT) - /* - * Scalefactor index 63 does not appear in Table B.1 of - * ISO/IEC 11172-3. Nonetheless, other implementations accept it, - * so we only reject it if OPT_STRICT is defined. - */ - if (scalefactor[ch][sb][0] == 63 || - scalefactor[ch][sb][1] == 63 || - scalefactor[ch][sb][2] == 63) { - stream->error = MAD_ERROR_BADSCALEFACTOR; - return -1; - } -# endif - } - } - } - - /* decode samples */ - - for (gr = 0; gr < 12; ++gr) { - for (sb = 0; sb < bound; ++sb) { - for (ch = 0; ch < nch; ++ch) { - if ((index = allocation[ch][sb])) { - index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1]; - - II_samples(&stream->ptr, &qc_table[index], samples); - - for (s = 0; s < 3; ++s) { - frame->sbsample[ch][3 * gr + s][sb] = - mad_f_mul(samples[s], sf_table[scalefactor[ch][sb][gr / 4]]); - } - } - else { - for (s = 0; s < 3; ++s) - frame->sbsample[ch][3 * gr + s][sb] = 0; - } - } - } - - for (sb = bound; sb < sblimit; ++sb) { - if ((index = allocation[0][sb])) { - index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1]; - - II_samples(&stream->ptr, &qc_table[index], samples); - - for (ch = 0; ch < nch; ++ch) { - for (s = 0; s < 3; ++s) { - frame->sbsample[ch][3 * gr + s][sb] = - mad_f_mul(samples[s], sf_table[scalefactor[ch][sb][gr / 4]]); - } - } - } - else { - for (ch = 0; ch < nch; ++ch) { - for (s = 0; s < 3; ++s) - frame->sbsample[ch][3 * gr + s][sb] = 0; - } - } - } - - for (ch = 0; ch < nch; ++ch) { - for (s = 0; s < 3; ++s) { - for (sb = sblimit; sb < 32; ++sb) - frame->sbsample[ch][3 * gr + s][sb] = 0; - } - } - } - - return 0; -} - -# ifdef _MSC_VER -# pragma warning(pop) -# endif diff --git a/libmad/src/layer12.h b/libmad/src/layer12.h deleted file mode 100644 index e1c4996..0000000 --- a/libmad/src/layer12.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: layer12.h,v 1.10 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_LAYER12_H -# define LIBMAD_LAYER12_H - -# include "stream.h" -# include "frame.h" - -int mad_layer_I(struct mad_stream *, struct mad_frame *); -int mad_layer_II(struct mad_stream *, struct mad_frame *); - -# endif diff --git a/libmad/src/layer3.c b/libmad/src/layer3.c deleted file mode 100644 index f92706f..0000000 --- a/libmad/src/layer3.c +++ /dev/null @@ -1,2707 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: layer3.c,v 1.43 2004/01/23 09:41:32 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include -# include - -# ifdef HAVE_ASSERT_H -# include -# endif - -# ifdef HAVE_LIMITS_H -# include -# else -# define CHAR_BIT 8 -# endif - -# include "fixed.h" -# include "bit.h" -# include "stream.h" -# include "frame.h" -# include "huffman.h" -# include "layer3.h" - -# ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4244 4018) -# endif - -/* --- Layer III ----------------------------------------------------------- */ - -enum { - count1table_select = 0x01, - scalefac_scale = 0x02, - preflag = 0x04, - mixed_block_flag = 0x08 -}; - -enum { - I_STEREO = 0x1, - MS_STEREO = 0x2 -}; - -struct sideinfo { - unsigned int main_data_begin; - unsigned int private_bits; - - unsigned char scfsi[2]; - - struct granule { - struct channel { - /* from side info */ - unsigned short part2_3_length; - unsigned short big_values; - unsigned short global_gain; - unsigned short scalefac_compress; - - unsigned char flags; - unsigned char block_type; - unsigned char table_select[3]; - unsigned char subblock_gain[3]; - unsigned char region0_count; - unsigned char region1_count; - - /* from main_data */ - unsigned char scalefac[39]; /* scalefac_l and/or scalefac_s */ - } ch[2]; - } gr[2]; -}; - -/* - * scalefactor bit lengths - * derived from section 2.4.2.7 of ISO/IEC 11172-3 - */ -static -struct { - unsigned char slen1; - unsigned char slen2; -} const sflen_table[16] = { - { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, - { 3, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 }, - { 2, 1 }, { 2, 2 }, { 2, 3 }, { 3, 1 }, - { 3, 2 }, { 3, 3 }, { 4, 2 }, { 4, 3 } -}; - -/* - * number of LSF scalefactor band values - * derived from section 2.4.3.2 of ISO/IEC 13818-3 - */ -static -unsigned char const nsfb_table[6][3][4] = { - { { 6, 5, 5, 5 }, - { 9, 9, 9, 9 }, - { 6, 9, 9, 9 } }, - - { { 6, 5, 7, 3 }, - { 9, 9, 12, 6 }, - { 6, 9, 12, 6 } }, - - { { 11, 10, 0, 0 }, - { 18, 18, 0, 0 }, - { 15, 18, 0, 0 } }, - - { { 7, 7, 7, 0 }, - { 12, 12, 12, 0 }, - { 6, 15, 12, 0 } }, - - { { 6, 6, 6, 3 }, - { 12, 9, 9, 6 }, - { 6, 12, 9, 6 } }, - - { { 8, 8, 5, 0 }, - { 15, 12, 9, 0 }, - { 6, 18, 9, 0 } } -}; - -/* - * MPEG-1 scalefactor band widths - * derived from Table B.8 of ISO/IEC 11172-3 - */ -static -unsigned char const sfb_48000_long[] = { - 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, - 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192 -}; - -static -unsigned char const sfb_44100_long[] = { - 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, - 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158 -}; - -static -unsigned char const sfb_32000_long[] = { - 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, - 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26 -}; - -static -unsigned char const sfb_48000_short[] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, - 6, 6, 6, 6, 6, 10, 10, 10, 12, 12, 12, 14, 14, - 14, 16, 16, 16, 20, 20, 20, 26, 26, 26, 66, 66, 66 -}; - -static -unsigned char const sfb_44100_short[] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, - 6, 6, 8, 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, - 14, 18, 18, 18, 22, 22, 22, 30, 30, 30, 56, 56, 56 -}; - -static -unsigned char const sfb_32000_short[] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, - 6, 6, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 20, - 20, 26, 26, 26, 34, 34, 34, 42, 42, 42, 12, 12, 12 -}; - -static -unsigned char const sfb_48000_mixed[] = { - /* long */ 4, 4, 4, 4, 4, 4, 6, 6, - /* short */ 4, 4, 4, 6, 6, 6, 6, 6, 6, 10, - 10, 10, 12, 12, 12, 14, 14, 14, 16, 16, - 16, 20, 20, 20, 26, 26, 26, 66, 66, 66 -}; - -static -unsigned char const sfb_44100_mixed[] = { - /* long */ 4, 4, 4, 4, 4, 4, 6, 6, - /* short */ 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, - 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, - 18, 22, 22, 22, 30, 30, 30, 56, 56, 56 -}; - -static -unsigned char const sfb_32000_mixed[] = { - /* long */ 4, 4, 4, 4, 4, 4, 6, 6, - /* short */ 4, 4, 4, 6, 6, 6, 8, 8, 8, 12, - 12, 12, 16, 16, 16, 20, 20, 20, 26, 26, - 26, 34, 34, 34, 42, 42, 42, 12, 12, 12 -}; - -/* - * MPEG-2 scalefactor band widths - * derived from Table B.2 of ISO/IEC 13818-3 - */ -static -unsigned char const sfb_24000_long[] = { - 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, - 18, 22, 26, 32, 38, 46, 54, 62, 70, 76, 36 -}; - -static -unsigned char const sfb_22050_long[] = { - 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, - 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54 -}; - -# define sfb_16000_long sfb_22050_long - -static -unsigned char const sfb_24000_short[] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, - 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, - 18, 24, 24, 24, 32, 32, 32, 44, 44, 44, 12, 12, 12 -}; - -static -unsigned char const sfb_22050_short[] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, - 6, 6, 8, 8, 8, 10, 10, 10, 14, 14, 14, 18, 18, - 18, 26, 26, 26, 32, 32, 32, 42, 42, 42, 18, 18, 18 -}; - -static -unsigned char const sfb_16000_short[] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, - 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, - 18, 24, 24, 24, 30, 30, 30, 40, 40, 40, 18, 18, 18 -}; - -static -unsigned char const sfb_24000_mixed[] = { - /* long */ 6, 6, 6, 6, 6, 6, - /* short */ 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, - 12, 12, 14, 14, 14, 18, 18, 18, 24, 24, - 24, 32, 32, 32, 44, 44, 44, 12, 12, 12 -}; - -static -unsigned char const sfb_22050_mixed[] = { - /* long */ 6, 6, 6, 6, 6, 6, - /* short */ 6, 6, 6, 6, 6, 6, 8, 8, 8, 10, - 10, 10, 14, 14, 14, 18, 18, 18, 26, 26, - 26, 32, 32, 32, 42, 42, 42, 18, 18, 18 -}; - -static -unsigned char const sfb_16000_mixed[] = { - /* long */ 6, 6, 6, 6, 6, 6, - /* short */ 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, - 12, 12, 14, 14, 14, 18, 18, 18, 24, 24, - 24, 30, 30, 30, 40, 40, 40, 18, 18, 18 -}; - -/* - * MPEG 2.5 scalefactor band widths - * derived from public sources - */ -# define sfb_12000_long sfb_16000_long -# define sfb_11025_long sfb_12000_long - -static -unsigned char const sfb_8000_long[] = { - 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32, - 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2 -}; - -# define sfb_12000_short sfb_16000_short -# define sfb_11025_short sfb_12000_short - -static -unsigned char const sfb_8000_short[] = { - 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 16, - 16, 16, 20, 20, 20, 24, 24, 24, 28, 28, 28, 36, 36, - 36, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26 -}; - -# define sfb_12000_mixed sfb_16000_mixed -# define sfb_11025_mixed sfb_12000_mixed - -/* the 8000 Hz short block scalefactor bands do not break after - the first 36 frequency lines, so this is probably wrong */ -static -unsigned char const sfb_8000_mixed[] = { - /* long */ 12, 12, 12, - /* short */ 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16, - 20, 20, 20, 24, 24, 24, 28, 28, 28, 36, 36, 36, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26 -}; - -static -struct { - unsigned char const *l; - unsigned char const *s; - unsigned char const *m; -} const sfbwidth_table[9] = { - { sfb_48000_long, sfb_48000_short, sfb_48000_mixed }, - { sfb_44100_long, sfb_44100_short, sfb_44100_mixed }, - { sfb_32000_long, sfb_32000_short, sfb_32000_mixed }, - { sfb_24000_long, sfb_24000_short, sfb_24000_mixed }, - { sfb_22050_long, sfb_22050_short, sfb_22050_mixed }, - { sfb_16000_long, sfb_16000_short, sfb_16000_mixed }, - { sfb_12000_long, sfb_12000_short, sfb_12000_mixed }, - { sfb_11025_long, sfb_11025_short, sfb_11025_mixed }, - { sfb_8000_long, sfb_8000_short, sfb_8000_mixed } -}; - -/* - * scalefactor band preemphasis (used only when preflag is set) - * derived from Table B.6 of ISO/IEC 11172-3 - */ -static -unsigned char const pretab[22] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 -}; - -/* - * table for requantization - * - * rq_table[x].mantissa * 2^(rq_table[x].exponent) = x^(4/3) - */ -static -struct fixedfloat { - unsigned long mantissa : 27; - unsigned short exponent : 5; -} const rq_table[8207] = { -# include "rq_table.dat" -}; - -/* - * fractional powers of two - * used for requantization and joint stereo decoding - * - * root_table[3 + x] = 2^(x/4) - */ -static -mad_fixed_t const root_table[7] = { - MAD_F(0x09837f05) /* 2^(-3/4) == 0.59460355750136 */, - MAD_F(0x0b504f33) /* 2^(-2/4) == 0.70710678118655 */, - MAD_F(0x0d744fcd) /* 2^(-1/4) == 0.84089641525371 */, - MAD_F(0x10000000) /* 2^( 0/4) == 1.00000000000000 */, - MAD_F(0x1306fe0a) /* 2^(+1/4) == 1.18920711500272 */, - MAD_F(0x16a09e66) /* 2^(+2/4) == 1.41421356237310 */, - MAD_F(0x1ae89f99) /* 2^(+3/4) == 1.68179283050743 */ -}; - -/* - * coefficients for aliasing reduction - * derived from Table B.9 of ISO/IEC 11172-3 - * - * c[] = { -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 } - * cs[i] = 1 / sqrt(1 + c[i]^2) - * ca[i] = c[i] / sqrt(1 + c[i]^2) - */ -static -mad_fixed_t const cs[8] = { - +MAD_F(0x0db84a81) /* +0.857492926 */, +MAD_F(0x0e1b9d7f) /* +0.881741997 */, - +MAD_F(0x0f31adcf) /* +0.949628649 */, +MAD_F(0x0fbba815) /* +0.983314592 */, - +MAD_F(0x0feda417) /* +0.995517816 */, +MAD_F(0x0ffc8fc8) /* +0.999160558 */, - +MAD_F(0x0fff964c) /* +0.999899195 */, +MAD_F(0x0ffff8d3) /* +0.999993155 */ -}; - -static -mad_fixed_t const ca[8] = { - -MAD_F(0x083b5fe7) /* -0.514495755 */, -MAD_F(0x078c36d2) /* -0.471731969 */, - -MAD_F(0x05039814) /* -0.313377454 */, -MAD_F(0x02e91dd1) /* -0.181913200 */, - -MAD_F(0x0183603a) /* -0.094574193 */, -MAD_F(0x00a7cb87) /* -0.040965583 */, - -MAD_F(0x003a2847) /* -0.014198569 */, -MAD_F(0x000f27b4) /* -0.003699975 */ -}; - -/* - * IMDCT coefficients for short blocks - * derived from section 2.4.3.4.10.2 of ISO/IEC 11172-3 - * - * imdct_s[i/even][k] = cos((PI / 24) * (2 * (i / 2) + 7) * (2 * k + 1)) - * imdct_s[i /odd][k] = cos((PI / 24) * (2 * (6 + (i-1)/2) + 7) * (2 * k + 1)) - */ -static -mad_fixed_t const imdct_s[6][6] = { -# include "imdct_s.dat" -}; - -# if !defined(ASO_IMDCT) -/* - * windowing coefficients for long blocks - * derived from section 2.4.3.4.10.3 of ISO/IEC 11172-3 - * - * window_l[i] = sin((PI / 36) * (i + 1/2)) - */ -static -mad_fixed_t const window_l[36] = { - MAD_F(0x00b2aa3e) /* 0.043619387 */, MAD_F(0x0216a2a2) /* 0.130526192 */, - MAD_F(0x03768962) /* 0.216439614 */, MAD_F(0x04cfb0e2) /* 0.300705800 */, - MAD_F(0x061f78aa) /* 0.382683432 */, MAD_F(0x07635284) /* 0.461748613 */, - MAD_F(0x0898c779) /* 0.537299608 */, MAD_F(0x09bd7ca0) /* 0.608761429 */, - MAD_F(0x0acf37ad) /* 0.675590208 */, MAD_F(0x0bcbe352) /* 0.737277337 */, - MAD_F(0x0cb19346) /* 0.793353340 */, MAD_F(0x0d7e8807) /* 0.843391446 */, - - MAD_F(0x0e313245) /* 0.887010833 */, MAD_F(0x0ec835e8) /* 0.923879533 */, - MAD_F(0x0f426cb5) /* 0.953716951 */, MAD_F(0x0f9ee890) /* 0.976296007 */, - MAD_F(0x0fdcf549) /* 0.991444861 */, MAD_F(0x0ffc19fd) /* 0.999048222 */, - MAD_F(0x0ffc19fd) /* 0.999048222 */, MAD_F(0x0fdcf549) /* 0.991444861 */, - MAD_F(0x0f9ee890) /* 0.976296007 */, MAD_F(0x0f426cb5) /* 0.953716951 */, - MAD_F(0x0ec835e8) /* 0.923879533 */, MAD_F(0x0e313245) /* 0.887010833 */, - - MAD_F(0x0d7e8807) /* 0.843391446 */, MAD_F(0x0cb19346) /* 0.793353340 */, - MAD_F(0x0bcbe352) /* 0.737277337 */, MAD_F(0x0acf37ad) /* 0.675590208 */, - MAD_F(0x09bd7ca0) /* 0.608761429 */, MAD_F(0x0898c779) /* 0.537299608 */, - MAD_F(0x07635284) /* 0.461748613 */, MAD_F(0x061f78aa) /* 0.382683432 */, - MAD_F(0x04cfb0e2) /* 0.300705800 */, MAD_F(0x03768962) /* 0.216439614 */, - MAD_F(0x0216a2a2) /* 0.130526192 */, MAD_F(0x00b2aa3e) /* 0.043619387 */, -}; -# endif /* ASO_IMDCT */ - -/* - * windowing coefficients for short blocks - * derived from section 2.4.3.4.10.3 of ISO/IEC 11172-3 - * - * window_s[i] = sin((PI / 12) * (i + 1/2)) - */ -static -mad_fixed_t const window_s[12] = { - MAD_F(0x0216a2a2) /* 0.130526192 */, MAD_F(0x061f78aa) /* 0.382683432 */, - MAD_F(0x09bd7ca0) /* 0.608761429 */, MAD_F(0x0cb19346) /* 0.793353340 */, - MAD_F(0x0ec835e8) /* 0.923879533 */, MAD_F(0x0fdcf549) /* 0.991444861 */, - MAD_F(0x0fdcf549) /* 0.991444861 */, MAD_F(0x0ec835e8) /* 0.923879533 */, - MAD_F(0x0cb19346) /* 0.793353340 */, MAD_F(0x09bd7ca0) /* 0.608761429 */, - MAD_F(0x061f78aa) /* 0.382683432 */, MAD_F(0x0216a2a2) /* 0.130526192 */, -}; - -/* - * coefficients for intensity stereo processing - * derived from section 2.4.3.4.9.3 of ISO/IEC 11172-3 - * - * is_ratio[i] = tan(i * (PI / 12)) - * is_table[i] = is_ratio[i] / (1 + is_ratio[i]) - */ -static -mad_fixed_t const is_table[7] = { - MAD_F(0x00000000) /* 0.000000000 */, - MAD_F(0x0361962f) /* 0.211324865 */, - MAD_F(0x05db3d74) /* 0.366025404 */, - MAD_F(0x08000000) /* 0.500000000 */, - MAD_F(0x0a24c28c) /* 0.633974596 */, - MAD_F(0x0c9e69d1) /* 0.788675135 */, - MAD_F(0x10000000) /* 1.000000000 */ -}; - -/* - * coefficients for LSF intensity stereo processing - * derived from section 2.4.3.2 of ISO/IEC 13818-3 - * - * is_lsf_table[0][i] = (1 / sqrt(sqrt(2)))^(i + 1) - * is_lsf_table[1][i] = (1 / sqrt(2)) ^(i + 1) - */ -static -mad_fixed_t const is_lsf_table[2][15] = { - { - MAD_F(0x0d744fcd) /* 0.840896415 */, - MAD_F(0x0b504f33) /* 0.707106781 */, - MAD_F(0x09837f05) /* 0.594603558 */, - MAD_F(0x08000000) /* 0.500000000 */, - MAD_F(0x06ba27e6) /* 0.420448208 */, - MAD_F(0x05a8279a) /* 0.353553391 */, - MAD_F(0x04c1bf83) /* 0.297301779 */, - MAD_F(0x04000000) /* 0.250000000 */, - MAD_F(0x035d13f3) /* 0.210224104 */, - MAD_F(0x02d413cd) /* 0.176776695 */, - MAD_F(0x0260dfc1) /* 0.148650889 */, - MAD_F(0x02000000) /* 0.125000000 */, - MAD_F(0x01ae89fa) /* 0.105112052 */, - MAD_F(0x016a09e6) /* 0.088388348 */, - MAD_F(0x01306fe1) /* 0.074325445 */ - }, { - MAD_F(0x0b504f33) /* 0.707106781 */, - MAD_F(0x08000000) /* 0.500000000 */, - MAD_F(0x05a8279a) /* 0.353553391 */, - MAD_F(0x04000000) /* 0.250000000 */, - MAD_F(0x02d413cd) /* 0.176776695 */, - MAD_F(0x02000000) /* 0.125000000 */, - MAD_F(0x016a09e6) /* 0.088388348 */, - MAD_F(0x01000000) /* 0.062500000 */, - MAD_F(0x00b504f3) /* 0.044194174 */, - MAD_F(0x00800000) /* 0.031250000 */, - MAD_F(0x005a827a) /* 0.022097087 */, - MAD_F(0x00400000) /* 0.015625000 */, - MAD_F(0x002d413d) /* 0.011048543 */, - MAD_F(0x00200000) /* 0.007812500 */, - MAD_F(0x0016a09e) /* 0.005524272 */ - } -}; - -/* - * NAME: III_sideinfo() - * DESCRIPTION: decode frame side information from a bitstream - */ -static -enum mad_error III_sideinfo(struct mad_bitptr *ptr, unsigned int nch, - int lsf, struct sideinfo *si, - unsigned int *data_bitlen, - unsigned int *priv_bitlen) -{ - unsigned int ngr, gr, ch, i; - enum mad_error result = MAD_ERROR_NONE; - - *data_bitlen = 0; - *priv_bitlen = lsf ? ((nch == 1) ? 1 : 2) : ((nch == 1) ? 5 : 3); - - si->main_data_begin = mad_bit_read(ptr, lsf ? 8 : 9); - si->private_bits = mad_bit_read(ptr, *priv_bitlen); - - ngr = 1; - if (!lsf) { - ngr = 2; - - for (ch = 0; ch < nch; ++ch) - si->scfsi[ch] = mad_bit_read(ptr, 4); - } - - for (gr = 0; gr < ngr; ++gr) { - struct granule *granule = &si->gr[gr]; - - for (ch = 0; ch < nch; ++ch) { - struct channel *channel = &granule->ch[ch]; - - channel->part2_3_length = mad_bit_read(ptr, 12); - channel->big_values = mad_bit_read(ptr, 9); - channel->global_gain = mad_bit_read(ptr, 8); - channel->scalefac_compress = mad_bit_read(ptr, lsf ? 9 : 4); - - *data_bitlen += channel->part2_3_length; - - if (channel->big_values > 288 && result == 0) - result = MAD_ERROR_BADBIGVALUES; - - channel->flags = 0; - - /* window_switching_flag */ - if (mad_bit_read(ptr, 1)) { - channel->block_type = mad_bit_read(ptr, 2); - - if (channel->block_type == 0 && result == 0) - result = MAD_ERROR_BADBLOCKTYPE; - - if (!lsf && channel->block_type == 2 && si->scfsi[ch] && result == 0) - result = MAD_ERROR_BADSCFSI; - - channel->region0_count = 7; - channel->region1_count = 36; - - if (mad_bit_read(ptr, 1)) - channel->flags |= mixed_block_flag; - else if (channel->block_type == 2) - channel->region0_count = 8; - - for (i = 0; i < 2; ++i) - channel->table_select[i] = mad_bit_read(ptr, 5); - -# if defined(DEBUG) - channel->table_select[2] = 4; /* not used */ -# endif - - for (i = 0; i < 3; ++i) - channel->subblock_gain[i] = mad_bit_read(ptr, 3); - } - else { - channel->block_type = 0; - - for (i = 0; i < 3; ++i) - channel->table_select[i] = mad_bit_read(ptr, 5); - - channel->region0_count = mad_bit_read(ptr, 4); - channel->region1_count = mad_bit_read(ptr, 3); - } - - /* [preflag,] scalefac_scale, count1table_select */ - channel->flags |= mad_bit_read(ptr, lsf ? 2 : 3); - } - } - - return result; -} - -/* - * NAME: III_scalefactors_lsf() - * DESCRIPTION: decode channel scalefactors for LSF from a bitstream - */ -static -unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr, - struct channel *channel, - struct channel *gr1ch, int mode_extension) -{ - struct mad_bitptr start; - unsigned int scalefac_compress, index, slen[4], part, n, i; - unsigned char const *nsfb; - - start = *ptr; - - scalefac_compress = channel->scalefac_compress; - index = (channel->block_type == 2) ? - ((channel->flags & mixed_block_flag) ? 2 : 1) : 0; - - if (!((mode_extension & I_STEREO) && gr1ch)) { - if (scalefac_compress < 400) { - slen[0] = (scalefac_compress >> 4) / 5; - slen[1] = (scalefac_compress >> 4) % 5; - slen[2] = (scalefac_compress % 16) >> 2; - slen[3] = scalefac_compress % 4; - - nsfb = nsfb_table[0][index]; - } - else if (scalefac_compress < 500) { - scalefac_compress -= 400; - - slen[0] = (scalefac_compress >> 2) / 5; - slen[1] = (scalefac_compress >> 2) % 5; - slen[2] = scalefac_compress % 4; - slen[3] = 0; - - nsfb = nsfb_table[1][index]; - } - else { - scalefac_compress -= 500; - - slen[0] = scalefac_compress / 3; - slen[1] = scalefac_compress % 3; - slen[2] = 0; - slen[3] = 0; - - channel->flags |= preflag; - - nsfb = nsfb_table[2][index]; - } - - n = 0; - for (part = 0; part < 4; ++part) { - for (i = 0; i < nsfb[part]; ++i) - channel->scalefac[n++] = mad_bit_read(ptr, slen[part]); - } - - while (n < 39) - channel->scalefac[n++] = 0; - } - else { /* (mode_extension & I_STEREO) && gr1ch (i.e. ch == 1) */ - scalefac_compress >>= 1; - - if (scalefac_compress < 180) { - slen[0] = scalefac_compress / 36; - slen[1] = (scalefac_compress % 36) / 6; - slen[2] = (scalefac_compress % 36) % 6; - slen[3] = 0; - - nsfb = nsfb_table[3][index]; - } - else if (scalefac_compress < 244) { - scalefac_compress -= 180; - - slen[0] = (scalefac_compress % 64) >> 4; - slen[1] = (scalefac_compress % 16) >> 2; - slen[2] = scalefac_compress % 4; - slen[3] = 0; - - nsfb = nsfb_table[4][index]; - } - else { - scalefac_compress -= 244; - - slen[0] = scalefac_compress / 3; - slen[1] = scalefac_compress % 3; - slen[2] = 0; - slen[3] = 0; - - nsfb = nsfb_table[5][index]; - } - - n = 0; - for (part = 0; part < 4; ++part) { - unsigned int max, is_pos; - - max = (1 << slen[part]) - 1; - - for (i = 0; i < nsfb[part]; ++i) { - is_pos = mad_bit_read(ptr, slen[part]); - - channel->scalefac[n] = is_pos; - gr1ch->scalefac[n++] = (is_pos == max); - } - } - - while (n < 39) { - channel->scalefac[n] = 0; - gr1ch->scalefac[n++] = 0; /* apparently not illegal */ - } - } - - return mad_bit_length(&start, ptr); -} - -/* - * NAME: III_scalefactors() - * DESCRIPTION: decode channel scalefactors of one granule from a bitstream - */ -static -unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, - struct channel const *gr0ch, unsigned int scfsi) -{ - struct mad_bitptr start; - unsigned int slen1, slen2, sfbi; - - start = *ptr; - - slen1 = sflen_table[channel->scalefac_compress].slen1; - slen2 = sflen_table[channel->scalefac_compress].slen2; - - if (channel->block_type == 2) { - unsigned int nsfb; - - sfbi = 0; - - nsfb = (channel->flags & mixed_block_flag) ? 8 + 3 * 3 : 6 * 3; - while (nsfb--) - channel->scalefac[sfbi++] = mad_bit_read(ptr, slen1); - - nsfb = 6 * 3; - while (nsfb--) - channel->scalefac[sfbi++] = mad_bit_read(ptr, slen2); - - nsfb = 1 * 3; - while (nsfb--) - channel->scalefac[sfbi++] = 0; - } - else { /* channel->block_type != 2 */ - if (scfsi & 0x8) { - for (sfbi = 0; sfbi < 6; ++sfbi) - channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; - } - else { - for (sfbi = 0; sfbi < 6; ++sfbi) - channel->scalefac[sfbi] = mad_bit_read(ptr, slen1); - } - - if (scfsi & 0x4) { - for (sfbi = 6; sfbi < 11; ++sfbi) - channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; - } - else { - for (sfbi = 6; sfbi < 11; ++sfbi) - channel->scalefac[sfbi] = mad_bit_read(ptr, slen1); - } - - if (scfsi & 0x2) { - for (sfbi = 11; sfbi < 16; ++sfbi) - channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; - } - else { - for (sfbi = 11; sfbi < 16; ++sfbi) - channel->scalefac[sfbi] = mad_bit_read(ptr, slen2); - } - - if (scfsi & 0x1) { - for (sfbi = 16; sfbi < 21; ++sfbi) - channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; - } - else { - for (sfbi = 16; sfbi < 21; ++sfbi) - channel->scalefac[sfbi] = mad_bit_read(ptr, slen2); - } - - channel->scalefac[21] = 0; - } - - return mad_bit_length(&start, ptr); -} - -/* - * The Layer III formula for requantization and scaling is defined by - * section 2.4.3.4.7.1 of ISO/IEC 11172-3, as follows: - * - * long blocks: - * xr[i] = sign(is[i]) * abs(is[i])^(4/3) * - * 2^((1/4) * (global_gain - 210)) * - * 2^-(scalefac_multiplier * - * (scalefac_l[sfb] + preflag * pretab[sfb])) - * - * short blocks: - * xr[i] = sign(is[i]) * abs(is[i])^(4/3) * - * 2^((1/4) * (global_gain - 210 - 8 * subblock_gain[w])) * - * 2^-(scalefac_multiplier * scalefac_s[sfb][w]) - * - * where: - * scalefac_multiplier = (scalefac_scale + 1) / 2 - * - * The routines III_exponents() and III_requantize() facilitate this - * calculation. - */ - -/* - * NAME: III_exponents() - * DESCRIPTION: calculate scalefactor exponents - */ -static -void III_exponents(struct channel const *channel, - unsigned char const *sfbwidth, signed int exponents[39]) -{ - signed int gain; - unsigned int scalefac_multiplier, sfbi; - - gain = (signed int) channel->global_gain - 210; - scalefac_multiplier = (channel->flags & scalefac_scale) ? 2 : 1; - - if (channel->block_type == 2) { - unsigned int l; - signed int gain0, gain1, gain2; - - sfbi = l = 0; - - if (channel->flags & mixed_block_flag) { - unsigned int premask; - - premask = (channel->flags & preflag) ? ~0 : 0; - - /* long block subbands 0-1 */ - - while (l < 36) { - exponents[sfbi] = gain - - (signed int) ((channel->scalefac[sfbi] + (pretab[sfbi] & premask)) << - scalefac_multiplier); - - l += sfbwidth[sfbi++]; - } - } - - /* this is probably wrong for 8000 Hz short/mixed blocks */ - - gain0 = gain - 8 * (signed int) channel->subblock_gain[0]; - gain1 = gain - 8 * (signed int) channel->subblock_gain[1]; - gain2 = gain - 8 * (signed int) channel->subblock_gain[2]; - - while (l < 576) { - exponents[sfbi + 0] = gain0 - - (signed int) (channel->scalefac[sfbi + 0] << scalefac_multiplier); - exponents[sfbi + 1] = gain1 - - (signed int) (channel->scalefac[sfbi + 1] << scalefac_multiplier); - exponents[sfbi + 2] = gain2 - - (signed int) (channel->scalefac[sfbi + 2] << scalefac_multiplier); - - l += 3 * sfbwidth[sfbi]; - sfbi += 3; - } - } - else { /* channel->block_type != 2 */ - if (channel->flags & preflag) { - for (sfbi = 0; sfbi < 22; ++sfbi) { - exponents[sfbi] = gain - - (signed int) ((channel->scalefac[sfbi] + pretab[sfbi]) << - scalefac_multiplier); - } - } - else { - for (sfbi = 0; sfbi < 22; ++sfbi) { - exponents[sfbi] = gain - - (signed int) (channel->scalefac[sfbi] << scalefac_multiplier); - } - } - } -} - -/* - * NAME: III_requantize() - * DESCRIPTION: requantize one (positive) value - */ -static -mad_fixed_t III_requantize(unsigned int value, signed int exp) -{ - mad_fixed_t requantized; - signed int frac; - struct fixedfloat const *power; - - frac = exp % 4; /* assumes sign(frac) == sign(exp) */ - exp /= 4; - - power = &rq_table[value]; - requantized = power->mantissa; - exp += power->exponent; - - if (exp < 0) { - if (-exp >= sizeof(mad_fixed_t) * CHAR_BIT) { - /* underflow */ - requantized = 0; - } - else { - requantized += 1L << (-exp - 1); - requantized >>= -exp; - } - } - else { - if (exp >= 5) { - /* overflow */ -# if defined(DEBUG) - fprintf(stderr, "requantize overflow (%f * 2^%d)\n", - mad_f_todouble(requantized), exp); -# endif - requantized = MAD_F_MAX; - } - else - requantized <<= exp; - } - - return frac ? mad_f_mul(requantized, root_table[3 + frac]) : requantized; -} - -/* we must take care that sz >= bits and sz < sizeof(long) lest bits == 0 */ -# define MASK(cache, sz, bits) \ - (((cache) >> ((sz) - (bits))) & ((1 << (bits)) - 1)) -# define MASK1BIT(cache, sz) \ - ((cache) & (1 << ((sz) - 1))) - -/* - * NAME: III_huffdecode() - * DESCRIPTION: decode Huffman code words of one channel of one granule - */ -static -enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], - struct channel *channel, - unsigned char const *sfbwidth, - unsigned int part2_length) -{ - signed int exponents[39], exp; - signed int const *expptr; - struct mad_bitptr peek; - signed int bits_left, cachesz; - register mad_fixed_t *xrptr; - mad_fixed_t const *sfbound; - register unsigned long bitcache; - - bits_left = (signed) channel->part2_3_length - (signed) part2_length; - if (bits_left < 0) - return MAD_ERROR_BADPART3LEN; - - III_exponents(channel, sfbwidth, exponents); - - peek = *ptr; - mad_bit_skip(ptr, bits_left); - - /* align bit reads to byte boundaries */ - cachesz = mad_bit_bitsleft(&peek); - cachesz += ((32 - 1 - 24) + (24 - cachesz)) & ~7; - - bitcache = mad_bit_read(&peek, cachesz); - bits_left -= cachesz; - - xrptr = &xr[0]; - - /* big_values */ - { - unsigned int region, rcount; - struct hufftable const *entry; - union huffpair const *table; - unsigned int linbits, startbits, big_values, reqhits; - mad_fixed_t reqcache[16]; - - sfbound = xrptr + *sfbwidth++; - rcount = channel->region0_count + 1; - - entry = &mad_huff_pair_table[channel->table_select[region = 0]]; - table = entry->table; - linbits = entry->linbits; - startbits = entry->startbits; - - if (table == 0) - return MAD_ERROR_BADHUFFTABLE; - - expptr = &exponents[0]; - exp = *expptr++; - reqhits = 0; - - big_values = channel->big_values; - - while (big_values-- && cachesz + bits_left > 0) { - union huffpair const *pair; - unsigned int clumpsz, value; - register mad_fixed_t requantized; - - if (xrptr == sfbound) { - sfbound += *sfbwidth++; - - /* change table if region boundary */ - - if (--rcount == 0) { - if (region == 0) - rcount = channel->region1_count + 1; - else - rcount = 0; /* all remaining */ - - entry = &mad_huff_pair_table[channel->table_select[++region]]; - table = entry->table; - linbits = entry->linbits; - startbits = entry->startbits; - - if (table == 0) - return MAD_ERROR_BADHUFFTABLE; - } - - if (exp != *expptr) { - exp = *expptr; - reqhits = 0; - } - - ++expptr; - } - - if (cachesz < 21) { - unsigned int bits; - - bits = ((32 - 1 - 21) + (21 - cachesz)) & ~7; - bitcache = (bitcache << bits) | mad_bit_read(&peek, bits); - cachesz += bits; - bits_left -= bits; - } - - /* hcod (0..19) */ - - clumpsz = startbits; - pair = &table[MASK(bitcache, cachesz, clumpsz)]; - - while (!pair->final) { - cachesz -= clumpsz; - - clumpsz = pair->ptr.bits; - pair = &table[pair->ptr.offset + MASK(bitcache, cachesz, clumpsz)]; - } - - cachesz -= pair->value.hlen; - - if (linbits) { - /* x (0..14) */ - - value = pair->value.x; - - switch (value) { - case 0: - xrptr[0] = 0; - break; - - case 15: - if (cachesz < linbits + 2) { - bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); - cachesz += 16; - bits_left -= 16; - } - - value += MASK(bitcache, cachesz, linbits); - cachesz -= linbits; - - requantized = III_requantize(value, exp); - goto x_final; - - default: - if (reqhits & (1 << value)) - requantized = reqcache[value]; - else { - reqhits |= (1 << value); - requantized = reqcache[value] = III_requantize(value, exp); - } - - x_final: - xrptr[0] = MASK1BIT(bitcache, cachesz--) ? - -requantized : requantized; - } - - /* y (0..14) */ - - value = pair->value.y; - - switch (value) { - case 0: - xrptr[1] = 0; - break; - - case 15: - if (cachesz < linbits + 1) { - bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); - cachesz += 16; - bits_left -= 16; - } - - value += MASK(bitcache, cachesz, linbits); - cachesz -= linbits; - - requantized = III_requantize(value, exp); - goto y_final; - - default: - if (reqhits & (1 << value)) - requantized = reqcache[value]; - else { - reqhits |= (1 << value); - requantized = reqcache[value] = III_requantize(value, exp); - } - - y_final: - xrptr[1] = MASK1BIT(bitcache, cachesz--) ? - -requantized : requantized; - } - } - else { - /* x (0..1) */ - - value = pair->value.x; - - if (value == 0) - xrptr[0] = 0; - else { - if (reqhits & (1 << value)) - requantized = reqcache[value]; - else { - reqhits |= (1 << value); - requantized = reqcache[value] = III_requantize(value, exp); - } - - xrptr[0] = MASK1BIT(bitcache, cachesz--) ? - -requantized : requantized; - } - - /* y (0..1) */ - - value = pair->value.y; - - if (value == 0) - xrptr[1] = 0; - else { - if (reqhits & (1 << value)) - requantized = reqcache[value]; - else { - reqhits |= (1 << value); - requantized = reqcache[value] = III_requantize(value, exp); - } - - xrptr[1] = MASK1BIT(bitcache, cachesz--) ? - -requantized : requantized; - } - } - - xrptr += 2; - } - } - - if (cachesz + bits_left < 0) - return MAD_ERROR_BADHUFFDATA; /* big_values overrun */ - - /* count1 */ - { - union huffquad const *table; - register mad_fixed_t requantized; - - table = mad_huff_quad_table[channel->flags & count1table_select]; - - requantized = III_requantize(1, exp); - - while (cachesz + bits_left > 0 && xrptr <= &xr[572]) { - union huffquad const *quad; - - /* hcod (1..6) */ - - if (cachesz < 10) { - bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); - cachesz += 16; - bits_left -= 16; - } - - quad = &table[MASK(bitcache, cachesz, 4)]; - - /* quad tables guaranteed to have at most one extra lookup */ - if (!quad->final) { - cachesz -= 4; - - quad = &table[quad->ptr.offset + - MASK(bitcache, cachesz, quad->ptr.bits)]; - } - - cachesz -= quad->value.hlen; - - if (xrptr == sfbound) { - sfbound += *sfbwidth++; - - if (exp != *expptr) { - exp = *expptr; - requantized = III_requantize(1, exp); - } - - ++expptr; - } - - /* v (0..1) */ - - xrptr[0] = quad->value.v ? - (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; - - /* w (0..1) */ - - xrptr[1] = quad->value.w ? - (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; - - xrptr += 2; - - if (xrptr == sfbound) { - sfbound += *sfbwidth++; - - if (exp != *expptr) { - exp = *expptr; - requantized = III_requantize(1, exp); - } - - ++expptr; - } - - /* x (0..1) */ - - xrptr[0] = quad->value.x ? - (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; - - /* y (0..1) */ - - xrptr[1] = quad->value.y ? - (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; - - xrptr += 2; - } - - if (cachesz + bits_left < 0) { -# if 0 && defined(DEBUG) - fprintf(stderr, "huffman count1 overrun (%d bits)\n", - -(cachesz + bits_left)); -# endif - - /* technically the bitstream is misformatted, but apparently - some encoders are just a bit sloppy with stuffing bits */ - - xrptr -= 4; - } - } - - assert(-bits_left <= MAD_BUFFER_GUARD * CHAR_BIT); - -# if 0 && defined(DEBUG) - if (bits_left < 0) - fprintf(stderr, "read %d bits too many\n", -bits_left); - else if (cachesz + bits_left > 0) - fprintf(stderr, "%d stuffing bits\n", cachesz + bits_left); -# endif - - /* rzero */ - while (xrptr < &xr[576]) { - xrptr[0] = 0; - xrptr[1] = 0; - - xrptr += 2; - } - - return MAD_ERROR_NONE; -} - -# undef MASK -# undef MASK1BIT - -/* - * NAME: III_reorder() - * DESCRIPTION: reorder frequency lines of a short block into subband order - */ -static -void III_reorder(mad_fixed_t xr[576], struct channel const *channel, - unsigned char const sfbwidth[39]) -{ - mad_fixed_t tmp[32][3][6]; - unsigned int sb, l, f, w, sbw[3], sw[3]; - - /* this is probably wrong for 8000 Hz mixed blocks */ - - sb = 0; - if (channel->flags & mixed_block_flag) { - sb = 2; - - l = 0; - while (l < 36) - l += *sfbwidth++; - } - - for (w = 0; w < 3; ++w) { - sbw[w] = sb; - sw[w] = 0; - } - - f = *sfbwidth++; - w = 0; - - for (l = 18 * sb; l < 576; ++l) { - if (f-- == 0) { - f = *sfbwidth++ - 1; - w = (w + 1) % 3; - } - - tmp[sbw[w]][w][sw[w]++] = xr[l]; - - if (sw[w] == 6) { - sw[w] = 0; - ++sbw[w]; - } - } - - memcpy(&xr[18 * sb], &tmp[sb], (576 - 18 * sb) * sizeof(mad_fixed_t)); -} - -/* - * NAME: III_stereo() - * DESCRIPTION: perform joint stereo processing on a granule - */ -static -enum mad_error III_stereo(mad_fixed_t xr[2][576], - struct granule const *granule, - struct mad_header *header, - unsigned char const *sfbwidth) -{ - short modes[39]; - unsigned int sfbi, l, n, i; - - if (granule->ch[0].block_type != - granule->ch[1].block_type || - (granule->ch[0].flags & mixed_block_flag) != - (granule->ch[1].flags & mixed_block_flag)) - return MAD_ERROR_BADSTEREO; - - for (i = 0; i < 39; ++i) - modes[i] = header->mode_extension; - - /* intensity stereo */ - - if (header->mode_extension & I_STEREO) { - struct channel const *right_ch = &granule->ch[1]; - mad_fixed_t const *right_xr = xr[1]; - unsigned int is_pos; - - header->flags |= MAD_FLAG_I_STEREO; - - /* first determine which scalefactor bands are to be processed */ - - if (right_ch->block_type == 2) { - unsigned int lower, start, max, bound[3], w; - - lower = start = max = bound[0] = bound[1] = bound[2] = 0; - - sfbi = l = 0; - - if (right_ch->flags & mixed_block_flag) { - while (l < 36) { - n = sfbwidth[sfbi++]; - - for (i = 0; i < n; ++i) { - if (right_xr[i]) { - lower = sfbi; - break; - } - } - - right_xr += n; - l += n; - } - - start = sfbi; - } - - w = 0; - while (l < 576) { - n = sfbwidth[sfbi++]; - - for (i = 0; i < n; ++i) { - if (right_xr[i]) { - max = bound[w] = sfbi; - break; - } - } - - right_xr += n; - l += n; - w = (w + 1) % 3; - } - - if (max) - lower = start; - - /* long blocks */ - - for (i = 0; i < lower; ++i) - modes[i] = header->mode_extension & ~I_STEREO; - - /* short blocks */ - - w = 0; - for (i = start; i < max; ++i) { - if (i < bound[w]) - modes[i] = header->mode_extension & ~I_STEREO; - - w = (w + 1) % 3; - } - } - else { /* right_ch->block_type != 2 */ - unsigned int bound; - - bound = 0; - for (sfbi = l = 0; l < 576; l += n) { - n = sfbwidth[sfbi++]; - - for (i = 0; i < n; ++i) { - if (right_xr[i]) { - bound = sfbi; - break; - } - } - - right_xr += n; - } - - for (i = 0; i < bound; ++i) - modes[i] = header->mode_extension & ~I_STEREO; - } - - /* now do the actual processing */ - - if (header->flags & MAD_FLAG_LSF_EXT) { - unsigned char const *illegal_pos = granule[1].ch[1].scalefac; - mad_fixed_t const *lsf_scale; - - /* intensity_scale */ - lsf_scale = is_lsf_table[right_ch->scalefac_compress & 0x1]; - - for (sfbi = l = 0; l < 576; ++sfbi, l += n) { - n = sfbwidth[sfbi]; - - if (!(modes[sfbi] & I_STEREO)) - continue; - - if (illegal_pos[sfbi]) { - modes[sfbi] &= ~I_STEREO; - continue; - } - - is_pos = right_ch->scalefac[sfbi]; - - for (i = 0; i < n; ++i) { - register mad_fixed_t left; - - left = xr[0][l + i]; - - if (is_pos == 0) - xr[1][l + i] = left; - else { - register mad_fixed_t opposite; - - opposite = mad_f_mul(left, lsf_scale[(is_pos - 1) / 2]); - - if (is_pos & 1) { - xr[0][l + i] = opposite; - xr[1][l + i] = left; - } - else - xr[1][l + i] = opposite; - } - } - } - } - else { /* !(header->flags & MAD_FLAG_LSF_EXT) */ - for (sfbi = l = 0; l < 576; ++sfbi, l += n) { - n = sfbwidth[sfbi]; - - if (!(modes[sfbi] & I_STEREO)) - continue; - - is_pos = right_ch->scalefac[sfbi]; - - if (is_pos >= 7) { /* illegal intensity position */ - modes[sfbi] &= ~I_STEREO; - continue; - } - - for (i = 0; i < n; ++i) { - register mad_fixed_t left; - - left = xr[0][l + i]; - - xr[0][l + i] = mad_f_mul(left, is_table[ is_pos]); - xr[1][l + i] = mad_f_mul(left, is_table[6 - is_pos]); - } - } - } - } - - /* middle/side stereo */ - - if (header->mode_extension & MS_STEREO) { - register mad_fixed_t invsqrt2; - - header->flags |= MAD_FLAG_MS_STEREO; - - invsqrt2 = root_table[3 + -2]; - - for (sfbi = l = 0; l < 576; ++sfbi, l += n) { - n = sfbwidth[sfbi]; - - if (modes[sfbi] != MS_STEREO) - continue; - - for (i = 0; i < n; ++i) { - register mad_fixed_t m, s; - - m = xr[0][l + i]; - s = xr[1][l + i]; - - xr[0][l + i] = mad_f_mul(m + s, invsqrt2); /* l = (m + s) / sqrt(2) */ - xr[1][l + i] = mad_f_mul(m - s, invsqrt2); /* r = (m - s) / sqrt(2) */ - } - } - } - - return MAD_ERROR_NONE; -} - -/* - * NAME: III_aliasreduce() - * DESCRIPTION: perform frequency line alias reduction - */ -static -void III_aliasreduce(mad_fixed_t xr[576], int lines) -{ - mad_fixed_t const *bound; - int i; - - bound = &xr[lines]; - for (xr += 18; xr < bound; xr += 18) { - for (i = 0; i < 8; ++i) { - register mad_fixed_t a, b; - register mad_fixed64hi_t hi; - register mad_fixed64lo_t lo; - - a = xr[-1 - i]; - b = xr[ i]; - -# if defined(ASO_ZEROCHECK) - if (a | b) { -# endif - MAD_F_ML0(hi, lo, a, cs[i]); - MAD_F_MLA(hi, lo, -b, ca[i]); - - xr[-1 - i] = MAD_F_MLZ(hi, lo); - - MAD_F_ML0(hi, lo, b, cs[i]); - MAD_F_MLA(hi, lo, a, ca[i]); - - xr[ i] = MAD_F_MLZ(hi, lo); -# if defined(ASO_ZEROCHECK) - } -# endif - } - } -} - -# if defined(ASO_IMDCT) -void III_imdct_l(mad_fixed_t const [18], mad_fixed_t [36], unsigned int); -# else -# if 1 -static -void fastsdct(mad_fixed_t const x[9], mad_fixed_t y[18]) -{ - mad_fixed_t a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12; - mad_fixed_t a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25; - mad_fixed_t m0, m1, m2, m3, m4, m5, m6, m7; - - enum { - c0 = MAD_F(0x1f838b8d), /* 2 * cos( 1 * PI / 18) */ - c1 = MAD_F(0x1bb67ae8), /* 2 * cos( 3 * PI / 18) */ - c2 = MAD_F(0x18836fa3), /* 2 * cos( 4 * PI / 18) */ - c3 = MAD_F(0x1491b752), /* 2 * cos( 5 * PI / 18) */ - c4 = MAD_F(0x0af1d43a), /* 2 * cos( 7 * PI / 18) */ - c5 = MAD_F(0x058e86a0), /* 2 * cos( 8 * PI / 18) */ - c6 = -MAD_F(0x1e11f642) /* 2 * cos(16 * PI / 18) */ - }; - - a0 = x[3] + x[5]; - a1 = x[3] - x[5]; - a2 = x[6] + x[2]; - a3 = x[6] - x[2]; - a4 = x[1] + x[7]; - a5 = x[1] - x[7]; - a6 = x[8] + x[0]; - a7 = x[8] - x[0]; - - a8 = a0 + a2; - a9 = a0 - a2; - a10 = a0 - a6; - a11 = a2 - a6; - a12 = a8 + a6; - a13 = a1 - a3; - a14 = a13 + a7; - a15 = a3 + a7; - a16 = a1 - a7; - a17 = a1 + a3; - - m0 = mad_f_mul(a17, -c3); - m1 = mad_f_mul(a16, -c0); - m2 = mad_f_mul(a15, -c4); - m3 = mad_f_mul(a14, -c1); - m4 = mad_f_mul(a5, -c1); - m5 = mad_f_mul(a11, -c6); - m6 = mad_f_mul(a10, -c5); - m7 = mad_f_mul(a9, -c2); - - a18 = x[4] + a4; - a19 = 2 * x[4] - a4; - a20 = a19 + m5; - a21 = a19 - m5; - a22 = a19 + m6; - a23 = m4 + m2; - a24 = m4 - m2; - a25 = m4 + m1; - - /* output to every other slot for convenience */ - - y[ 0] = a18 + a12; - y[ 2] = m0 - a25; - y[ 4] = m7 - a20; - y[ 6] = m3; - y[ 8] = a21 - m6; - y[10] = a24 - m1; - y[12] = a12 - 2 * a18; - y[14] = a23 + m0; - y[16] = a22 + m7; -} - -static inline -void sdctII(mad_fixed_t const x[18], mad_fixed_t X[18]) -{ - mad_fixed_t tmp[9]; - int i; - - /* scale[i] = 2 * cos(PI * (2 * i + 1) / (2 * 18)) */ - static mad_fixed_t const scale[9] = { - MAD_F(0x1fe0d3b4), MAD_F(0x1ee8dd47), MAD_F(0x1d007930), - MAD_F(0x1a367e59), MAD_F(0x16a09e66), MAD_F(0x125abcf8), - MAD_F(0x0d8616bc), MAD_F(0x08483ee1), MAD_F(0x02c9fad7) - }; - - /* divide the 18-point SDCT-II into two 9-point SDCT-IIs */ - - /* even input butterfly */ - - for (i = 0; i < 9; i += 3) { - tmp[i + 0] = x[i + 0] + x[18 - (i + 0) - 1]; - tmp[i + 1] = x[i + 1] + x[18 - (i + 1) - 1]; - tmp[i + 2] = x[i + 2] + x[18 - (i + 2) - 1]; - } - - fastsdct(tmp, &X[0]); - - /* odd input butterfly and scaling */ - - for (i = 0; i < 9; i += 3) { - tmp[i + 0] = mad_f_mul(x[i + 0] - x[18 - (i + 0) - 1], scale[i + 0]); - tmp[i + 1] = mad_f_mul(x[i + 1] - x[18 - (i + 1) - 1], scale[i + 1]); - tmp[i + 2] = mad_f_mul(x[i + 2] - x[18 - (i + 2) - 1], scale[i + 2]); - } - - fastsdct(tmp, &X[1]); - - /* output accumulation */ - - for (i = 3; i < 18; i += 8) { - X[i + 0] -= X[(i + 0) - 2]; - X[i + 2] -= X[(i + 2) - 2]; - X[i + 4] -= X[(i + 4) - 2]; - X[i + 6] -= X[(i + 6) - 2]; - } -} - -static inline -void dctIV(mad_fixed_t const y[18], mad_fixed_t X[18]) -{ - mad_fixed_t tmp[18]; - int i; - - /* scale[i] = 2 * cos(PI * (2 * i + 1) / (4 * 18)) */ - static mad_fixed_t const scale[18] = { - MAD_F(0x1ff833fa), MAD_F(0x1fb9ea93), MAD_F(0x1f3dd120), - MAD_F(0x1e84d969), MAD_F(0x1d906bcf), MAD_F(0x1c62648b), - MAD_F(0x1afd100f), MAD_F(0x1963268b), MAD_F(0x1797c6a4), - MAD_F(0x159e6f5b), MAD_F(0x137af940), MAD_F(0x11318ef3), - MAD_F(0x0ec6a507), MAD_F(0x0c3ef153), MAD_F(0x099f61c5), - MAD_F(0x06ed12c5), MAD_F(0x042d4544), MAD_F(0x0165547c) - }; - - /* scaling */ - - for (i = 0; i < 18; i += 3) { - tmp[i + 0] = mad_f_mul(y[i + 0], scale[i + 0]); - tmp[i + 1] = mad_f_mul(y[i + 1], scale[i + 1]); - tmp[i + 2] = mad_f_mul(y[i + 2], scale[i + 2]); - } - - /* SDCT-II */ - - sdctII(tmp, X); - - /* scale reduction and output accumulation */ - - X[0] /= 2; - for (i = 1; i < 17; i += 4) { - X[i + 0] = X[i + 0] / 2 - X[(i + 0) - 1]; - X[i + 1] = X[i + 1] / 2 - X[(i + 1) - 1]; - X[i + 2] = X[i + 2] / 2 - X[(i + 2) - 1]; - X[i + 3] = X[i + 3] / 2 - X[(i + 3) - 1]; - } - X[17] = X[17] / 2 - X[16]; -} - -/* - * NAME: imdct36 - * DESCRIPTION: perform X[18]->x[36] IMDCT using Szu-Wei Lee's fast algorithm - */ -static inline -void imdct36(mad_fixed_t const x[18], mad_fixed_t y[36]) -{ - mad_fixed_t tmp[18]; - int i; - - /* DCT-IV */ - - dctIV(x, tmp); - - /* convert 18-point DCT-IV to 36-point IMDCT */ - - for (i = 0; i < 9; i += 3) { - y[i + 0] = tmp[9 + (i + 0)]; - y[i + 1] = tmp[9 + (i + 1)]; - y[i + 2] = tmp[9 + (i + 2)]; - } - for (i = 9; i < 27; i += 3) { - y[i + 0] = -tmp[36 - (9 + (i + 0)) - 1]; - y[i + 1] = -tmp[36 - (9 + (i + 1)) - 1]; - y[i + 2] = -tmp[36 - (9 + (i + 2)) - 1]; - } - for (i = 27; i < 36; i += 3) { - y[i + 0] = -tmp[(i + 0) - 27]; - y[i + 1] = -tmp[(i + 1) - 27]; - y[i + 2] = -tmp[(i + 2) - 27]; - } -} -# else -/* - * NAME: imdct36 - * DESCRIPTION: perform X[18]->x[36] IMDCT - */ -static inline -void imdct36(mad_fixed_t const X[18], mad_fixed_t x[36]) -{ - mad_fixed_t t0, t1, t2, t3, t4, t5, t6, t7; - mad_fixed_t t8, t9, t10, t11, t12, t13, t14, t15; - register mad_fixed64hi_t hi; - register mad_fixed64lo_t lo; - - MAD_F_ML0(hi, lo, X[4], MAD_F(0x0ec835e8)); - MAD_F_MLA(hi, lo, X[13], MAD_F(0x061f78aa)); - - t6 = MAD_F_MLZ(hi, lo); - - MAD_F_MLA(hi, lo, (t14 = X[1] - X[10]), -MAD_F(0x061f78aa)); - MAD_F_MLA(hi, lo, (t15 = X[7] + X[16]), -MAD_F(0x0ec835e8)); - - t0 = MAD_F_MLZ(hi, lo); - - MAD_F_MLA(hi, lo, (t8 = X[0] - X[11] - X[12]), MAD_F(0x0216a2a2)); - MAD_F_MLA(hi, lo, (t9 = X[2] - X[9] - X[14]), MAD_F(0x09bd7ca0)); - MAD_F_MLA(hi, lo, (t10 = X[3] - X[8] - X[15]), -MAD_F(0x0cb19346)); - MAD_F_MLA(hi, lo, (t11 = X[5] - X[6] - X[17]), -MAD_F(0x0fdcf549)); - - x[7] = MAD_F_MLZ(hi, lo); - x[10] = -x[7]; - - MAD_F_ML0(hi, lo, t8, -MAD_F(0x0cb19346)); - MAD_F_MLA(hi, lo, t9, MAD_F(0x0fdcf549)); - MAD_F_MLA(hi, lo, t10, MAD_F(0x0216a2a2)); - MAD_F_MLA(hi, lo, t11, -MAD_F(0x09bd7ca0)); - - x[19] = x[34] = MAD_F_MLZ(hi, lo) - t0; - - t12 = X[0] - X[3] + X[8] - X[11] - X[12] + X[15]; - t13 = X[2] + X[5] - X[6] - X[9] - X[14] - X[17]; - - MAD_F_ML0(hi, lo, t12, -MAD_F(0x0ec835e8)); - MAD_F_MLA(hi, lo, t13, MAD_F(0x061f78aa)); - - x[22] = x[31] = MAD_F_MLZ(hi, lo) + t0; - - MAD_F_ML0(hi, lo, X[1], -MAD_F(0x09bd7ca0)); - MAD_F_MLA(hi, lo, X[7], MAD_F(0x0216a2a2)); - MAD_F_MLA(hi, lo, X[10], -MAD_F(0x0fdcf549)); - MAD_F_MLA(hi, lo, X[16], MAD_F(0x0cb19346)); - - t1 = MAD_F_MLZ(hi, lo) + t6; - - MAD_F_ML0(hi, lo, X[0], MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[2], MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[6], MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[9], MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[11], MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[14], MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[15], -MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0f9ee890)); - - x[6] = MAD_F_MLZ(hi, lo) + t1; - x[11] = -x[6]; - - MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[2], -MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[3], MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[5], MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[6], MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[8], -MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[12], -MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[14], MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[15], MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[17], MAD_F(0x04cfb0e2)); - - x[23] = x[30] = MAD_F_MLZ(hi, lo) + t1; - - MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[2], MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[3], -MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[5], MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[6], MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[9], -MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[11], MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[14], MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[15], MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0acf37ad)); - - x[18] = x[35] = MAD_F_MLZ(hi, lo) - t1; - - MAD_F_ML0(hi, lo, X[4], MAD_F(0x061f78aa)); - MAD_F_MLA(hi, lo, X[13], -MAD_F(0x0ec835e8)); - - t7 = MAD_F_MLZ(hi, lo); - - MAD_F_MLA(hi, lo, X[1], -MAD_F(0x0cb19346)); - MAD_F_MLA(hi, lo, X[7], MAD_F(0x0fdcf549)); - MAD_F_MLA(hi, lo, X[10], MAD_F(0x0216a2a2)); - MAD_F_MLA(hi, lo, X[16], -MAD_F(0x09bd7ca0)); - - t2 = MAD_F_MLZ(hi, lo); - - MAD_F_MLA(hi, lo, X[0], MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[2], MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[5], MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[9], MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[12], MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[14], MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[15], MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[17], MAD_F(0x0f426cb5)); - - x[5] = MAD_F_MLZ(hi, lo); - x[12] = -x[5]; - - MAD_F_ML0(hi, lo, X[0], MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[2], -MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[3], MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[6], -MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[8], MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[11], MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[12], -MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[14], MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[15], MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0bcbe352)); - - x[0] = MAD_F_MLZ(hi, lo) + t2; - x[17] = -x[0]; - - MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[2], -MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[3], -MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[5], MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[6], MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[8], MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[9], MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[11], -MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[14], -MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[17], -MAD_F(0x03768962)); - - x[24] = x[29] = MAD_F_MLZ(hi, lo) + t2; - - MAD_F_ML0(hi, lo, X[1], -MAD_F(0x0216a2a2)); - MAD_F_MLA(hi, lo, X[7], -MAD_F(0x09bd7ca0)); - MAD_F_MLA(hi, lo, X[10], MAD_F(0x0cb19346)); - MAD_F_MLA(hi, lo, X[16], MAD_F(0x0fdcf549)); - - t3 = MAD_F_MLZ(hi, lo) + t7; - - MAD_F_ML0(hi, lo, X[0], MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[2], MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[3], -MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[5], -MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[6], MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[8], MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[12], MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[14], MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0ffc19fd)); - - x[8] = MAD_F_MLZ(hi, lo) + t3; - x[9] = -x[8]; - - MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[2], MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[3], MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[8], MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[9], MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[11], -MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[14], -MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[15], MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[17], MAD_F(0x07635284)); - - x[21] = x[32] = MAD_F_MLZ(hi, lo) + t3; - - MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[2], MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[3], MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[6], -MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[8], MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[9], MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[12], MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[14], MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[15], -MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0898c779)); - - x[20] = x[33] = MAD_F_MLZ(hi, lo) - t3; - - MAD_F_ML0(hi, lo, t14, -MAD_F(0x0ec835e8)); - MAD_F_MLA(hi, lo, t15, MAD_F(0x061f78aa)); - - t4 = MAD_F_MLZ(hi, lo) - t7; - - MAD_F_ML0(hi, lo, t12, MAD_F(0x061f78aa)); - MAD_F_MLA(hi, lo, t13, MAD_F(0x0ec835e8)); - - x[4] = MAD_F_MLZ(hi, lo) + t4; - x[13] = -x[4]; - - MAD_F_ML0(hi, lo, t8, MAD_F(0x09bd7ca0)); - MAD_F_MLA(hi, lo, t9, -MAD_F(0x0216a2a2)); - MAD_F_MLA(hi, lo, t10, MAD_F(0x0fdcf549)); - MAD_F_MLA(hi, lo, t11, -MAD_F(0x0cb19346)); - - x[1] = MAD_F_MLZ(hi, lo) + t4; - x[16] = -x[1]; - - MAD_F_ML0(hi, lo, t8, -MAD_F(0x0fdcf549)); - MAD_F_MLA(hi, lo, t9, -MAD_F(0x0cb19346)); - MAD_F_MLA(hi, lo, t10, -MAD_F(0x09bd7ca0)); - MAD_F_MLA(hi, lo, t11, -MAD_F(0x0216a2a2)); - - x[25] = x[28] = MAD_F_MLZ(hi, lo) + t4; - - MAD_F_ML0(hi, lo, X[1], -MAD_F(0x0fdcf549)); - MAD_F_MLA(hi, lo, X[7], -MAD_F(0x0cb19346)); - MAD_F_MLA(hi, lo, X[10], -MAD_F(0x09bd7ca0)); - MAD_F_MLA(hi, lo, X[16], -MAD_F(0x0216a2a2)); - - t5 = MAD_F_MLZ(hi, lo) - t6; - - MAD_F_ML0(hi, lo, X[0], MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[2], MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[3], MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[5], MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[6], MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[8], -MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[9], MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[11], -MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[12], MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[14], -MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[15], MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0d7e8807)); - - x[2] = MAD_F_MLZ(hi, lo) + t5; - x[15] = -x[2]; - - MAD_F_ML0(hi, lo, X[0], MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[2], MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[3], MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[5], MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[6], -MAD_F(0x00b2aa3e)); - MAD_F_MLA(hi, lo, X[8], MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[9], -MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[11], MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[14], MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[17], MAD_F(0x0e313245)); - - x[3] = MAD_F_MLZ(hi, lo) + t5; - x[14] = -x[3]; - - MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0ffc19fd)); - MAD_F_MLA(hi, lo, X[2], -MAD_F(0x0f9ee890)); - MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0f426cb5)); - MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0e313245)); - MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0d7e8807)); - MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0bcbe352)); - MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0acf37ad)); - MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0898c779)); - MAD_F_MLA(hi, lo, X[12], -MAD_F(0x07635284)); - MAD_F_MLA(hi, lo, X[14], -MAD_F(0x04cfb0e2)); - MAD_F_MLA(hi, lo, X[15], -MAD_F(0x03768962)); - MAD_F_MLA(hi, lo, X[17], -MAD_F(0x00b2aa3e)); - - x[26] = x[27] = MAD_F_MLZ(hi, lo) + t5; -} -# endif - -/* - * NAME: III_imdct_l() - * DESCRIPTION: perform IMDCT and windowing for long blocks - */ -static -void III_imdct_l(mad_fixed_t const X[18], mad_fixed_t z[36], - unsigned int block_type) -{ - unsigned int i; - - /* IMDCT */ - - imdct36(X, z); - - /* windowing */ - - switch (block_type) { - case 0: /* normal window */ -# if defined(ASO_INTERLEAVE1) - { - register mad_fixed_t tmp1, tmp2; - - tmp1 = window_l[0]; - tmp2 = window_l[1]; - - for (i = 0; i < 34; i += 2) { - z[i + 0] = mad_f_mul(z[i + 0], tmp1); - tmp1 = window_l[i + 2]; - z[i + 1] = mad_f_mul(z[i + 1], tmp2); - tmp2 = window_l[i + 3]; - } - - z[34] = mad_f_mul(z[34], tmp1); - z[35] = mad_f_mul(z[35], tmp2); - } -# elif defined(ASO_INTERLEAVE2) - { - register mad_fixed_t tmp1, tmp2; - - tmp1 = z[0]; - tmp2 = window_l[0]; - - for (i = 0; i < 35; ++i) { - z[i] = mad_f_mul(tmp1, tmp2); - tmp1 = z[i + 1]; - tmp2 = window_l[i + 1]; - } - - z[35] = mad_f_mul(tmp1, tmp2); - } -# elif 1 - for (i = 0; i < 36; i += 4) { - z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]); - z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]); - z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]); - z[i + 3] = mad_f_mul(z[i + 3], window_l[i + 3]); - } -# else - for (i = 0; i < 36; ++i) z[i] = mad_f_mul(z[i], window_l[i]); -# endif - break; - - case 1: /* start block */ - for (i = 0; i < 18; i += 3) { - z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]); - z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]); - z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]); - } - /* (i = 18; i < 24; ++i) z[i] unchanged */ - for (i = 24; i < 30; ++i) z[i] = mad_f_mul(z[i], window_s[i - 18]); - for (i = 30; i < 36; ++i) z[i] = 0; - break; - - case 3: /* stop block */ - for (i = 0; i < 6; ++i) z[i] = 0; - for (i = 6; i < 12; ++i) z[i] = mad_f_mul(z[i], window_s[i - 6]); - /* (i = 12; i < 18; ++i) z[i] unchanged */ - for (i = 18; i < 36; i += 3) { - z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]); - z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]); - z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]); - } - break; - } -} -# endif /* ASO_IMDCT */ - -/* - * NAME: III_imdct_s() - * DESCRIPTION: perform IMDCT and windowing for short blocks - */ -static -void III_imdct_s(mad_fixed_t const X[18], mad_fixed_t z[36]) -{ - mad_fixed_t y[36], *yptr; - mad_fixed_t const *wptr; - int w, i; - register mad_fixed64hi_t hi; - register mad_fixed64lo_t lo; - - /* IMDCT */ - - yptr = &y[0]; - - for (w = 0; w < 3; ++w) { - register mad_fixed_t const (*s)[6]; - - s = imdct_s; - - for (i = 0; i < 3; ++i) { - MAD_F_ML0(hi, lo, X[0], (*s)[0]); - MAD_F_MLA(hi, lo, X[1], (*s)[1]); - MAD_F_MLA(hi, lo, X[2], (*s)[2]); - MAD_F_MLA(hi, lo, X[3], (*s)[3]); - MAD_F_MLA(hi, lo, X[4], (*s)[4]); - MAD_F_MLA(hi, lo, X[5], (*s)[5]); - - yptr[i + 0] = MAD_F_MLZ(hi, lo); - yptr[5 - i] = -yptr[i + 0]; - - ++s; - - MAD_F_ML0(hi, lo, X[0], (*s)[0]); - MAD_F_MLA(hi, lo, X[1], (*s)[1]); - MAD_F_MLA(hi, lo, X[2], (*s)[2]); - MAD_F_MLA(hi, lo, X[3], (*s)[3]); - MAD_F_MLA(hi, lo, X[4], (*s)[4]); - MAD_F_MLA(hi, lo, X[5], (*s)[5]); - - yptr[ i + 6] = MAD_F_MLZ(hi, lo); - yptr[11 - i] = yptr[i + 6]; - - ++s; - } - - yptr += 12; - X += 6; - } - - /* windowing, overlapping and concatenation */ - - yptr = &y[0]; - wptr = &window_s[0]; - - for (i = 0; i < 6; ++i) { - z[i + 0] = 0; - z[i + 6] = mad_f_mul(yptr[ 0 + 0], wptr[0]); - - MAD_F_ML0(hi, lo, yptr[ 0 + 6], wptr[6]); - MAD_F_MLA(hi, lo, yptr[12 + 0], wptr[0]); - - z[i + 12] = MAD_F_MLZ(hi, lo); - - MAD_F_ML0(hi, lo, yptr[12 + 6], wptr[6]); - MAD_F_MLA(hi, lo, yptr[24 + 0], wptr[0]); - - z[i + 18] = MAD_F_MLZ(hi, lo); - - z[i + 24] = mad_f_mul(yptr[24 + 6], wptr[6]); - z[i + 30] = 0; - - ++yptr; - ++wptr; - } -} - -/* - * NAME: III_overlap() - * DESCRIPTION: perform overlap-add of windowed IMDCT outputs - */ -static -void III_overlap(mad_fixed_t const output[36], mad_fixed_t overlap[18], - mad_fixed_t sample[18][32], unsigned int sb) -{ - unsigned int i; - -# if defined(ASO_INTERLEAVE2) - { - register mad_fixed_t tmp1, tmp2; - - tmp1 = overlap[0]; - tmp2 = overlap[1]; - - for (i = 0; i < 16; i += 2) { - sample[i + 0][sb] = output[i + 0 + 0] + tmp1; - overlap[i + 0] = output[i + 0 + 18]; - tmp1 = overlap[i + 2]; - - sample[i + 1][sb] = output[i + 1 + 0] + tmp2; - overlap[i + 1] = output[i + 1 + 18]; - tmp2 = overlap[i + 3]; - } - - sample[16][sb] = output[16 + 0] + tmp1; - overlap[16] = output[16 + 18]; - sample[17][sb] = output[17 + 0] + tmp2; - overlap[17] = output[17 + 18]; - } -# elif 0 - for (i = 0; i < 18; i += 2) { - sample[i + 0][sb] = output[i + 0 + 0] + overlap[i + 0]; - overlap[i + 0] = output[i + 0 + 18]; - - sample[i + 1][sb] = output[i + 1 + 0] + overlap[i + 1]; - overlap[i + 1] = output[i + 1 + 18]; - } -# else - for (i = 0; i < 18; ++i) { - sample[i][sb] = output[i + 0] + overlap[i]; - overlap[i] = output[i + 18]; - } -# endif -} - -/* - * NAME: III_overlap_z() - * DESCRIPTION: perform "overlap-add" of zero IMDCT outputs - */ -static inline -void III_overlap_z(mad_fixed_t overlap[18], - mad_fixed_t sample[18][32], unsigned int sb) -{ - unsigned int i; - -# if defined(ASO_INTERLEAVE2) - { - register mad_fixed_t tmp1, tmp2; - - tmp1 = overlap[0]; - tmp2 = overlap[1]; - - for (i = 0; i < 16; i += 2) { - sample[i + 0][sb] = tmp1; - overlap[i + 0] = 0; - tmp1 = overlap[i + 2]; - - sample[i + 1][sb] = tmp2; - overlap[i + 1] = 0; - tmp2 = overlap[i + 3]; - } - - sample[16][sb] = tmp1; - overlap[16] = 0; - sample[17][sb] = tmp2; - overlap[17] = 0; - } -# else - for (i = 0; i < 18; ++i) { - sample[i][sb] = overlap[i]; - overlap[i] = 0; - } -# endif -} - -/* - * NAME: III_freqinver() - * DESCRIPTION: perform subband frequency inversion for odd sample lines - */ -static -void III_freqinver(mad_fixed_t sample[18][32], unsigned int sb) -{ - unsigned int i; - -# if 1 || defined(ASO_INTERLEAVE1) || defined(ASO_INTERLEAVE2) - { - register mad_fixed_t tmp1, tmp2; - - tmp1 = sample[1][sb]; - tmp2 = sample[3][sb]; - - for (i = 1; i < 13; i += 4) { - sample[i + 0][sb] = -tmp1; - tmp1 = sample[i + 4][sb]; - sample[i + 2][sb] = -tmp2; - tmp2 = sample[i + 6][sb]; - } - - sample[13][sb] = -tmp1; - tmp1 = sample[17][sb]; - sample[15][sb] = -tmp2; - sample[17][sb] = -tmp1; - } -# else - for (i = 1; i < 18; i += 2) - sample[i][sb] = -sample[i][sb]; -# endif -} - -/* - * NAME: III_decode() - * DESCRIPTION: decode frame main_data - */ -static -enum mad_error III_decode(struct mad_bitptr *ptr, struct mad_frame *frame, - struct sideinfo *si, unsigned int nch) -{ - struct mad_header *header = &frame->header; - unsigned int sfreqi, ngr, gr; - - { - unsigned int sfreq; - - sfreq = header->samplerate; - if (header->flags & MAD_FLAG_MPEG_2_5_EXT) - sfreq *= 2; - - /* 48000 => 0, 44100 => 1, 32000 => 2, - 24000 => 3, 22050 => 4, 16000 => 5 */ - sfreqi = ((sfreq >> 7) & 0x000f) + - ((sfreq >> 15) & 0x0001) - 8; - - if (header->flags & MAD_FLAG_MPEG_2_5_EXT) - sfreqi += 3; - } - - /* scalefactors, Huffman decoding, requantization */ - - ngr = (header->flags & MAD_FLAG_LSF_EXT) ? 1 : 2; - - for (gr = 0; gr < ngr; ++gr) { - struct granule *granule = &si->gr[gr]; - unsigned char const *sfbwidth[2]; - mad_fixed_t xr[2][576]; - unsigned int ch; - enum mad_error error; - - for (ch = 0; ch < nch; ++ch) { - struct channel *channel = &granule->ch[ch]; - unsigned int part2_length; - - sfbwidth[ch] = sfbwidth_table[sfreqi].l; - if (channel->block_type == 2) { - sfbwidth[ch] = (channel->flags & mixed_block_flag) ? - sfbwidth_table[sfreqi].m : sfbwidth_table[sfreqi].s; - } - - if (header->flags & MAD_FLAG_LSF_EXT) { - part2_length = III_scalefactors_lsf(ptr, channel, - ch == 0 ? 0 : &si->gr[1].ch[1], - header->mode_extension); - } - else { - part2_length = III_scalefactors(ptr, channel, &si->gr[0].ch[ch], - gr == 0 ? 0 : si->scfsi[ch]); - } - - error = III_huffdecode(ptr, xr[ch], channel, sfbwidth[ch], part2_length); - if (error) - return error; - } - - /* joint stereo processing */ - - if (header->mode == MAD_MODE_JOINT_STEREO && header->mode_extension) { - error = III_stereo(xr, granule, header, sfbwidth[0]); - if (error) - return error; - } - - /* reordering, alias reduction, IMDCT, overlap-add, frequency inversion */ - - for (ch = 0; ch < nch; ++ch) { - struct channel const *channel = &granule->ch[ch]; - mad_fixed_t (*sample)[32] = &frame->sbsample[ch][18 * gr]; - unsigned int sb, l, i, sblimit; - mad_fixed_t output[36]; - - if (channel->block_type == 2) { - III_reorder(xr[ch], channel, sfbwidth[ch]); - -# if !defined(OPT_STRICT) - /* - * According to ISO/IEC 11172-3, "Alias reduction is not applied for - * granules with block_type == 2 (short block)." However, other - * sources suggest alias reduction should indeed be performed on the - * lower two subbands of mixed blocks. Most other implementations do - * this, so by default we will too. - */ - if (channel->flags & mixed_block_flag) - III_aliasreduce(xr[ch], 36); -# endif - } - else - III_aliasreduce(xr[ch], 576); - - l = 0; - - /* subbands 0-1 */ - - if (channel->block_type != 2 || (channel->flags & mixed_block_flag)) { - unsigned int block_type; - - block_type = channel->block_type; - if (channel->flags & mixed_block_flag) - block_type = 0; - - /* long blocks */ - for (sb = 0; sb < 2; ++sb, l += 18) { - III_imdct_l(&xr[ch][l], output, block_type); - III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); - } - } - else { - /* short blocks */ - for (sb = 0; sb < 2; ++sb, l += 18) { - III_imdct_s(&xr[ch][l], output); - III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); - } - } - - III_freqinver(sample, 1); - - /* (nonzero) subbands 2-31 */ - - i = 576; - while (i > 36 && xr[ch][i - 1] == 0) - --i; - - sblimit = 32 - (576 - i) / 18; - - if (channel->block_type != 2) { - /* long blocks */ - for (sb = 2; sb < sblimit; ++sb, l += 18) { - III_imdct_l(&xr[ch][l], output, channel->block_type); - III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); - - if (sb & 1) - III_freqinver(sample, sb); - } - } - else { - /* short blocks */ - for (sb = 2; sb < sblimit; ++sb, l += 18) { - III_imdct_s(&xr[ch][l], output); - III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); - - if (sb & 1) - III_freqinver(sample, sb); - } - } - - /* remaining (zero) subbands */ - - for (sb = sblimit; sb < 32; ++sb) { - III_overlap_z((*frame->overlap)[ch][sb], sample, sb); - - if (sb & 1) - III_freqinver(sample, sb); - } - } - } - - return MAD_ERROR_NONE; -} - -/* - * NAME: layer->III() - * DESCRIPTION: decode a single Layer III frame - */ -int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame) -{ - struct mad_header *header = &frame->header; - unsigned int nch, priv_bitlen, next_md_begin = 0; - unsigned int si_len, data_bitlen, md_len; - unsigned int frame_space, frame_used, frame_free; - struct mad_bitptr ptr; - struct sideinfo si; - enum mad_error error; - int result = 0; - - /* allocate Layer III dynamic structures */ - - if (stream->main_data == 0) { - stream->main_data = malloc(MAD_BUFFER_MDLEN); - if (stream->main_data == 0) { - stream->error = MAD_ERROR_NOMEM; - return -1; - } - } - - if (frame->overlap == 0) { - frame->overlap = calloc(2 * 32 * 18, sizeof(mad_fixed_t)); - if (frame->overlap == 0) { - stream->error = MAD_ERROR_NOMEM; - return -1; - } - } - - nch = MAD_NCHANNELS(header); - si_len = (header->flags & MAD_FLAG_LSF_EXT) ? - (nch == 1 ? 9 : 17) : (nch == 1 ? 17 : 32); - - /* check frame sanity */ - - if (stream->next_frame - mad_bit_nextbyte(&stream->ptr) < - (signed int) si_len) { - stream->error = MAD_ERROR_BADFRAMELEN; - stream->md_len = 0; - return -1; - } - - /* check CRC word */ - - if (header->flags & MAD_FLAG_PROTECTION) { - header->crc_check = - mad_bit_crc(stream->ptr, si_len * CHAR_BIT, header->crc_check); - - if (header->crc_check != header->crc_target && - !(frame->options & MAD_OPTION_IGNORECRC)) { - stream->error = MAD_ERROR_BADCRC; - result = -1; - } - } - - /* decode frame side information */ - - error = III_sideinfo(&stream->ptr, nch, header->flags & MAD_FLAG_LSF_EXT, - &si, &data_bitlen, &priv_bitlen); - if (error && result == 0) { - stream->error = error; - result = -1; - } - - header->flags |= priv_bitlen; - header->private_bits |= si.private_bits; - - /* find main_data of next frame */ - - { - struct mad_bitptr peek; - unsigned long header; - - mad_bit_init(&peek, stream->next_frame); - - header = mad_bit_read(&peek, 32); - if ((header & 0xffe60000L) /* syncword | layer */ == 0xffe20000L) { - if (!(header & 0x00010000L)) /* protection_bit */ - mad_bit_skip(&peek, 16); /* crc_check */ - - next_md_begin = - mad_bit_read(&peek, (header & 0x00080000L) /* ID */ ? 9 : 8); - } - - mad_bit_finish(&peek); - } - - /* find main_data of this frame */ - - frame_space = stream->next_frame - mad_bit_nextbyte(&stream->ptr); - - if (next_md_begin > si.main_data_begin + frame_space) - next_md_begin = 0; - - md_len = si.main_data_begin + frame_space - next_md_begin; - - frame_used = 0; - - if (si.main_data_begin == 0) { - ptr = stream->ptr; - stream->md_len = 0; - - frame_used = md_len; - } - else { - if (si.main_data_begin > stream->md_len) { - if (result == 0) { - stream->error = MAD_ERROR_BADDATAPTR; - result = -1; - } - } - else { - mad_bit_init(&ptr, - *stream->main_data + stream->md_len - si.main_data_begin); - - if (md_len > si.main_data_begin) { - assert(stream->md_len + md_len - - si.main_data_begin <= MAD_BUFFER_MDLEN); - - memcpy(*stream->main_data + stream->md_len, - mad_bit_nextbyte(&stream->ptr), - frame_used = md_len - si.main_data_begin); - stream->md_len += frame_used; - } - } - } - - frame_free = frame_space - frame_used; - - /* decode main_data */ - - if (result == 0) { - error = III_decode(&ptr, frame, &si, nch); - if (error) { - stream->error = error; - result = -1; - } - - /* designate ancillary bits */ - - stream->anc_ptr = ptr; - stream->anc_bitlen = md_len * CHAR_BIT - data_bitlen; - } - -# if 0 && defined(DEBUG) - fprintf(stderr, - "main_data_begin:%u, md_len:%u, frame_free:%u, " - "data_bitlen:%u, anc_bitlen: %u\n", - si.main_data_begin, md_len, frame_free, - data_bitlen, stream->anc_bitlen); -# endif - - /* preload main_data buffer with up to 511 bytes for next frame(s) */ - - if (frame_free >= next_md_begin) { - memcpy(*stream->main_data, - stream->next_frame - next_md_begin, next_md_begin); - stream->md_len = next_md_begin; - } - else { - if (md_len < si.main_data_begin) { - unsigned int extra; - - extra = si.main_data_begin - md_len; - if (extra + frame_free > next_md_begin) - extra = next_md_begin - frame_free; - - if (extra < stream->md_len) { - memmove(*stream->main_data, - *stream->main_data + stream->md_len - extra, extra); - stream->md_len = extra; - } - } - else - stream->md_len = 0; - - memcpy(*stream->main_data + stream->md_len, - stream->next_frame - frame_free, frame_free); - stream->md_len += frame_free; - } - - return result; -} - -# ifdef _MSC_VER -# pragma warning(pop) -# endif diff --git a/libmad/src/layer3.h b/libmad/src/layer3.h deleted file mode 100644 index 2504d46..0000000 --- a/libmad/src/layer3.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: layer3.h,v 1.10 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_LAYER3_H -# define LIBMAD_LAYER3_H - -# include "stream.h" -# include "frame.h" - -int mad_layer_III(struct mad_stream *, struct mad_frame *); - -# endif diff --git a/libmad/src/qc_table.dat b/libmad/src/qc_table.dat deleted file mode 100644 index 35a2223..0000000 --- a/libmad/src/qc_table.dat +++ /dev/null @@ -1,77 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: qc_table.dat,v 1.7 2004/01/23 09:41:32 rob Exp $ - */ - -/* - * These are the Layer II classes of quantization. - * The table is derived from Table B.4 of ISO/IEC 11172-3. - */ - - { 3, 2, 5, - MAD_F(0x15555555) /* 1.33333333333 => 1.33333333209, e 0.00000000124 */, - MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, - { 5, 3, 7, - MAD_F(0x1999999a) /* 1.60000000000 => 1.60000000149, e -0.00000000149 */, - MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, - { 7, 0, 3, - MAD_F(0x12492492) /* 1.14285714286 => 1.14285714179, e 0.00000000107 */, - MAD_F(0x04000000) /* 0.25000000000 => 0.25000000000, e 0.00000000000 */ }, - { 9, 4, 10, - MAD_F(0x1c71c71c) /* 1.77777777777 => 1.77777777612, e 0.00000000165 */, - MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, - { 15, 0, 4, - MAD_F(0x11111111) /* 1.06666666666 => 1.06666666642, e 0.00000000024 */, - MAD_F(0x02000000) /* 0.12500000000 => 0.12500000000, e 0.00000000000 */ }, - { 31, 0, 5, - MAD_F(0x10842108) /* 1.03225806452 => 1.03225806355, e 0.00000000097 */, - MAD_F(0x01000000) /* 0.06250000000 => 0.06250000000, e 0.00000000000 */ }, - { 63, 0, 6, - MAD_F(0x10410410) /* 1.01587301587 => 1.01587301493, e 0.00000000094 */, - MAD_F(0x00800000) /* 0.03125000000 => 0.03125000000, e 0.00000000000 */ }, - { 127, 0, 7, - MAD_F(0x10204081) /* 1.00787401575 => 1.00787401572, e 0.00000000003 */, - MAD_F(0x00400000) /* 0.01562500000 => 0.01562500000, e 0.00000000000 */ }, - { 255, 0, 8, - MAD_F(0x10101010) /* 1.00392156863 => 1.00392156839, e 0.00000000024 */, - MAD_F(0x00200000) /* 0.00781250000 => 0.00781250000, e 0.00000000000 */ }, - { 511, 0, 9, - MAD_F(0x10080402) /* 1.00195694716 => 1.00195694715, e 0.00000000001 */, - MAD_F(0x00100000) /* 0.00390625000 => 0.00390625000, e 0.00000000000 */ }, - { 1023, 0, 10, - MAD_F(0x10040100) /* 1.00097751711 => 1.00097751617, e 0.00000000094 */, - MAD_F(0x00080000) /* 0.00195312500 => 0.00195312500, e 0.00000000000 */ }, - { 2047, 0, 11, - MAD_F(0x10020040) /* 1.00048851979 => 1.00048851967, e 0.00000000012 */, - MAD_F(0x00040000) /* 0.00097656250 => 0.00097656250, e 0.00000000000 */ }, - { 4095, 0, 12, - MAD_F(0x10010010) /* 1.00024420024 => 1.00024420023, e 0.00000000001 */, - MAD_F(0x00020000) /* 0.00048828125 => 0.00048828125, e 0.00000000000 */ }, - { 8191, 0, 13, - MAD_F(0x10008004) /* 1.00012208522 => 1.00012208521, e 0.00000000001 */, - MAD_F(0x00010000) /* 0.00024414063 => 0.00024414062, e 0.00000000000 */ }, - { 16383, 0, 14, - MAD_F(0x10004001) /* 1.00006103888 => 1.00006103888, e -0.00000000000 */, - MAD_F(0x00008000) /* 0.00012207031 => 0.00012207031, e -0.00000000000 */ }, - { 32767, 0, 15, - MAD_F(0x10002000) /* 1.00003051851 => 1.00003051758, e 0.00000000093 */, - MAD_F(0x00004000) /* 0.00006103516 => 0.00006103516, e 0.00000000000 */ }, - { 65535, 0, 16, - MAD_F(0x10001000) /* 1.00001525902 => 1.00001525879, e 0.00000000023 */, - MAD_F(0x00002000) /* 0.00003051758 => 0.00003051758, e 0.00000000000 */ } diff --git a/libmad/src/rq_table.dat b/libmad/src/rq_table.dat deleted file mode 100644 index 059c4f3..0000000 --- a/libmad/src/rq_table.dat +++ /dev/null @@ -1,8747 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: rq_table.dat,v 1.7 2004/01/23 09:41:32 rob Exp $ - */ - -/* - * This is the lookup table used to compute x^(4/3) for Layer III - * requantization. To maintain the best possible accuracy, the value is - * stored as a normalized mantissa with exponent. The requantization - * algorithm recombines these parts with appropriate scaling. - */ - - /* 0 */ { MAD_F(0x00000000) /* 0.000000000 */, 0 }, - /* 1 */ { MAD_F(0x04000000) /* 0.250000000 */, 2 }, - /* 2 */ { MAD_F(0x050a28be) /* 0.314980262 */, 3 }, - /* 3 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 4 }, - /* 4 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 4 }, - /* 5 */ { MAD_F(0x04466275) /* 0.267183742 */, 5 }, - /* 6 */ { MAD_F(0x05738c72) /* 0.340710111 */, 5 }, - /* 7 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 5 }, - /* 8 */ { MAD_F(0x04000000) /* 0.250000000 */, 6 }, - /* 9 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 6 }, - /* 10 */ { MAD_F(0x0562d694) /* 0.336630420 */, 6 }, - /* 11 */ { MAD_F(0x061dae96) /* 0.382246578 */, 6 }, - /* 12 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 6 }, - /* 13 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 6 }, - /* 14 */ { MAD_F(0x0437be65) /* 0.263609310 */, 7 }, - /* 15 */ { MAD_F(0x049fc824) /* 0.289009227 */, 7 }, - - /* 16 */ { MAD_F(0x050a28be) /* 0.314980262 */, 7 }, - /* 17 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 7 }, - /* 18 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 7 }, - /* 19 */ { MAD_F(0x06566361) /* 0.396090870 */, 7 }, - /* 20 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 7 }, - /* 21 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 7 }, - /* 22 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 7 }, - /* 23 */ { MAD_F(0x04168b05) /* 0.255503674 */, 8 }, - /* 24 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 8 }, - /* 25 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 8 }, - /* 26 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 8 }, - /* 27 */ { MAD_F(0x05100000) /* 0.316406250 */, 8 }, - /* 28 */ { MAD_F(0x05506451) /* 0.332126919 */, 8 }, - /* 29 */ { MAD_F(0x05918e15) /* 0.348035890 */, 8 }, - /* 30 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 8 }, - /* 31 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 8 }, - - /* 32 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 8 }, - /* 33 */ { MAD_F(0x069d9400) /* 0.413471222 */, 8 }, - /* 34 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 8 }, - /* 35 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 8 }, - /* 36 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 8 }, - /* 37 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 8 }, - /* 38 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 8 }, - /* 39 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 9 }, - /* 40 */ { MAD_F(0x04466275) /* 0.267183742 */, 9 }, - /* 41 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 9 }, - /* 42 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 9 }, - /* 43 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 9 }, - /* 44 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 9 }, - /* 45 */ { MAD_F(0x05007b49) /* 0.312617576 */, 9 }, - /* 46 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 9 }, - /* 47 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 9 }, - - /* 48 */ { MAD_F(0x05738c72) /* 0.340710111 */, 9 }, - /* 49 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 9 }, - /* 50 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 9 }, - /* 51 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 9 }, - /* 52 */ { MAD_F(0x0610b982) /* 0.379083164 */, 9 }, - /* 53 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 9 }, - /* 54 */ { MAD_F(0x0660db91) /* 0.398646895 */, 9 }, - /* 55 */ { MAD_F(0x06894c90) /* 0.408520284 */, 9 }, - /* 56 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 9 }, - /* 57 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 9 }, - /* 58 */ { MAD_F(0x07041636) /* 0.438497744 */, 9 }, - /* 59 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 9 }, - /* 60 */ { MAD_F(0x075722ef) /* 0.458773552 */, 9 }, - /* 61 */ { MAD_F(0x078102b8) /* 0.468996735 */, 9 }, - /* 62 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 9 }, - /* 63 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 9 }, - - /* 64 */ { MAD_F(0x04000000) /* 0.250000000 */, 10 }, - /* 65 */ { MAD_F(0x04156381) /* 0.255221850 */, 10 }, - /* 66 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 10 }, - /* 67 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 10 }, - /* 68 */ { MAD_F(0x045635cf) /* 0.271047409 */, 10 }, - /* 69 */ { MAD_F(0x046c083e) /* 0.276375048 */, 10 }, - /* 70 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 10 }, - /* 71 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 10 }, - /* 72 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 10 }, - /* 73 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 10 }, - /* 74 */ { MAD_F(0x04dab524) /* 0.303395408 */, 10 }, - /* 75 */ { MAD_F(0x04f12624) /* 0.308874267 */, 10 }, - /* 76 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 10 }, - /* 77 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 10 }, - /* 78 */ { MAD_F(0x053511cb) /* 0.325456423 */, 10 }, - /* 79 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 10 }, - - /* 80 */ { MAD_F(0x0562d694) /* 0.336630420 */, 10 }, - /* 81 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 10 }, - /* 82 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 10 }, - /* 83 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 10 }, - /* 84 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 10 }, - /* 85 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 10 }, - /* 86 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 10 }, - /* 87 */ { MAD_F(0x0606012b) /* 0.376465960 */, 10 }, - /* 88 */ { MAD_F(0x061dae96) /* 0.382246578 */, 10 }, - /* 89 */ { MAD_F(0x06357302) /* 0.388049134 */, 10 }, - /* 90 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 10 }, - /* 91 */ { MAD_F(0x0665402d) /* 0.399719406 */, 10 }, - /* 92 */ { MAD_F(0x067d4896) /* 0.405586801 */, 10 }, - /* 93 */ { MAD_F(0x06956753) /* 0.411475493 */, 10 }, - /* 94 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 10 }, - /* 95 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 10 }, - - /* 96 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 10 }, - /* 97 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 10 }, - /* 98 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 10 }, - /* 99 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 10 }, - /* 100 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 10 }, - /* 101 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 10 }, - /* 102 */ { MAD_F(0x07724f64) /* 0.465407744 */, 10 }, - /* 103 */ { MAD_F(0x078b4514) /* 0.471501425 */, 10 }, - /* 104 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 10 }, - /* 105 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 10 }, - /* 106 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 10 }, - /* 107 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 10 }, - /* 108 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 11 }, - /* 109 */ { MAD_F(0x04115aca) /* 0.254236974 */, 11 }, - /* 110 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 11 }, - /* 111 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 11 }, - - /* 112 */ { MAD_F(0x0437be65) /* 0.263609310 */, 11 }, - /* 113 */ { MAD_F(0x04449dee) /* 0.266752177 */, 11 }, - /* 114 */ { MAD_F(0x04518733) /* 0.269904329 */, 11 }, - /* 115 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 11 }, - /* 116 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 11 }, - /* 117 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 11 }, - /* 118 */ { MAD_F(0x04858c83) /* 0.282604707 */, 11 }, - /* 119 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 11 }, - /* 120 */ { MAD_F(0x049fc824) /* 0.289009227 */, 11 }, - /* 121 */ { MAD_F(0x04acf402) /* 0.292224893 */, 11 }, - /* 122 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 11 }, - /* 123 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 11 }, - /* 124 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 11 }, - /* 125 */ { MAD_F(0x04e20000) /* 0.305175781 */, 11 }, - /* 126 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 11 }, - /* 127 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 11 }, - - /* 128 */ { MAD_F(0x050a28be) /* 0.314980262 */, 11 }, - /* 129 */ { MAD_F(0x05179da4) /* 0.318265572 */, 11 }, - /* 130 */ { MAD_F(0x05251b73) /* 0.321559381 */, 11 }, - /* 131 */ { MAD_F(0x0532a220) /* 0.324861647 */, 11 }, - /* 132 */ { MAD_F(0x054031a0) /* 0.328172327 */, 11 }, - /* 133 */ { MAD_F(0x054dc9e7) /* 0.331491377 */, 11 }, - /* 134 */ { MAD_F(0x055b6ae9) /* 0.334818756 */, 11 }, - /* 135 */ { MAD_F(0x0569149c) /* 0.338154423 */, 11 }, - /* 136 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 11 }, - /* 137 */ { MAD_F(0x058481e9) /* 0.344850455 */, 11 }, - /* 138 */ { MAD_F(0x0592456d) /* 0.348210741 */, 11 }, - /* 139 */ { MAD_F(0x05a01176) /* 0.351579152 */, 11 }, - /* 140 */ { MAD_F(0x05ade5fa) /* 0.354955651 */, 11 }, - /* 141 */ { MAD_F(0x05bbc2ef) /* 0.358340200 */, 11 }, - /* 142 */ { MAD_F(0x05c9a84a) /* 0.361732758 */, 11 }, - /* 143 */ { MAD_F(0x05d79601) /* 0.365133291 */, 11 }, - - /* 144 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 11 }, - /* 145 */ { MAD_F(0x05f38a5d) /* 0.371958126 */, 11 }, - /* 146 */ { MAD_F(0x060190ee) /* 0.375382356 */, 11 }, - /* 147 */ { MAD_F(0x060f9fb3) /* 0.378814413 */, 11 }, - /* 148 */ { MAD_F(0x061db6a5) /* 0.382254261 */, 11 }, - /* 149 */ { MAD_F(0x062bd5b8) /* 0.385701865 */, 11 }, - /* 150 */ { MAD_F(0x0639fce4) /* 0.389157191 */, 11 }, - /* 151 */ { MAD_F(0x06482c1f) /* 0.392620204 */, 11 }, - /* 152 */ { MAD_F(0x06566361) /* 0.396090870 */, 11 }, - /* 153 */ { MAD_F(0x0664a2a0) /* 0.399569155 */, 11 }, - /* 154 */ { MAD_F(0x0672e9d4) /* 0.403055027 */, 11 }, - /* 155 */ { MAD_F(0x068138f3) /* 0.406548452 */, 11 }, - /* 156 */ { MAD_F(0x068f8ff5) /* 0.410049398 */, 11 }, - /* 157 */ { MAD_F(0x069deed1) /* 0.413557833 */, 11 }, - /* 158 */ { MAD_F(0x06ac557f) /* 0.417073724 */, 11 }, - /* 159 */ { MAD_F(0x06bac3f6) /* 0.420597041 */, 11 }, - - /* 160 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 11 }, - /* 161 */ { MAD_F(0x06d7b81f) /* 0.427665827 */, 11 }, - /* 162 */ { MAD_F(0x06e63dc0) /* 0.431211234 */, 11 }, - /* 163 */ { MAD_F(0x06f4cb09) /* 0.434763944 */, 11 }, - /* 164 */ { MAD_F(0x07035ff3) /* 0.438323927 */, 11 }, - /* 165 */ { MAD_F(0x0711fc75) /* 0.441891153 */, 11 }, - /* 166 */ { MAD_F(0x0720a087) /* 0.445465593 */, 11 }, - /* 167 */ { MAD_F(0x072f4c22) /* 0.449047217 */, 11 }, - /* 168 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 11 }, - /* 169 */ { MAD_F(0x074cb9d3) /* 0.456231906 */, 11 }, - /* 170 */ { MAD_F(0x075b7bdb) /* 0.459834914 */, 11 }, - /* 171 */ { MAD_F(0x076a454c) /* 0.463444993 */, 11 }, - /* 172 */ { MAD_F(0x07791620) /* 0.467062117 */, 11 }, - /* 173 */ { MAD_F(0x0787ee50) /* 0.470686258 */, 11 }, - /* 174 */ { MAD_F(0x0796cdd4) /* 0.474317388 */, 11 }, - /* 175 */ { MAD_F(0x07a5b4a5) /* 0.477955481 */, 11 }, - - /* 176 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 11 }, - /* 177 */ { MAD_F(0x07c39812) /* 0.485252449 */, 11 }, - /* 178 */ { MAD_F(0x07d294a0) /* 0.488911273 */, 11 }, - /* 179 */ { MAD_F(0x07e1985f) /* 0.492576954 */, 11 }, - /* 180 */ { MAD_F(0x07f0a348) /* 0.496249468 */, 11 }, - /* 181 */ { MAD_F(0x07ffb554) /* 0.499928790 */, 11 }, - /* 182 */ { MAD_F(0x0407673f) /* 0.251807447 */, 12 }, - /* 183 */ { MAD_F(0x040ef75e) /* 0.253653877 */, 12 }, - /* 184 */ { MAD_F(0x04168b05) /* 0.255503674 */, 12 }, - /* 185 */ { MAD_F(0x041e2230) /* 0.257356825 */, 12 }, - /* 186 */ { MAD_F(0x0425bcdd) /* 0.259213318 */, 12 }, - /* 187 */ { MAD_F(0x042d5b07) /* 0.261073141 */, 12 }, - /* 188 */ { MAD_F(0x0434fcad) /* 0.262936282 */, 12 }, - /* 189 */ { MAD_F(0x043ca1c9) /* 0.264802730 */, 12 }, - /* 190 */ { MAD_F(0x04444a5a) /* 0.266672472 */, 12 }, - /* 191 */ { MAD_F(0x044bf65d) /* 0.268545497 */, 12 }, - - /* 192 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 12 }, - /* 193 */ { MAD_F(0x045b58a9) /* 0.272301352 */, 12 }, - /* 194 */ { MAD_F(0x04630eed) /* 0.274184158 */, 12 }, - /* 195 */ { MAD_F(0x046ac896) /* 0.276070203 */, 12 }, - /* 196 */ { MAD_F(0x047285a2) /* 0.277959474 */, 12 }, - /* 197 */ { MAD_F(0x047a460c) /* 0.279851960 */, 12 }, - /* 198 */ { MAD_F(0x048209d3) /* 0.281747652 */, 12 }, - /* 199 */ { MAD_F(0x0489d0f4) /* 0.283646538 */, 12 }, - /* 200 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 12 }, - /* 201 */ { MAD_F(0x04996935) /* 0.287453849 */, 12 }, - /* 202 */ { MAD_F(0x04a13a50) /* 0.289362253 */, 12 }, - /* 203 */ { MAD_F(0x04a90eba) /* 0.291273810 */, 12 }, - /* 204 */ { MAD_F(0x04b0e66e) /* 0.293188507 */, 12 }, - /* 205 */ { MAD_F(0x04b8c16c) /* 0.295106336 */, 12 }, - /* 206 */ { MAD_F(0x04c09faf) /* 0.297027285 */, 12 }, - /* 207 */ { MAD_F(0x04c88135) /* 0.298951346 */, 12 }, - - /* 208 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 12 }, - /* 209 */ { MAD_F(0x04d84dff) /* 0.302808759 */, 12 }, - /* 210 */ { MAD_F(0x04e0393e) /* 0.304742092 */, 12 }, - /* 211 */ { MAD_F(0x04e827b6) /* 0.306678497 */, 12 }, - /* 212 */ { MAD_F(0x04f01963) /* 0.308617963 */, 12 }, - /* 213 */ { MAD_F(0x04f80e44) /* 0.310560480 */, 12 }, - /* 214 */ { MAD_F(0x05000655) /* 0.312506041 */, 12 }, - /* 215 */ { MAD_F(0x05080195) /* 0.314454634 */, 12 }, - /* 216 */ { MAD_F(0x05100000) /* 0.316406250 */, 12 }, - /* 217 */ { MAD_F(0x05180194) /* 0.318360880 */, 12 }, - /* 218 */ { MAD_F(0x0520064f) /* 0.320318516 */, 12 }, - /* 219 */ { MAD_F(0x05280e2d) /* 0.322279147 */, 12 }, - /* 220 */ { MAD_F(0x0530192e) /* 0.324242764 */, 12 }, - /* 221 */ { MAD_F(0x0538274e) /* 0.326209359 */, 12 }, - /* 222 */ { MAD_F(0x0540388a) /* 0.328178922 */, 12 }, - /* 223 */ { MAD_F(0x05484ce2) /* 0.330151445 */, 12 }, - - /* 224 */ { MAD_F(0x05506451) /* 0.332126919 */, 12 }, - /* 225 */ { MAD_F(0x05587ed5) /* 0.334105334 */, 12 }, - /* 226 */ { MAD_F(0x05609c6e) /* 0.336086683 */, 12 }, - /* 227 */ { MAD_F(0x0568bd17) /* 0.338070956 */, 12 }, - /* 228 */ { MAD_F(0x0570e0cf) /* 0.340058145 */, 12 }, - /* 229 */ { MAD_F(0x05790793) /* 0.342048241 */, 12 }, - /* 230 */ { MAD_F(0x05813162) /* 0.344041237 */, 12 }, - /* 231 */ { MAD_F(0x05895e39) /* 0.346037122 */, 12 }, - /* 232 */ { MAD_F(0x05918e15) /* 0.348035890 */, 12 }, - /* 233 */ { MAD_F(0x0599c0f4) /* 0.350037532 */, 12 }, - /* 234 */ { MAD_F(0x05a1f6d5) /* 0.352042040 */, 12 }, - /* 235 */ { MAD_F(0x05aa2fb5) /* 0.354049405 */, 12 }, - /* 236 */ { MAD_F(0x05b26b92) /* 0.356059619 */, 12 }, - /* 237 */ { MAD_F(0x05baaa69) /* 0.358072674 */, 12 }, - /* 238 */ { MAD_F(0x05c2ec39) /* 0.360088563 */, 12 }, - /* 239 */ { MAD_F(0x05cb3100) /* 0.362107278 */, 12 }, - - /* 240 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 12 }, - /* 241 */ { MAD_F(0x05dbc368) /* 0.366153151 */, 12 }, - /* 242 */ { MAD_F(0x05e41105) /* 0.368180294 */, 12 }, - /* 243 */ { MAD_F(0x05ec6190) /* 0.370210231 */, 12 }, - /* 244 */ { MAD_F(0x05f4b507) /* 0.372242955 */, 12 }, - /* 245 */ { MAD_F(0x05fd0b68) /* 0.374278458 */, 12 }, - /* 246 */ { MAD_F(0x060564b1) /* 0.376316732 */, 12 }, - /* 247 */ { MAD_F(0x060dc0e0) /* 0.378357769 */, 12 }, - /* 248 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 12 }, - /* 249 */ { MAD_F(0x061e81e8) /* 0.382448106 */, 12 }, - /* 250 */ { MAD_F(0x0626e6bc) /* 0.384497391 */, 12 }, - /* 251 */ { MAD_F(0x062f4e6f) /* 0.386549409 */, 12 }, - /* 252 */ { MAD_F(0x0637b8fd) /* 0.388604155 */, 12 }, - /* 253 */ { MAD_F(0x06402666) /* 0.390661620 */, 12 }, - /* 254 */ { MAD_F(0x064896a7) /* 0.392721798 */, 12 }, - /* 255 */ { MAD_F(0x065109be) /* 0.394784681 */, 12 }, - - /* 256 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 12 }, - /* 257 */ { MAD_F(0x0661f867) /* 0.398918536 */, 12 }, - /* 258 */ { MAD_F(0x066a73f5) /* 0.400989493 */, 12 }, - /* 259 */ { MAD_F(0x0672f252) /* 0.403063128 */, 12 }, - /* 260 */ { MAD_F(0x067b737c) /* 0.405139433 */, 12 }, - /* 261 */ { MAD_F(0x0683f771) /* 0.407218402 */, 12 }, - /* 262 */ { MAD_F(0x068c7e2f) /* 0.409300027 */, 12 }, - /* 263 */ { MAD_F(0x069507b5) /* 0.411384303 */, 12 }, - /* 264 */ { MAD_F(0x069d9400) /* 0.413471222 */, 12 }, - /* 265 */ { MAD_F(0x06a6230f) /* 0.415560778 */, 12 }, - /* 266 */ { MAD_F(0x06aeb4e0) /* 0.417652964 */, 12 }, - /* 267 */ { MAD_F(0x06b74971) /* 0.419747773 */, 12 }, - /* 268 */ { MAD_F(0x06bfe0c0) /* 0.421845199 */, 12 }, - /* 269 */ { MAD_F(0x06c87acc) /* 0.423945235 */, 12 }, - /* 270 */ { MAD_F(0x06d11794) /* 0.426047876 */, 12 }, - /* 271 */ { MAD_F(0x06d9b714) /* 0.428153114 */, 12 }, - - /* 272 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 12 }, - /* 273 */ { MAD_F(0x06eafe3a) /* 0.432371356 */, 12 }, - /* 274 */ { MAD_F(0x06f3a5dc) /* 0.434484348 */, 12 }, - /* 275 */ { MAD_F(0x06fc5030) /* 0.436599912 */, 12 }, - /* 276 */ { MAD_F(0x0704fd35) /* 0.438718042 */, 12 }, - /* 277 */ { MAD_F(0x070dacea) /* 0.440838732 */, 12 }, - /* 278 */ { MAD_F(0x07165f4b) /* 0.442961975 */, 12 }, - /* 279 */ { MAD_F(0x071f1459) /* 0.445087765 */, 12 }, - /* 280 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 12 }, - /* 281 */ { MAD_F(0x07308671) /* 0.449346964 */, 12 }, - /* 282 */ { MAD_F(0x07394378) /* 0.451480360 */, 12 }, - /* 283 */ { MAD_F(0x07420325) /* 0.453616280 */, 12 }, - /* 284 */ { MAD_F(0x074ac575) /* 0.455754717 */, 12 }, - /* 285 */ { MAD_F(0x07538a67) /* 0.457895665 */, 12 }, - /* 286 */ { MAD_F(0x075c51fa) /* 0.460039119 */, 12 }, - /* 287 */ { MAD_F(0x07651c2c) /* 0.462185072 */, 12 }, - - /* 288 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 12 }, - /* 289 */ { MAD_F(0x0776b867) /* 0.466484455 */, 12 }, - /* 290 */ { MAD_F(0x077f8a6d) /* 0.468637872 */, 12 }, - /* 291 */ { MAD_F(0x07885f0b) /* 0.470793767 */, 12 }, - /* 292 */ { MAD_F(0x07913641) /* 0.472952132 */, 12 }, - /* 293 */ { MAD_F(0x079a100c) /* 0.475112962 */, 12 }, - /* 294 */ { MAD_F(0x07a2ec6c) /* 0.477276252 */, 12 }, - /* 295 */ { MAD_F(0x07abcb5f) /* 0.479441997 */, 12 }, - /* 296 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 12 }, - /* 297 */ { MAD_F(0x07bd90f6) /* 0.483780825 */, 12 }, - /* 298 */ { MAD_F(0x07c67798) /* 0.485953899 */, 12 }, - /* 299 */ { MAD_F(0x07cf60c7) /* 0.488129404 */, 12 }, - /* 300 */ { MAD_F(0x07d84c81) /* 0.490307336 */, 12 }, - /* 301 */ { MAD_F(0x07e13ac5) /* 0.492487690 */, 12 }, - /* 302 */ { MAD_F(0x07ea2b92) /* 0.494670459 */, 12 }, - /* 303 */ { MAD_F(0x07f31ee6) /* 0.496855639 */, 12 }, - - /* 304 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 12 }, - /* 305 */ { MAD_F(0x0402868e) /* 0.250616605 */, 13 }, - /* 306 */ { MAD_F(0x040703ff) /* 0.251712795 */, 13 }, - /* 307 */ { MAD_F(0x040b82b0) /* 0.252810180 */, 13 }, - /* 308 */ { MAD_F(0x041002a1) /* 0.253908756 */, 13 }, - /* 309 */ { MAD_F(0x041483d1) /* 0.255008523 */, 13 }, - /* 310 */ { MAD_F(0x04190640) /* 0.256109476 */, 13 }, - /* 311 */ { MAD_F(0x041d89ed) /* 0.257211614 */, 13 }, - /* 312 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 13 }, - /* 313 */ { MAD_F(0x042694fe) /* 0.259419433 */, 13 }, - /* 314 */ { MAD_F(0x042b1c60) /* 0.260525110 */, 13 }, - /* 315 */ { MAD_F(0x042fa4fe) /* 0.261631960 */, 13 }, - /* 316 */ { MAD_F(0x04342ed7) /* 0.262739982 */, 13 }, - /* 317 */ { MAD_F(0x0438b9e9) /* 0.263849174 */, 13 }, - /* 318 */ { MAD_F(0x043d4635) /* 0.264959533 */, 13 }, - /* 319 */ { MAD_F(0x0441d3b9) /* 0.266071056 */, 13 }, - - /* 320 */ { MAD_F(0x04466275) /* 0.267183742 */, 13 }, - /* 321 */ { MAD_F(0x044af269) /* 0.268297587 */, 13 }, - /* 322 */ { MAD_F(0x044f8393) /* 0.269412589 */, 13 }, - /* 323 */ { MAD_F(0x045415f3) /* 0.270528746 */, 13 }, - /* 324 */ { MAD_F(0x0458a989) /* 0.271646056 */, 13 }, - /* 325 */ { MAD_F(0x045d3e53) /* 0.272764515 */, 13 }, - /* 326 */ { MAD_F(0x0461d451) /* 0.273884123 */, 13 }, - /* 327 */ { MAD_F(0x04666b83) /* 0.275004875 */, 13 }, - /* 328 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 13 }, - /* 329 */ { MAD_F(0x046f9d7e) /* 0.277249808 */, 13 }, - /* 330 */ { MAD_F(0x04743847) /* 0.278373983 */, 13 }, - /* 331 */ { MAD_F(0x0478d440) /* 0.279499294 */, 13 }, - /* 332 */ { MAD_F(0x047d716a) /* 0.280625739 */, 13 }, - /* 333 */ { MAD_F(0x04820fc3) /* 0.281753315 */, 13 }, - /* 334 */ { MAD_F(0x0486af4c) /* 0.282882021 */, 13 }, - /* 335 */ { MAD_F(0x048b5003) /* 0.284011853 */, 13 }, - - /* 336 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 13 }, - /* 337 */ { MAD_F(0x049494fb) /* 0.286274891 */, 13 }, - /* 338 */ { MAD_F(0x0499393a) /* 0.287408091 */, 13 }, - /* 339 */ { MAD_F(0x049ddea5) /* 0.288542409 */, 13 }, - /* 340 */ { MAD_F(0x04a2853c) /* 0.289677844 */, 13 }, - /* 341 */ { MAD_F(0x04a72cfe) /* 0.290814392 */, 13 }, - /* 342 */ { MAD_F(0x04abd5ea) /* 0.291952051 */, 13 }, - /* 343 */ { MAD_F(0x04b08000) /* 0.293090820 */, 13 }, - /* 344 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 13 }, - /* 345 */ { MAD_F(0x04b9d7a7) /* 0.295371678 */, 13 }, - /* 346 */ { MAD_F(0x04be8537) /* 0.296513762 */, 13 }, - /* 347 */ { MAD_F(0x04c333ee) /* 0.297656947 */, 13 }, - /* 348 */ { MAD_F(0x04c7e3cc) /* 0.298801231 */, 13 }, - /* 349 */ { MAD_F(0x04cc94d1) /* 0.299946611 */, 13 }, - /* 350 */ { MAD_F(0x04d146fb) /* 0.301093085 */, 13 }, - /* 351 */ { MAD_F(0x04d5fa4b) /* 0.302240653 */, 13 }, - - /* 352 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 13 }, - /* 353 */ { MAD_F(0x04df6458) /* 0.304539056 */, 13 }, - /* 354 */ { MAD_F(0x04e41b14) /* 0.305689888 */, 13 }, - /* 355 */ { MAD_F(0x04e8d2f3) /* 0.306841804 */, 13 }, - /* 356 */ { MAD_F(0x04ed8bf5) /* 0.307994802 */, 13 }, - /* 357 */ { MAD_F(0x04f24618) /* 0.309148880 */, 13 }, - /* 358 */ { MAD_F(0x04f7015d) /* 0.310304037 */, 13 }, - /* 359 */ { MAD_F(0x04fbbdc3) /* 0.311460269 */, 13 }, - /* 360 */ { MAD_F(0x05007b49) /* 0.312617576 */, 13 }, - /* 361 */ { MAD_F(0x050539ef) /* 0.313775954 */, 13 }, - /* 362 */ { MAD_F(0x0509f9b4) /* 0.314935403 */, 13 }, - /* 363 */ { MAD_F(0x050eba98) /* 0.316095920 */, 13 }, - /* 364 */ { MAD_F(0x05137c9a) /* 0.317257503 */, 13 }, - /* 365 */ { MAD_F(0x05183fba) /* 0.318420150 */, 13 }, - /* 366 */ { MAD_F(0x051d03f7) /* 0.319583859 */, 13 }, - /* 367 */ { MAD_F(0x0521c950) /* 0.320748629 */, 13 }, - - /* 368 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 13 }, - /* 369 */ { MAD_F(0x052b5757) /* 0.323081342 */, 13 }, - /* 370 */ { MAD_F(0x05302003) /* 0.324249281 */, 13 }, - /* 371 */ { MAD_F(0x0534e9ca) /* 0.325418273 */, 13 }, - /* 372 */ { MAD_F(0x0539b4ab) /* 0.326588316 */, 13 }, - /* 373 */ { MAD_F(0x053e80a6) /* 0.327759407 */, 13 }, - /* 374 */ { MAD_F(0x05434db9) /* 0.328931546 */, 13 }, - /* 375 */ { MAD_F(0x05481be5) /* 0.330104730 */, 13 }, - /* 376 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 13 }, - /* 377 */ { MAD_F(0x0551bb85) /* 0.332454225 */, 13 }, - /* 378 */ { MAD_F(0x05568cf8) /* 0.333630533 */, 13 }, - /* 379 */ { MAD_F(0x055b5f81) /* 0.334807879 */, 13 }, - /* 380 */ { MAD_F(0x05603321) /* 0.335986261 */, 13 }, - /* 381 */ { MAD_F(0x056507d6) /* 0.337165677 */, 13 }, - /* 382 */ { MAD_F(0x0569dda0) /* 0.338346125 */, 13 }, - /* 383 */ { MAD_F(0x056eb47f) /* 0.339527604 */, 13 }, - - /* 384 */ { MAD_F(0x05738c72) /* 0.340710111 */, 13 }, - /* 385 */ { MAD_F(0x05786578) /* 0.341893646 */, 13 }, - /* 386 */ { MAD_F(0x057d3f92) /* 0.343078205 */, 13 }, - /* 387 */ { MAD_F(0x05821abf) /* 0.344263788 */, 13 }, - /* 388 */ { MAD_F(0x0586f6fd) /* 0.345450393 */, 13 }, - /* 389 */ { MAD_F(0x058bd44e) /* 0.346638017 */, 13 }, - /* 390 */ { MAD_F(0x0590b2b0) /* 0.347826659 */, 13 }, - /* 391 */ { MAD_F(0x05959222) /* 0.349016318 */, 13 }, - /* 392 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 13 }, - /* 393 */ { MAD_F(0x059f5438) /* 0.351398678 */, 13 }, - /* 394 */ { MAD_F(0x05a436da) /* 0.352591376 */, 13 }, - /* 395 */ { MAD_F(0x05a91a8c) /* 0.353785083 */, 13 }, - /* 396 */ { MAD_F(0x05adff4c) /* 0.354979798 */, 13 }, - /* 397 */ { MAD_F(0x05b2e51a) /* 0.356175519 */, 13 }, - /* 398 */ { MAD_F(0x05b7cbf5) /* 0.357372244 */, 13 }, - /* 399 */ { MAD_F(0x05bcb3de) /* 0.358569972 */, 13 }, - - /* 400 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 13 }, - /* 401 */ { MAD_F(0x05c686d5) /* 0.360968429 */, 13 }, - /* 402 */ { MAD_F(0x05cb71e2) /* 0.362169156 */, 13 }, - /* 403 */ { MAD_F(0x05d05dfb) /* 0.363370878 */, 13 }, - /* 404 */ { MAD_F(0x05d54b1f) /* 0.364573594 */, 13 }, - /* 405 */ { MAD_F(0x05da394d) /* 0.365777304 */, 13 }, - /* 406 */ { MAD_F(0x05df2885) /* 0.366982004 */, 13 }, - /* 407 */ { MAD_F(0x05e418c7) /* 0.368187694 */, 13 }, - /* 408 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 13 }, - /* 409 */ { MAD_F(0x05edfc66) /* 0.370602036 */, 13 }, - /* 410 */ { MAD_F(0x05f2efc2) /* 0.371810684 */, 13 }, - /* 411 */ { MAD_F(0x05f7e426) /* 0.373020316 */, 13 }, - /* 412 */ { MAD_F(0x05fcd992) /* 0.374230929 */, 13 }, - /* 413 */ { MAD_F(0x0601d004) /* 0.375442522 */, 13 }, - /* 414 */ { MAD_F(0x0606c77d) /* 0.376655093 */, 13 }, - /* 415 */ { MAD_F(0x060bbffd) /* 0.377868641 */, 13 }, - - /* 416 */ { MAD_F(0x0610b982) /* 0.379083164 */, 13 }, - /* 417 */ { MAD_F(0x0615b40c) /* 0.380298661 */, 13 }, - /* 418 */ { MAD_F(0x061aaf9c) /* 0.381515130 */, 13 }, - /* 419 */ { MAD_F(0x061fac2f) /* 0.382732569 */, 13 }, - /* 420 */ { MAD_F(0x0624a9c7) /* 0.383950977 */, 13 }, - /* 421 */ { MAD_F(0x0629a863) /* 0.385170352 */, 13 }, - /* 422 */ { MAD_F(0x062ea802) /* 0.386390694 */, 13 }, - /* 423 */ { MAD_F(0x0633a8a3) /* 0.387611999 */, 13 }, - /* 424 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 13 }, - /* 425 */ { MAD_F(0x063dacee) /* 0.390057497 */, 13 }, - /* 426 */ { MAD_F(0x0642b096) /* 0.391281687 */, 13 }, - /* 427 */ { MAD_F(0x0647b53f) /* 0.392506834 */, 13 }, - /* 428 */ { MAD_F(0x064cbae9) /* 0.393732939 */, 13 }, - /* 429 */ { MAD_F(0x0651c193) /* 0.394959999 */, 13 }, - /* 430 */ { MAD_F(0x0656c93d) /* 0.396188012 */, 13 }, - /* 431 */ { MAD_F(0x065bd1e7) /* 0.397416978 */, 13 }, - - /* 432 */ { MAD_F(0x0660db91) /* 0.398646895 */, 13 }, - /* 433 */ { MAD_F(0x0665e639) /* 0.399877761 */, 13 }, - /* 434 */ { MAD_F(0x066af1df) /* 0.401109575 */, 13 }, - /* 435 */ { MAD_F(0x066ffe84) /* 0.402342335 */, 13 }, - /* 436 */ { MAD_F(0x06750c26) /* 0.403576041 */, 13 }, - /* 437 */ { MAD_F(0x067a1ac6) /* 0.404810690 */, 13 }, - /* 438 */ { MAD_F(0x067f2a62) /* 0.406046281 */, 13 }, - /* 439 */ { MAD_F(0x06843afb) /* 0.407282813 */, 13 }, - /* 440 */ { MAD_F(0x06894c90) /* 0.408520284 */, 13 }, - /* 441 */ { MAD_F(0x068e5f21) /* 0.409758693 */, 13 }, - /* 442 */ { MAD_F(0x069372ae) /* 0.410998038 */, 13 }, - /* 443 */ { MAD_F(0x06988735) /* 0.412238319 */, 13 }, - /* 444 */ { MAD_F(0x069d9cb7) /* 0.413479532 */, 13 }, - /* 445 */ { MAD_F(0x06a2b333) /* 0.414721679 */, 13 }, - /* 446 */ { MAD_F(0x06a7caa9) /* 0.415964756 */, 13 }, - /* 447 */ { MAD_F(0x06ace318) /* 0.417208762 */, 13 }, - - /* 448 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 13 }, - /* 449 */ { MAD_F(0x06b716e2) /* 0.419699557 */, 13 }, - /* 450 */ { MAD_F(0x06bc323b) /* 0.420946343 */, 13 }, - /* 451 */ { MAD_F(0x06c14e8d) /* 0.422194054 */, 13 }, - /* 452 */ { MAD_F(0x06c66bd6) /* 0.423442686 */, 13 }, - /* 453 */ { MAD_F(0x06cb8a17) /* 0.424692240 */, 13 }, - /* 454 */ { MAD_F(0x06d0a94e) /* 0.425942714 */, 13 }, - /* 455 */ { MAD_F(0x06d5c97c) /* 0.427194106 */, 13 }, - /* 456 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 13 }, - /* 457 */ { MAD_F(0x06e00cbb) /* 0.429699640 */, 13 }, - /* 458 */ { MAD_F(0x06e52fca) /* 0.430953779 */, 13 }, - /* 459 */ { MAD_F(0x06ea53cf) /* 0.432208832 */, 13 }, - /* 460 */ { MAD_F(0x06ef78c8) /* 0.433464796 */, 13 }, - /* 461 */ { MAD_F(0x06f49eb6) /* 0.434721671 */, 13 }, - /* 462 */ { MAD_F(0x06f9c597) /* 0.435979455 */, 13 }, - /* 463 */ { MAD_F(0x06feed6d) /* 0.437238146 */, 13 }, - - /* 464 */ { MAD_F(0x07041636) /* 0.438497744 */, 13 }, - /* 465 */ { MAD_F(0x07093ff2) /* 0.439758248 */, 13 }, - /* 466 */ { MAD_F(0x070e6aa0) /* 0.441019655 */, 13 }, - /* 467 */ { MAD_F(0x07139641) /* 0.442281965 */, 13 }, - /* 468 */ { MAD_F(0x0718c2d3) /* 0.443545176 */, 13 }, - /* 469 */ { MAD_F(0x071df058) /* 0.444809288 */, 13 }, - /* 470 */ { MAD_F(0x07231ecd) /* 0.446074298 */, 13 }, - /* 471 */ { MAD_F(0x07284e34) /* 0.447340205 */, 13 }, - /* 472 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 13 }, - /* 473 */ { MAD_F(0x0732afd2) /* 0.449874708 */, 13 }, - /* 474 */ { MAD_F(0x0737e209) /* 0.451143300 */, 13 }, - /* 475 */ { MAD_F(0x073d1530) /* 0.452412785 */, 13 }, - /* 476 */ { MAD_F(0x07424946) /* 0.453683161 */, 13 }, - /* 477 */ { MAD_F(0x07477e4b) /* 0.454954427 */, 13 }, - /* 478 */ { MAD_F(0x074cb43e) /* 0.456226581 */, 13 }, - /* 479 */ { MAD_F(0x0751eb20) /* 0.457499623 */, 13 }, - - /* 480 */ { MAD_F(0x075722ef) /* 0.458773552 */, 13 }, - /* 481 */ { MAD_F(0x075c5bac) /* 0.460048365 */, 13 }, - /* 482 */ { MAD_F(0x07619557) /* 0.461324062 */, 13 }, - /* 483 */ { MAD_F(0x0766cfee) /* 0.462600642 */, 13 }, - /* 484 */ { MAD_F(0x076c0b72) /* 0.463878102 */, 13 }, - /* 485 */ { MAD_F(0x077147e2) /* 0.465156443 */, 13 }, - /* 486 */ { MAD_F(0x0776853e) /* 0.466435663 */, 13 }, - /* 487 */ { MAD_F(0x077bc385) /* 0.467715761 */, 13 }, - /* 488 */ { MAD_F(0x078102b8) /* 0.468996735 */, 13 }, - /* 489 */ { MAD_F(0x078642d6) /* 0.470278584 */, 13 }, - /* 490 */ { MAD_F(0x078b83de) /* 0.471561307 */, 13 }, - /* 491 */ { MAD_F(0x0790c5d1) /* 0.472844904 */, 13 }, - /* 492 */ { MAD_F(0x079608ae) /* 0.474129372 */, 13 }, - /* 493 */ { MAD_F(0x079b4c74) /* 0.475414710 */, 13 }, - /* 494 */ { MAD_F(0x07a09124) /* 0.476700918 */, 13 }, - /* 495 */ { MAD_F(0x07a5d6bd) /* 0.477987994 */, 13 }, - - /* 496 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 13 }, - /* 497 */ { MAD_F(0x07b064a8) /* 0.480564746 */, 13 }, - /* 498 */ { MAD_F(0x07b5acfb) /* 0.481854420 */, 13 }, - /* 499 */ { MAD_F(0x07baf635) /* 0.483144957 */, 13 }, - /* 500 */ { MAD_F(0x07c04056) /* 0.484436356 */, 13 }, - /* 501 */ { MAD_F(0x07c58b5f) /* 0.485728617 */, 13 }, - /* 502 */ { MAD_F(0x07cad74e) /* 0.487021738 */, 13 }, - /* 503 */ { MAD_F(0x07d02424) /* 0.488315717 */, 13 }, - /* 504 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 13 }, - /* 505 */ { MAD_F(0x07dac083) /* 0.490906249 */, 13 }, - /* 506 */ { MAD_F(0x07e0100a) /* 0.492202799 */, 13 }, - /* 507 */ { MAD_F(0x07e56078) /* 0.493500203 */, 13 }, - /* 508 */ { MAD_F(0x07eab1ca) /* 0.494798460 */, 13 }, - /* 509 */ { MAD_F(0x07f00401) /* 0.496097570 */, 13 }, - /* 510 */ { MAD_F(0x07f5571d) /* 0.497397530 */, 13 }, - /* 511 */ { MAD_F(0x07faab1c) /* 0.498698341 */, 13 }, - - /* 512 */ { MAD_F(0x04000000) /* 0.250000000 */, 14 }, - /* 513 */ { MAD_F(0x0402aae3) /* 0.250651254 */, 14 }, - /* 514 */ { MAD_F(0x04055638) /* 0.251302930 */, 14 }, - /* 515 */ { MAD_F(0x040801ff) /* 0.251955030 */, 14 }, - /* 516 */ { MAD_F(0x040aae37) /* 0.252607552 */, 14 }, - /* 517 */ { MAD_F(0x040d5ae0) /* 0.253260495 */, 14 }, - /* 518 */ { MAD_F(0x041007fa) /* 0.253913860 */, 14 }, - /* 519 */ { MAD_F(0x0412b586) /* 0.254567645 */, 14 }, - /* 520 */ { MAD_F(0x04156381) /* 0.255221850 */, 14 }, - /* 521 */ { MAD_F(0x041811ee) /* 0.255876475 */, 14 }, - /* 522 */ { MAD_F(0x041ac0cb) /* 0.256531518 */, 14 }, - /* 523 */ { MAD_F(0x041d7018) /* 0.257186980 */, 14 }, - /* 524 */ { MAD_F(0x04201fd5) /* 0.257842860 */, 14 }, - /* 525 */ { MAD_F(0x0422d003) /* 0.258499157 */, 14 }, - /* 526 */ { MAD_F(0x042580a0) /* 0.259155872 */, 14 }, - /* 527 */ { MAD_F(0x042831ad) /* 0.259813002 */, 14 }, - - /* 528 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 14 }, - /* 529 */ { MAD_F(0x042d9516) /* 0.261128510 */, 14 }, - /* 530 */ { MAD_F(0x04304772) /* 0.261786886 */, 14 }, - /* 531 */ { MAD_F(0x0432fa3d) /* 0.262445676 */, 14 }, - /* 532 */ { MAD_F(0x0435ad76) /* 0.263104880 */, 14 }, - /* 533 */ { MAD_F(0x0438611f) /* 0.263764497 */, 14 }, - /* 534 */ { MAD_F(0x043b1536) /* 0.264424527 */, 14 }, - /* 535 */ { MAD_F(0x043dc9bc) /* 0.265084969 */, 14 }, - /* 536 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 14 }, - /* 537 */ { MAD_F(0x04433414) /* 0.266407088 */, 14 }, - /* 538 */ { MAD_F(0x0445e9e5) /* 0.267068763 */, 14 }, - /* 539 */ { MAD_F(0x0448a024) /* 0.267730848 */, 14 }, - /* 540 */ { MAD_F(0x044b56d1) /* 0.268393343 */, 14 }, - /* 541 */ { MAD_F(0x044e0dec) /* 0.269056248 */, 14 }, - /* 542 */ { MAD_F(0x0450c575) /* 0.269719560 */, 14 }, - /* 543 */ { MAD_F(0x04537d6b) /* 0.270383281 */, 14 }, - - /* 544 */ { MAD_F(0x045635cf) /* 0.271047409 */, 14 }, - /* 545 */ { MAD_F(0x0458ee9f) /* 0.271711944 */, 14 }, - /* 546 */ { MAD_F(0x045ba7dd) /* 0.272376886 */, 14 }, - /* 547 */ { MAD_F(0x045e6188) /* 0.273042234 */, 14 }, - /* 548 */ { MAD_F(0x04611ba0) /* 0.273707988 */, 14 }, - /* 549 */ { MAD_F(0x0463d625) /* 0.274374147 */, 14 }, - /* 550 */ { MAD_F(0x04669116) /* 0.275040710 */, 14 }, - /* 551 */ { MAD_F(0x04694c74) /* 0.275707677 */, 14 }, - /* 552 */ { MAD_F(0x046c083e) /* 0.276375048 */, 14 }, - /* 553 */ { MAD_F(0x046ec474) /* 0.277042822 */, 14 }, - /* 554 */ { MAD_F(0x04718116) /* 0.277710999 */, 14 }, - /* 555 */ { MAD_F(0x04743e25) /* 0.278379578 */, 14 }, - /* 556 */ { MAD_F(0x0476fb9f) /* 0.279048558 */, 14 }, - /* 557 */ { MAD_F(0x0479b984) /* 0.279717940 */, 14 }, - /* 558 */ { MAD_F(0x047c77d6) /* 0.280387722 */, 14 }, - /* 559 */ { MAD_F(0x047f3693) /* 0.281057905 */, 14 }, - - /* 560 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 14 }, - /* 561 */ { MAD_F(0x0484b54e) /* 0.282399469 */, 14 }, - /* 562 */ { MAD_F(0x0487754c) /* 0.283070849 */, 14 }, - /* 563 */ { MAD_F(0x048a35b6) /* 0.283742628 */, 14 }, - /* 564 */ { MAD_F(0x048cf68a) /* 0.284414805 */, 14 }, - /* 565 */ { MAD_F(0x048fb7c8) /* 0.285087379 */, 14 }, - /* 566 */ { MAD_F(0x04927972) /* 0.285760350 */, 14 }, - /* 567 */ { MAD_F(0x04953b85) /* 0.286433717 */, 14 }, - /* 568 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 14 }, - /* 569 */ { MAD_F(0x049ac0eb) /* 0.287781640 */, 14 }, - /* 570 */ { MAD_F(0x049d843e) /* 0.288456194 */, 14 }, - /* 571 */ { MAD_F(0x04a047fa) /* 0.289131142 */, 14 }, - /* 572 */ { MAD_F(0x04a30c20) /* 0.289806485 */, 14 }, - /* 573 */ { MAD_F(0x04a5d0af) /* 0.290482221 */, 14 }, - /* 574 */ { MAD_F(0x04a895a8) /* 0.291158351 */, 14 }, - /* 575 */ { MAD_F(0x04ab5b0b) /* 0.291834873 */, 14 }, - - /* 576 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 14 }, - /* 577 */ { MAD_F(0x04b0e70c) /* 0.293189094 */, 14 }, - /* 578 */ { MAD_F(0x04b3adaa) /* 0.293866792 */, 14 }, - /* 579 */ { MAD_F(0x04b674b1) /* 0.294544881 */, 14 }, - /* 580 */ { MAD_F(0x04b93c21) /* 0.295223360 */, 14 }, - /* 581 */ { MAD_F(0x04bc03fa) /* 0.295902229 */, 14 }, - /* 582 */ { MAD_F(0x04becc3b) /* 0.296581488 */, 14 }, - /* 583 */ { MAD_F(0x04c194e4) /* 0.297261136 */, 14 }, - /* 584 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 14 }, - /* 585 */ { MAD_F(0x04c72771) /* 0.298621598 */, 14 }, - /* 586 */ { MAD_F(0x04c9f153) /* 0.299302411 */, 14 }, - /* 587 */ { MAD_F(0x04ccbb9d) /* 0.299983611 */, 14 }, - /* 588 */ { MAD_F(0x04cf864f) /* 0.300665198 */, 14 }, - /* 589 */ { MAD_F(0x04d25169) /* 0.301347172 */, 14 }, - /* 590 */ { MAD_F(0x04d51ceb) /* 0.302029532 */, 14 }, - /* 591 */ { MAD_F(0x04d7e8d4) /* 0.302712277 */, 14 }, - - /* 592 */ { MAD_F(0x04dab524) /* 0.303395408 */, 14 }, - /* 593 */ { MAD_F(0x04dd81dc) /* 0.304078923 */, 14 }, - /* 594 */ { MAD_F(0x04e04efb) /* 0.304762823 */, 14 }, - /* 595 */ { MAD_F(0x04e31c81) /* 0.305447106 */, 14 }, - /* 596 */ { MAD_F(0x04e5ea6e) /* 0.306131773 */, 14 }, - /* 597 */ { MAD_F(0x04e8b8c2) /* 0.306816823 */, 14 }, - /* 598 */ { MAD_F(0x04eb877c) /* 0.307502256 */, 14 }, - /* 599 */ { MAD_F(0x04ee569d) /* 0.308188071 */, 14 }, - /* 600 */ { MAD_F(0x04f12624) /* 0.308874267 */, 14 }, - /* 601 */ { MAD_F(0x04f3f612) /* 0.309560845 */, 14 }, - /* 602 */ { MAD_F(0x04f6c666) /* 0.310247804 */, 14 }, - /* 603 */ { MAD_F(0x04f99721) /* 0.310935143 */, 14 }, - /* 604 */ { MAD_F(0x04fc6841) /* 0.311622862 */, 14 }, - /* 605 */ { MAD_F(0x04ff39c7) /* 0.312310961 */, 14 }, - /* 606 */ { MAD_F(0x05020bb3) /* 0.312999439 */, 14 }, - /* 607 */ { MAD_F(0x0504de05) /* 0.313688296 */, 14 }, - - /* 608 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 14 }, - /* 609 */ { MAD_F(0x050a83d8) /* 0.315067145 */, 14 }, - /* 610 */ { MAD_F(0x050d575b) /* 0.315757136 */, 14 }, - /* 611 */ { MAD_F(0x05102b42) /* 0.316447504 */, 14 }, - /* 612 */ { MAD_F(0x0512ff8e) /* 0.317138249 */, 14 }, - /* 613 */ { MAD_F(0x0515d440) /* 0.317829370 */, 14 }, - /* 614 */ { MAD_F(0x0518a956) /* 0.318520867 */, 14 }, - /* 615 */ { MAD_F(0x051b7ed1) /* 0.319212739 */, 14 }, - /* 616 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 14 }, - /* 617 */ { MAD_F(0x05212af5) /* 0.320597609 */, 14 }, - /* 618 */ { MAD_F(0x0524019e) /* 0.321290606 */, 14 }, - /* 619 */ { MAD_F(0x0526d8ab) /* 0.321983976 */, 14 }, - /* 620 */ { MAD_F(0x0529b01d) /* 0.322677720 */, 14 }, - /* 621 */ { MAD_F(0x052c87f2) /* 0.323371837 */, 14 }, - /* 622 */ { MAD_F(0x052f602c) /* 0.324066327 */, 14 }, - /* 623 */ { MAD_F(0x053238ca) /* 0.324761189 */, 14 }, - - /* 624 */ { MAD_F(0x053511cb) /* 0.325456423 */, 14 }, - /* 625 */ { MAD_F(0x0537eb30) /* 0.326152028 */, 14 }, - /* 626 */ { MAD_F(0x053ac4f9) /* 0.326848005 */, 14 }, - /* 627 */ { MAD_F(0x053d9f25) /* 0.327544352 */, 14 }, - /* 628 */ { MAD_F(0x054079b5) /* 0.328241070 */, 14 }, - /* 629 */ { MAD_F(0x054354a8) /* 0.328938157 */, 14 }, - /* 630 */ { MAD_F(0x05462ffe) /* 0.329635614 */, 14 }, - /* 631 */ { MAD_F(0x05490bb7) /* 0.330333440 */, 14 }, - /* 632 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 14 }, - /* 633 */ { MAD_F(0x054ec453) /* 0.331730198 */, 14 }, - /* 634 */ { MAD_F(0x0551a134) /* 0.332429129 */, 14 }, - /* 635 */ { MAD_F(0x05547e79) /* 0.333128427 */, 14 }, - /* 636 */ { MAD_F(0x05575c20) /* 0.333828093 */, 14 }, - /* 637 */ { MAD_F(0x055a3a2a) /* 0.334528126 */, 14 }, - /* 638 */ { MAD_F(0x055d1896) /* 0.335228525 */, 14 }, - /* 639 */ { MAD_F(0x055ff764) /* 0.335929290 */, 14 }, - - /* 640 */ { MAD_F(0x0562d694) /* 0.336630420 */, 14 }, - /* 641 */ { MAD_F(0x0565b627) /* 0.337331916 */, 14 }, - /* 642 */ { MAD_F(0x0568961b) /* 0.338033777 */, 14 }, - /* 643 */ { MAD_F(0x056b7671) /* 0.338736002 */, 14 }, - /* 644 */ { MAD_F(0x056e5729) /* 0.339438592 */, 14 }, - /* 645 */ { MAD_F(0x05713843) /* 0.340141545 */, 14 }, - /* 646 */ { MAD_F(0x057419be) /* 0.340844862 */, 14 }, - /* 647 */ { MAD_F(0x0576fb9a) /* 0.341548541 */, 14 }, - /* 648 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 14 }, - /* 649 */ { MAD_F(0x057cc077) /* 0.342956988 */, 14 }, - /* 650 */ { MAD_F(0x057fa378) /* 0.343661754 */, 14 }, - /* 651 */ { MAD_F(0x058286d9) /* 0.344366882 */, 14 }, - /* 652 */ { MAD_F(0x05856a9b) /* 0.345072371 */, 14 }, - /* 653 */ { MAD_F(0x05884ebe) /* 0.345778221 */, 14 }, - /* 654 */ { MAD_F(0x058b3342) /* 0.346484431 */, 14 }, - /* 655 */ { MAD_F(0x058e1827) /* 0.347191002 */, 14 }, - - /* 656 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 14 }, - /* 657 */ { MAD_F(0x0593e311) /* 0.348605221 */, 14 }, - /* 658 */ { MAD_F(0x0596c917) /* 0.349312869 */, 14 }, - /* 659 */ { MAD_F(0x0599af7d) /* 0.350020876 */, 14 }, - /* 660 */ { MAD_F(0x059c9643) /* 0.350729240 */, 14 }, - /* 661 */ { MAD_F(0x059f7d6a) /* 0.351437963 */, 14 }, - /* 662 */ { MAD_F(0x05a264f0) /* 0.352147044 */, 14 }, - /* 663 */ { MAD_F(0x05a54cd6) /* 0.352856481 */, 14 }, - /* 664 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 14 }, - /* 665 */ { MAD_F(0x05ab1dc2) /* 0.354276426 */, 14 }, - /* 666 */ { MAD_F(0x05ae06c7) /* 0.354986932 */, 14 }, - /* 667 */ { MAD_F(0x05b0f02b) /* 0.355697795 */, 14 }, - /* 668 */ { MAD_F(0x05b3d9f0) /* 0.356409012 */, 14 }, - /* 669 */ { MAD_F(0x05b6c413) /* 0.357120585 */, 14 }, - /* 670 */ { MAD_F(0x05b9ae95) /* 0.357832512 */, 14 }, - /* 671 */ { MAD_F(0x05bc9977) /* 0.358544794 */, 14 }, - - /* 672 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 14 }, - /* 673 */ { MAD_F(0x05c27057) /* 0.359970419 */, 14 }, - /* 674 */ { MAD_F(0x05c55c56) /* 0.360683761 */, 14 }, - /* 675 */ { MAD_F(0x05c848b3) /* 0.361397456 */, 14 }, - /* 676 */ { MAD_F(0x05cb356e) /* 0.362111504 */, 14 }, - /* 677 */ { MAD_F(0x05ce2289) /* 0.362825904 */, 14 }, - /* 678 */ { MAD_F(0x05d11001) /* 0.363540655 */, 14 }, - /* 679 */ { MAD_F(0x05d3fdd8) /* 0.364255759 */, 14 }, - /* 680 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 14 }, - /* 681 */ { MAD_F(0x05d9daa1) /* 0.365687018 */, 14 }, - /* 682 */ { MAD_F(0x05dcc993) /* 0.366403174 */, 14 }, - /* 683 */ { MAD_F(0x05dfb8e2) /* 0.367119680 */, 14 }, - /* 684 */ { MAD_F(0x05e2a890) /* 0.367836535 */, 14 }, - /* 685 */ { MAD_F(0x05e5989b) /* 0.368553740 */, 14 }, - /* 686 */ { MAD_F(0x05e88904) /* 0.369271294 */, 14 }, - /* 687 */ { MAD_F(0x05eb79cb) /* 0.369989197 */, 14 }, - - /* 688 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 14 }, - /* 689 */ { MAD_F(0x05f15c70) /* 0.371426047 */, 14 }, - /* 690 */ { MAD_F(0x05f44e4f) /* 0.372144994 */, 14 }, - /* 691 */ { MAD_F(0x05f7408b) /* 0.372864289 */, 14 }, - /* 692 */ { MAD_F(0x05fa3324) /* 0.373583930 */, 14 }, - /* 693 */ { MAD_F(0x05fd261b) /* 0.374303918 */, 14 }, - /* 694 */ { MAD_F(0x0600196e) /* 0.375024253 */, 14 }, - /* 695 */ { MAD_F(0x06030d1e) /* 0.375744934 */, 14 }, - /* 696 */ { MAD_F(0x0606012b) /* 0.376465960 */, 14 }, - /* 697 */ { MAD_F(0x0608f595) /* 0.377187332 */, 14 }, - /* 698 */ { MAD_F(0x060bea5c) /* 0.377909049 */, 14 }, - /* 699 */ { MAD_F(0x060edf7f) /* 0.378631110 */, 14 }, - /* 700 */ { MAD_F(0x0611d4fe) /* 0.379353516 */, 14 }, - /* 701 */ { MAD_F(0x0614cada) /* 0.380076266 */, 14 }, - /* 702 */ { MAD_F(0x0617c112) /* 0.380799360 */, 14 }, - /* 703 */ { MAD_F(0x061ab7a6) /* 0.381522798 */, 14 }, - - /* 704 */ { MAD_F(0x061dae96) /* 0.382246578 */, 14 }, - /* 705 */ { MAD_F(0x0620a5e3) /* 0.382970701 */, 14 }, - /* 706 */ { MAD_F(0x06239d8b) /* 0.383695167 */, 14 }, - /* 707 */ { MAD_F(0x0626958f) /* 0.384419975 */, 14 }, - /* 708 */ { MAD_F(0x06298def) /* 0.385145124 */, 14 }, - /* 709 */ { MAD_F(0x062c86aa) /* 0.385870615 */, 14 }, - /* 710 */ { MAD_F(0x062f7fc1) /* 0.386596448 */, 14 }, - /* 711 */ { MAD_F(0x06327934) /* 0.387322621 */, 14 }, - /* 712 */ { MAD_F(0x06357302) /* 0.388049134 */, 14 }, - /* 713 */ { MAD_F(0x06386d2b) /* 0.388775988 */, 14 }, - /* 714 */ { MAD_F(0x063b67b0) /* 0.389503182 */, 14 }, - /* 715 */ { MAD_F(0x063e6290) /* 0.390230715 */, 14 }, - /* 716 */ { MAD_F(0x06415dcb) /* 0.390958588 */, 14 }, - /* 717 */ { MAD_F(0x06445960) /* 0.391686799 */, 14 }, - /* 718 */ { MAD_F(0x06475551) /* 0.392415349 */, 14 }, - /* 719 */ { MAD_F(0x064a519c) /* 0.393144238 */, 14 }, - - /* 720 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 14 }, - /* 721 */ { MAD_F(0x06504b44) /* 0.394603028 */, 14 }, - /* 722 */ { MAD_F(0x0653489f) /* 0.395332930 */, 14 }, - /* 723 */ { MAD_F(0x06564655) /* 0.396063168 */, 14 }, - /* 724 */ { MAD_F(0x06594465) /* 0.396793743 */, 14 }, - /* 725 */ { MAD_F(0x065c42d0) /* 0.397524655 */, 14 }, - /* 726 */ { MAD_F(0x065f4195) /* 0.398255903 */, 14 }, - /* 727 */ { MAD_F(0x066240b4) /* 0.398987487 */, 14 }, - /* 728 */ { MAD_F(0x0665402d) /* 0.399719406 */, 14 }, - /* 729 */ { MAD_F(0x06684000) /* 0.400451660 */, 14 }, - /* 730 */ { MAD_F(0x066b402d) /* 0.401184249 */, 14 }, - /* 731 */ { MAD_F(0x066e40b3) /* 0.401917173 */, 14 }, - /* 732 */ { MAD_F(0x06714194) /* 0.402650431 */, 14 }, - /* 733 */ { MAD_F(0x067442ce) /* 0.403384024 */, 14 }, - /* 734 */ { MAD_F(0x06774462) /* 0.404117949 */, 14 }, - /* 735 */ { MAD_F(0x067a464f) /* 0.404852209 */, 14 }, - - /* 736 */ { MAD_F(0x067d4896) /* 0.405586801 */, 14 }, - /* 737 */ { MAD_F(0x06804b36) /* 0.406321726 */, 14 }, - /* 738 */ { MAD_F(0x06834e2f) /* 0.407056983 */, 14 }, - /* 739 */ { MAD_F(0x06865181) /* 0.407792573 */, 14 }, - /* 740 */ { MAD_F(0x0689552c) /* 0.408528495 */, 14 }, - /* 741 */ { MAD_F(0x068c5931) /* 0.409264748 */, 14 }, - /* 742 */ { MAD_F(0x068f5d8e) /* 0.410001332 */, 14 }, - /* 743 */ { MAD_F(0x06926245) /* 0.410738247 */, 14 }, - /* 744 */ { MAD_F(0x06956753) /* 0.411475493 */, 14 }, - /* 745 */ { MAD_F(0x06986cbb) /* 0.412213070 */, 14 }, - /* 746 */ { MAD_F(0x069b727b) /* 0.412950976 */, 14 }, - /* 747 */ { MAD_F(0x069e7894) /* 0.413689213 */, 14 }, - /* 748 */ { MAD_F(0x06a17f05) /* 0.414427779 */, 14 }, - /* 749 */ { MAD_F(0x06a485cf) /* 0.415166674 */, 14 }, - /* 750 */ { MAD_F(0x06a78cf1) /* 0.415905897 */, 14 }, - /* 751 */ { MAD_F(0x06aa946b) /* 0.416645450 */, 14 }, - - /* 752 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 14 }, - /* 753 */ { MAD_F(0x06b0a468) /* 0.418125540 */, 14 }, - /* 754 */ { MAD_F(0x06b3acea) /* 0.418866076 */, 14 }, - /* 755 */ { MAD_F(0x06b6b5c4) /* 0.419606940 */, 14 }, - /* 756 */ { MAD_F(0x06b9bef6) /* 0.420348132 */, 14 }, - /* 757 */ { MAD_F(0x06bcc880) /* 0.421089650 */, 14 }, - /* 758 */ { MAD_F(0x06bfd261) /* 0.421831494 */, 14 }, - /* 759 */ { MAD_F(0x06c2dc9a) /* 0.422573665 */, 14 }, - /* 760 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 14 }, - /* 761 */ { MAD_F(0x06c8f213) /* 0.424058985 */, 14 }, - /* 762 */ { MAD_F(0x06cbfd52) /* 0.424802133 */, 14 }, - /* 763 */ { MAD_F(0x06cf08e9) /* 0.425545607 */, 14 }, - /* 764 */ { MAD_F(0x06d214d7) /* 0.426289405 */, 14 }, - /* 765 */ { MAD_F(0x06d5211c) /* 0.427033528 */, 14 }, - /* 766 */ { MAD_F(0x06d82db8) /* 0.427777975 */, 14 }, - /* 767 */ { MAD_F(0x06db3aaa) /* 0.428522746 */, 14 }, - - /* 768 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 14 }, - /* 769 */ { MAD_F(0x06e15595) /* 0.430013259 */, 14 }, - /* 770 */ { MAD_F(0x06e4638d) /* 0.430759001 */, 14 }, - /* 771 */ { MAD_F(0x06e771db) /* 0.431505065 */, 14 }, - /* 772 */ { MAD_F(0x06ea807f) /* 0.432251452 */, 14 }, - /* 773 */ { MAD_F(0x06ed8f7b) /* 0.432998162 */, 14 }, - /* 774 */ { MAD_F(0x06f09ecc) /* 0.433745193 */, 14 }, - /* 775 */ { MAD_F(0x06f3ae75) /* 0.434492546 */, 14 }, - /* 776 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 14 }, - /* 777 */ { MAD_F(0x06f9cec8) /* 0.435988217 */, 14 }, - /* 778 */ { MAD_F(0x06fcdf72) /* 0.436736534 */, 14 }, - /* 779 */ { MAD_F(0x06fff073) /* 0.437485172 */, 14 }, - /* 780 */ { MAD_F(0x070301ca) /* 0.438234130 */, 14 }, - /* 781 */ { MAD_F(0x07061377) /* 0.438983408 */, 14 }, - /* 782 */ { MAD_F(0x0709257a) /* 0.439733006 */, 14 }, - /* 783 */ { MAD_F(0x070c37d2) /* 0.440482924 */, 14 }, - - /* 784 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 14 }, - /* 785 */ { MAD_F(0x07125d84) /* 0.441983717 */, 14 }, - /* 786 */ { MAD_F(0x071570de) /* 0.442734592 */, 14 }, - /* 787 */ { MAD_F(0x0718848d) /* 0.443485785 */, 14 }, - /* 788 */ { MAD_F(0x071b9891) /* 0.444237296 */, 14 }, - /* 789 */ { MAD_F(0x071eaceb) /* 0.444989126 */, 14 }, - /* 790 */ { MAD_F(0x0721c19a) /* 0.445741273 */, 14 }, - /* 791 */ { MAD_F(0x0724d69e) /* 0.446493738 */, 14 }, - /* 792 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 14 }, - /* 793 */ { MAD_F(0x072b01a6) /* 0.447999618 */, 14 }, - /* 794 */ { MAD_F(0x072e17a9) /* 0.448753033 */, 14 }, - /* 795 */ { MAD_F(0x07312e01) /* 0.449506765 */, 14 }, - /* 796 */ { MAD_F(0x073444ae) /* 0.450260813 */, 14 }, - /* 797 */ { MAD_F(0x07375bb0) /* 0.451015176 */, 14 }, - /* 798 */ { MAD_F(0x073a7307) /* 0.451769856 */, 14 }, - /* 799 */ { MAD_F(0x073d8ab2) /* 0.452524850 */, 14 }, - - /* 800 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 14 }, - /* 801 */ { MAD_F(0x0743bb06) /* 0.454035784 */, 14 }, - /* 802 */ { MAD_F(0x0746d3af) /* 0.454791723 */, 14 }, - /* 803 */ { MAD_F(0x0749ecac) /* 0.455547976 */, 14 }, - /* 804 */ { MAD_F(0x074d05fe) /* 0.456304543 */, 14 }, - /* 805 */ { MAD_F(0x07501fa3) /* 0.457061423 */, 14 }, - /* 806 */ { MAD_F(0x0753399d) /* 0.457818618 */, 14 }, - /* 807 */ { MAD_F(0x075653eb) /* 0.458576125 */, 14 }, - /* 808 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 14 }, - /* 809 */ { MAD_F(0x075c8983) /* 0.460092079 */, 14 }, - /* 810 */ { MAD_F(0x075fa4cc) /* 0.460850524 */, 14 }, - /* 811 */ { MAD_F(0x0762c06a) /* 0.461609282 */, 14 }, - /* 812 */ { MAD_F(0x0765dc5b) /* 0.462368352 */, 14 }, - /* 813 */ { MAD_F(0x0768f8a0) /* 0.463127733 */, 14 }, - /* 814 */ { MAD_F(0x076c1538) /* 0.463887426 */, 14 }, - /* 815 */ { MAD_F(0x076f3224) /* 0.464647430 */, 14 }, - - /* 816 */ { MAD_F(0x07724f64) /* 0.465407744 */, 14 }, - /* 817 */ { MAD_F(0x07756cf7) /* 0.466168370 */, 14 }, - /* 818 */ { MAD_F(0x07788add) /* 0.466929306 */, 14 }, - /* 819 */ { MAD_F(0x077ba916) /* 0.467690552 */, 14 }, - /* 820 */ { MAD_F(0x077ec7a3) /* 0.468452108 */, 14 }, - /* 821 */ { MAD_F(0x0781e683) /* 0.469213973 */, 14 }, - /* 822 */ { MAD_F(0x078505b5) /* 0.469976148 */, 14 }, - /* 823 */ { MAD_F(0x0788253b) /* 0.470738632 */, 14 }, - /* 824 */ { MAD_F(0x078b4514) /* 0.471501425 */, 14 }, - /* 825 */ { MAD_F(0x078e653f) /* 0.472264527 */, 14 }, - /* 826 */ { MAD_F(0x079185be) /* 0.473027937 */, 14 }, - /* 827 */ { MAD_F(0x0794a68f) /* 0.473791655 */, 14 }, - /* 828 */ { MAD_F(0x0797c7b2) /* 0.474555681 */, 14 }, - /* 829 */ { MAD_F(0x079ae929) /* 0.475320014 */, 14 }, - /* 830 */ { MAD_F(0x079e0af1) /* 0.476084655 */, 14 }, - /* 831 */ { MAD_F(0x07a12d0c) /* 0.476849603 */, 14 }, - - /* 832 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 14 }, - /* 833 */ { MAD_F(0x07a7723a) /* 0.478380420 */, 14 }, - /* 834 */ { MAD_F(0x07aa954c) /* 0.479146288 */, 14 }, - /* 835 */ { MAD_F(0x07adb8b0) /* 0.479912463 */, 14 }, - /* 836 */ { MAD_F(0x07b0dc67) /* 0.480678943 */, 14 }, - /* 837 */ { MAD_F(0x07b4006f) /* 0.481445729 */, 14 }, - /* 838 */ { MAD_F(0x07b724ca) /* 0.482212820 */, 14 }, - /* 839 */ { MAD_F(0x07ba4976) /* 0.482980216 */, 14 }, - /* 840 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 14 }, - /* 841 */ { MAD_F(0x07c093c5) /* 0.484515924 */, 14 }, - /* 842 */ { MAD_F(0x07c3b967) /* 0.485284235 */, 14 }, - /* 843 */ { MAD_F(0x07c6df5a) /* 0.486052849 */, 14 }, - /* 844 */ { MAD_F(0x07ca059f) /* 0.486821768 */, 14 }, - /* 845 */ { MAD_F(0x07cd2c36) /* 0.487590991 */, 14 }, - /* 846 */ { MAD_F(0x07d0531e) /* 0.488360517 */, 14 }, - /* 847 */ { MAD_F(0x07d37a57) /* 0.489130346 */, 14 }, - - /* 848 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 14 }, - /* 849 */ { MAD_F(0x07d9c9be) /* 0.490670914 */, 14 }, - /* 850 */ { MAD_F(0x07dcf1ec) /* 0.491441651 */, 14 }, - /* 851 */ { MAD_F(0x07e01a6a) /* 0.492212691 */, 14 }, - /* 852 */ { MAD_F(0x07e3433a) /* 0.492984033 */, 14 }, - /* 853 */ { MAD_F(0x07e66c5a) /* 0.493755677 */, 14 }, - /* 854 */ { MAD_F(0x07e995cc) /* 0.494527623 */, 14 }, - /* 855 */ { MAD_F(0x07ecbf8e) /* 0.495299870 */, 14 }, - /* 856 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 14 }, - /* 857 */ { MAD_F(0x07f31405) /* 0.496845266 */, 14 }, - /* 858 */ { MAD_F(0x07f63eba) /* 0.497618416 */, 14 }, - /* 859 */ { MAD_F(0x07f969c0) /* 0.498391866 */, 14 }, - /* 860 */ { MAD_F(0x07fc9516) /* 0.499165616 */, 14 }, - /* 861 */ { MAD_F(0x07ffc0bc) /* 0.499939666 */, 14 }, - /* 862 */ { MAD_F(0x04017659) /* 0.250357008 */, 15 }, - /* 863 */ { MAD_F(0x04030c7d) /* 0.250744333 */, 15 }, - - /* 864 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 15 }, - /* 865 */ { MAD_F(0x0406393d) /* 0.251519431 */, 15 }, - /* 866 */ { MAD_F(0x0407cfd9) /* 0.251907204 */, 15 }, - /* 867 */ { MAD_F(0x0409669d) /* 0.252295127 */, 15 }, - /* 868 */ { MAD_F(0x040afd89) /* 0.252683198 */, 15 }, - /* 869 */ { MAD_F(0x040c949e) /* 0.253071419 */, 15 }, - /* 870 */ { MAD_F(0x040e2bda) /* 0.253459789 */, 15 }, - /* 871 */ { MAD_F(0x040fc33e) /* 0.253848307 */, 15 }, - /* 872 */ { MAD_F(0x04115aca) /* 0.254236974 */, 15 }, - /* 873 */ { MAD_F(0x0412f27e) /* 0.254625790 */, 15 }, - /* 874 */ { MAD_F(0x04148a5a) /* 0.255014755 */, 15 }, - /* 875 */ { MAD_F(0x0416225d) /* 0.255403867 */, 15 }, - /* 876 */ { MAD_F(0x0417ba89) /* 0.255793128 */, 15 }, - /* 877 */ { MAD_F(0x041952dc) /* 0.256182537 */, 15 }, - /* 878 */ { MAD_F(0x041aeb57) /* 0.256572095 */, 15 }, - /* 879 */ { MAD_F(0x041c83fa) /* 0.256961800 */, 15 }, - - /* 880 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 15 }, - /* 881 */ { MAD_F(0x041fb5b6) /* 0.257741653 */, 15 }, - /* 882 */ { MAD_F(0x04214ed0) /* 0.258131801 */, 15 }, - /* 883 */ { MAD_F(0x0422e811) /* 0.258522097 */, 15 }, - /* 884 */ { MAD_F(0x04248179) /* 0.258912540 */, 15 }, - /* 885 */ { MAD_F(0x04261b0a) /* 0.259303130 */, 15 }, - /* 886 */ { MAD_F(0x0427b4c2) /* 0.259693868 */, 15 }, - /* 887 */ { MAD_F(0x04294ea1) /* 0.260084752 */, 15 }, - /* 888 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 15 }, - /* 889 */ { MAD_F(0x042c82d6) /* 0.260866961 */, 15 }, - /* 890 */ { MAD_F(0x042e1d2b) /* 0.261258286 */, 15 }, - /* 891 */ { MAD_F(0x042fb7a8) /* 0.261649758 */, 15 }, - /* 892 */ { MAD_F(0x0431524c) /* 0.262041376 */, 15 }, - /* 893 */ { MAD_F(0x0432ed17) /* 0.262433140 */, 15 }, - /* 894 */ { MAD_F(0x0434880a) /* 0.262825051 */, 15 }, - /* 895 */ { MAD_F(0x04362324) /* 0.263217107 */, 15 }, - - /* 896 */ { MAD_F(0x0437be65) /* 0.263609310 */, 15 }, - /* 897 */ { MAD_F(0x043959cd) /* 0.264001659 */, 15 }, - /* 898 */ { MAD_F(0x043af55d) /* 0.264394153 */, 15 }, - /* 899 */ { MAD_F(0x043c9113) /* 0.264786794 */, 15 }, - /* 900 */ { MAD_F(0x043e2cf1) /* 0.265179580 */, 15 }, - /* 901 */ { MAD_F(0x043fc8f6) /* 0.265572511 */, 15 }, - /* 902 */ { MAD_F(0x04416522) /* 0.265965588 */, 15 }, - /* 903 */ { MAD_F(0x04430174) /* 0.266358810 */, 15 }, - /* 904 */ { MAD_F(0x04449dee) /* 0.266752177 */, 15 }, - /* 905 */ { MAD_F(0x04463a8f) /* 0.267145689 */, 15 }, - /* 906 */ { MAD_F(0x0447d756) /* 0.267539347 */, 15 }, - /* 907 */ { MAD_F(0x04497445) /* 0.267933149 */, 15 }, - /* 908 */ { MAD_F(0x044b115a) /* 0.268327096 */, 15 }, - /* 909 */ { MAD_F(0x044cae96) /* 0.268721187 */, 15 }, - /* 910 */ { MAD_F(0x044e4bf9) /* 0.269115423 */, 15 }, - /* 911 */ { MAD_F(0x044fe983) /* 0.269509804 */, 15 }, - - /* 912 */ { MAD_F(0x04518733) /* 0.269904329 */, 15 }, - /* 913 */ { MAD_F(0x0453250a) /* 0.270298998 */, 15 }, - /* 914 */ { MAD_F(0x0454c308) /* 0.270693811 */, 15 }, - /* 915 */ { MAD_F(0x0456612d) /* 0.271088768 */, 15 }, - /* 916 */ { MAD_F(0x0457ff78) /* 0.271483869 */, 15 }, - /* 917 */ { MAD_F(0x04599dea) /* 0.271879114 */, 15 }, - /* 918 */ { MAD_F(0x045b3c82) /* 0.272274503 */, 15 }, - /* 919 */ { MAD_F(0x045cdb41) /* 0.272670035 */, 15 }, - /* 920 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 15 }, - /* 921 */ { MAD_F(0x04601932) /* 0.273461530 */, 15 }, - /* 922 */ { MAD_F(0x0461b864) /* 0.273857492 */, 15 }, - /* 923 */ { MAD_F(0x046357bd) /* 0.274253597 */, 15 }, - /* 924 */ { MAD_F(0x0464f73c) /* 0.274649846 */, 15 }, - /* 925 */ { MAD_F(0x046696e2) /* 0.275046238 */, 15 }, - /* 926 */ { MAD_F(0x046836ae) /* 0.275442772 */, 15 }, - /* 927 */ { MAD_F(0x0469d6a0) /* 0.275839449 */, 15 }, - - /* 928 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 15 }, - /* 929 */ { MAD_F(0x046d16f7) /* 0.276633232 */, 15 }, - /* 930 */ { MAD_F(0x046eb75c) /* 0.277030337 */, 15 }, - /* 931 */ { MAD_F(0x047057e8) /* 0.277427584 */, 15 }, - /* 932 */ { MAD_F(0x0471f899) /* 0.277824973 */, 15 }, - /* 933 */ { MAD_F(0x04739971) /* 0.278222505 */, 15 }, - /* 934 */ { MAD_F(0x04753a6f) /* 0.278620179 */, 15 }, - /* 935 */ { MAD_F(0x0476db92) /* 0.279017995 */, 15 }, - /* 936 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 15 }, - /* 937 */ { MAD_F(0x047a1e4c) /* 0.279814051 */, 15 }, - /* 938 */ { MAD_F(0x047bbfe2) /* 0.280212292 */, 15 }, - /* 939 */ { MAD_F(0x047d619e) /* 0.280610675 */, 15 }, - /* 940 */ { MAD_F(0x047f0380) /* 0.281009199 */, 15 }, - /* 941 */ { MAD_F(0x0480a588) /* 0.281407864 */, 15 }, - /* 942 */ { MAD_F(0x048247b6) /* 0.281806670 */, 15 }, - /* 943 */ { MAD_F(0x0483ea0a) /* 0.282205618 */, 15 }, - - /* 944 */ { MAD_F(0x04858c83) /* 0.282604707 */, 15 }, - /* 945 */ { MAD_F(0x04872f22) /* 0.283003936 */, 15 }, - /* 946 */ { MAD_F(0x0488d1e8) /* 0.283403307 */, 15 }, - /* 947 */ { MAD_F(0x048a74d3) /* 0.283802818 */, 15 }, - /* 948 */ { MAD_F(0x048c17e3) /* 0.284202470 */, 15 }, - /* 949 */ { MAD_F(0x048dbb1a) /* 0.284602263 */, 15 }, - /* 950 */ { MAD_F(0x048f5e76) /* 0.285002195 */, 15 }, - /* 951 */ { MAD_F(0x049101f8) /* 0.285402269 */, 15 }, - /* 952 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 15 }, - /* 953 */ { MAD_F(0x0494496c) /* 0.286202836 */, 15 }, - /* 954 */ { MAD_F(0x0495ed5f) /* 0.286603329 */, 15 }, - /* 955 */ { MAD_F(0x04979177) /* 0.287003963 */, 15 }, - /* 956 */ { MAD_F(0x049935b5) /* 0.287404737 */, 15 }, - /* 957 */ { MAD_F(0x049ada19) /* 0.287805650 */, 15 }, - /* 958 */ { MAD_F(0x049c7ea1) /* 0.288206703 */, 15 }, - /* 959 */ { MAD_F(0x049e2350) /* 0.288607895 */, 15 }, - - /* 960 */ { MAD_F(0x049fc824) /* 0.289009227 */, 15 }, - /* 961 */ { MAD_F(0x04a16d1d) /* 0.289410699 */, 15 }, - /* 962 */ { MAD_F(0x04a3123b) /* 0.289812309 */, 15 }, - /* 963 */ { MAD_F(0x04a4b77f) /* 0.290214059 */, 15 }, - /* 964 */ { MAD_F(0x04a65ce8) /* 0.290615948 */, 15 }, - /* 965 */ { MAD_F(0x04a80277) /* 0.291017976 */, 15 }, - /* 966 */ { MAD_F(0x04a9a82b) /* 0.291420143 */, 15 }, - /* 967 */ { MAD_F(0x04ab4e04) /* 0.291822449 */, 15 }, - /* 968 */ { MAD_F(0x04acf402) /* 0.292224893 */, 15 }, - /* 969 */ { MAD_F(0x04ae9a26) /* 0.292627476 */, 15 }, - /* 970 */ { MAD_F(0x04b0406e) /* 0.293030197 */, 15 }, - /* 971 */ { MAD_F(0x04b1e6dc) /* 0.293433057 */, 15 }, - /* 972 */ { MAD_F(0x04b38d6f) /* 0.293836055 */, 15 }, - /* 973 */ { MAD_F(0x04b53427) /* 0.294239192 */, 15 }, - /* 974 */ { MAD_F(0x04b6db05) /* 0.294642466 */, 15 }, - /* 975 */ { MAD_F(0x04b88207) /* 0.295045879 */, 15 }, - - /* 976 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 15 }, - /* 977 */ { MAD_F(0x04bbd07a) /* 0.295853118 */, 15 }, - /* 978 */ { MAD_F(0x04bd77ec) /* 0.296256944 */, 15 }, - /* 979 */ { MAD_F(0x04bf1f82) /* 0.296660907 */, 15 }, - /* 980 */ { MAD_F(0x04c0c73d) /* 0.297065009 */, 15 }, - /* 981 */ { MAD_F(0x04c26f1d) /* 0.297469248 */, 15 }, - /* 982 */ { MAD_F(0x04c41722) /* 0.297873624 */, 15 }, - /* 983 */ { MAD_F(0x04c5bf4c) /* 0.298278137 */, 15 }, - /* 984 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 15 }, - /* 985 */ { MAD_F(0x04c9100d) /* 0.299087576 */, 15 }, - /* 986 */ { MAD_F(0x04cab8a6) /* 0.299492500 */, 15 }, - /* 987 */ { MAD_F(0x04cc6163) /* 0.299897562 */, 15 }, - /* 988 */ { MAD_F(0x04ce0a44) /* 0.300302761 */, 15 }, - /* 989 */ { MAD_F(0x04cfb34b) /* 0.300708096 */, 15 }, - /* 990 */ { MAD_F(0x04d15c76) /* 0.301113568 */, 15 }, - /* 991 */ { MAD_F(0x04d305c5) /* 0.301519176 */, 15 }, - - /* 992 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 15 }, - /* 993 */ { MAD_F(0x04d658d2) /* 0.302330802 */, 15 }, - /* 994 */ { MAD_F(0x04d80290) /* 0.302736820 */, 15 }, - /* 995 */ { MAD_F(0x04d9ac72) /* 0.303142973 */, 15 }, - /* 996 */ { MAD_F(0x04db5679) /* 0.303549263 */, 15 }, - /* 997 */ { MAD_F(0x04dd00a4) /* 0.303955689 */, 15 }, - /* 998 */ { MAD_F(0x04deaaf3) /* 0.304362251 */, 15 }, - /* 999 */ { MAD_F(0x04e05567) /* 0.304768948 */, 15 }, - /* 1000 */ { MAD_F(0x04e20000) /* 0.305175781 */, 15 }, - /* 1001 */ { MAD_F(0x04e3aabd) /* 0.305582750 */, 15 }, - /* 1002 */ { MAD_F(0x04e5559e) /* 0.305989854 */, 15 }, - /* 1003 */ { MAD_F(0x04e700a3) /* 0.306397094 */, 15 }, - /* 1004 */ { MAD_F(0x04e8abcd) /* 0.306804470 */, 15 }, - /* 1005 */ { MAD_F(0x04ea571c) /* 0.307211980 */, 15 }, - /* 1006 */ { MAD_F(0x04ec028e) /* 0.307619626 */, 15 }, - /* 1007 */ { MAD_F(0x04edae25) /* 0.308027406 */, 15 }, - - /* 1008 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 15 }, - /* 1009 */ { MAD_F(0x04f105bf) /* 0.308843373 */, 15 }, - /* 1010 */ { MAD_F(0x04f2b1c3) /* 0.309251558 */, 15 }, - /* 1011 */ { MAD_F(0x04f45dea) /* 0.309659879 */, 15 }, - /* 1012 */ { MAD_F(0x04f60a36) /* 0.310068333 */, 15 }, - /* 1013 */ { MAD_F(0x04f7b6a6) /* 0.310476923 */, 15 }, - /* 1014 */ { MAD_F(0x04f9633a) /* 0.310885647 */, 15 }, - /* 1015 */ { MAD_F(0x04fb0ff2) /* 0.311294505 */, 15 }, - /* 1016 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 15 }, - /* 1017 */ { MAD_F(0x04fe69ce) /* 0.312112625 */, 15 }, - /* 1018 */ { MAD_F(0x050016f3) /* 0.312521885 */, 15 }, - /* 1019 */ { MAD_F(0x0501c43b) /* 0.312931280 */, 15 }, - /* 1020 */ { MAD_F(0x050371a7) /* 0.313340809 */, 15 }, - /* 1021 */ { MAD_F(0x05051f37) /* 0.313750472 */, 15 }, - /* 1022 */ { MAD_F(0x0506cceb) /* 0.314160269 */, 15 }, - /* 1023 */ { MAD_F(0x05087ac2) /* 0.314570199 */, 15 }, - - /* 1024 */ { MAD_F(0x050a28be) /* 0.314980262 */, 15 }, - /* 1025 */ { MAD_F(0x050bd6de) /* 0.315390460 */, 15 }, - /* 1026 */ { MAD_F(0x050d8521) /* 0.315800790 */, 15 }, - /* 1027 */ { MAD_F(0x050f3388) /* 0.316211255 */, 15 }, - /* 1028 */ { MAD_F(0x0510e213) /* 0.316621852 */, 15 }, - /* 1029 */ { MAD_F(0x051290c2) /* 0.317032582 */, 15 }, - /* 1030 */ { MAD_F(0x05143f94) /* 0.317443446 */, 15 }, - /* 1031 */ { MAD_F(0x0515ee8a) /* 0.317854442 */, 15 }, - /* 1032 */ { MAD_F(0x05179da4) /* 0.318265572 */, 15 }, - /* 1033 */ { MAD_F(0x05194ce1) /* 0.318676834 */, 15 }, - /* 1034 */ { MAD_F(0x051afc42) /* 0.319088229 */, 15 }, - /* 1035 */ { MAD_F(0x051cabc7) /* 0.319499756 */, 15 }, - /* 1036 */ { MAD_F(0x051e5b6f) /* 0.319911417 */, 15 }, - /* 1037 */ { MAD_F(0x05200b3a) /* 0.320323209 */, 15 }, - /* 1038 */ { MAD_F(0x0521bb2a) /* 0.320735134 */, 15 }, - /* 1039 */ { MAD_F(0x05236b3d) /* 0.321147192 */, 15 }, - - /* 1040 */ { MAD_F(0x05251b73) /* 0.321559381 */, 15 }, - /* 1041 */ { MAD_F(0x0526cbcd) /* 0.321971703 */, 15 }, - /* 1042 */ { MAD_F(0x05287c4a) /* 0.322384156 */, 15 }, - /* 1043 */ { MAD_F(0x052a2cea) /* 0.322796742 */, 15 }, - /* 1044 */ { MAD_F(0x052bddae) /* 0.323209460 */, 15 }, - /* 1045 */ { MAD_F(0x052d8e96) /* 0.323622309 */, 15 }, - /* 1046 */ { MAD_F(0x052f3fa1) /* 0.324035290 */, 15 }, - /* 1047 */ { MAD_F(0x0530f0cf) /* 0.324448403 */, 15 }, - /* 1048 */ { MAD_F(0x0532a220) /* 0.324861647 */, 15 }, - /* 1049 */ { MAD_F(0x05345395) /* 0.325275023 */, 15 }, - /* 1050 */ { MAD_F(0x0536052d) /* 0.325688530 */, 15 }, - /* 1051 */ { MAD_F(0x0537b6e8) /* 0.326102168 */, 15 }, - /* 1052 */ { MAD_F(0x053968c6) /* 0.326515938 */, 15 }, - /* 1053 */ { MAD_F(0x053b1ac8) /* 0.326929839 */, 15 }, - /* 1054 */ { MAD_F(0x053ccced) /* 0.327343870 */, 15 }, - /* 1055 */ { MAD_F(0x053e7f35) /* 0.327758033 */, 15 }, - - /* 1056 */ { MAD_F(0x054031a0) /* 0.328172327 */, 15 }, - /* 1057 */ { MAD_F(0x0541e42e) /* 0.328586751 */, 15 }, - /* 1058 */ { MAD_F(0x054396df) /* 0.329001306 */, 15 }, - /* 1059 */ { MAD_F(0x054549b4) /* 0.329415992 */, 15 }, - /* 1060 */ { MAD_F(0x0546fcab) /* 0.329830808 */, 15 }, - /* 1061 */ { MAD_F(0x0548afc6) /* 0.330245755 */, 15 }, - /* 1062 */ { MAD_F(0x054a6303) /* 0.330660832 */, 15 }, - /* 1063 */ { MAD_F(0x054c1663) /* 0.331076039 */, 15 }, - /* 1064 */ { MAD_F(0x054dc9e7) /* 0.331491377 */, 15 }, - /* 1065 */ { MAD_F(0x054f7d8d) /* 0.331906845 */, 15 }, - /* 1066 */ { MAD_F(0x05513156) /* 0.332322443 */, 15 }, - /* 1067 */ { MAD_F(0x0552e542) /* 0.332738170 */, 15 }, - /* 1068 */ { MAD_F(0x05549951) /* 0.333154028 */, 15 }, - /* 1069 */ { MAD_F(0x05564d83) /* 0.333570016 */, 15 }, - /* 1070 */ { MAD_F(0x055801d8) /* 0.333986133 */, 15 }, - /* 1071 */ { MAD_F(0x0559b64f) /* 0.334402380 */, 15 }, - - /* 1072 */ { MAD_F(0x055b6ae9) /* 0.334818756 */, 15 }, - /* 1073 */ { MAD_F(0x055d1fa6) /* 0.335235262 */, 15 }, - /* 1074 */ { MAD_F(0x055ed486) /* 0.335651898 */, 15 }, - /* 1075 */ { MAD_F(0x05608988) /* 0.336068662 */, 15 }, - /* 1076 */ { MAD_F(0x05623ead) /* 0.336485556 */, 15 }, - /* 1077 */ { MAD_F(0x0563f3f5) /* 0.336902579 */, 15 }, - /* 1078 */ { MAD_F(0x0565a960) /* 0.337319732 */, 15 }, - /* 1079 */ { MAD_F(0x05675eed) /* 0.337737013 */, 15 }, - /* 1080 */ { MAD_F(0x0569149c) /* 0.338154423 */, 15 }, - /* 1081 */ { MAD_F(0x056aca6f) /* 0.338571962 */, 15 }, - /* 1082 */ { MAD_F(0x056c8064) /* 0.338989630 */, 15 }, - /* 1083 */ { MAD_F(0x056e367b) /* 0.339407426 */, 15 }, - /* 1084 */ { MAD_F(0x056fecb5) /* 0.339825351 */, 15 }, - /* 1085 */ { MAD_F(0x0571a311) /* 0.340243405 */, 15 }, - /* 1086 */ { MAD_F(0x05735990) /* 0.340661587 */, 15 }, - /* 1087 */ { MAD_F(0x05751032) /* 0.341079898 */, 15 }, - - /* 1088 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 15 }, - /* 1089 */ { MAD_F(0x05787ddc) /* 0.341916903 */, 15 }, - /* 1090 */ { MAD_F(0x057a34e4) /* 0.342335598 */, 15 }, - /* 1091 */ { MAD_F(0x057bec0f) /* 0.342754421 */, 15 }, - /* 1092 */ { MAD_F(0x057da35d) /* 0.343173373 */, 15 }, - /* 1093 */ { MAD_F(0x057f5acc) /* 0.343592452 */, 15 }, - /* 1094 */ { MAD_F(0x0581125e) /* 0.344011659 */, 15 }, - /* 1095 */ { MAD_F(0x0582ca12) /* 0.344430993 */, 15 }, - /* 1096 */ { MAD_F(0x058481e9) /* 0.344850455 */, 15 }, - /* 1097 */ { MAD_F(0x058639e2) /* 0.345270045 */, 15 }, - /* 1098 */ { MAD_F(0x0587f1fd) /* 0.345689763 */, 15 }, - /* 1099 */ { MAD_F(0x0589aa3a) /* 0.346109608 */, 15 }, - /* 1100 */ { MAD_F(0x058b629a) /* 0.346529580 */, 15 }, - /* 1101 */ { MAD_F(0x058d1b1b) /* 0.346949679 */, 15 }, - /* 1102 */ { MAD_F(0x058ed3bf) /* 0.347369906 */, 15 }, - /* 1103 */ { MAD_F(0x05908c85) /* 0.347790260 */, 15 }, - - /* 1104 */ { MAD_F(0x0592456d) /* 0.348210741 */, 15 }, - /* 1105 */ { MAD_F(0x0593fe77) /* 0.348631348 */, 15 }, - /* 1106 */ { MAD_F(0x0595b7a3) /* 0.349052083 */, 15 }, - /* 1107 */ { MAD_F(0x059770f1) /* 0.349472945 */, 15 }, - /* 1108 */ { MAD_F(0x05992a61) /* 0.349893933 */, 15 }, - /* 1109 */ { MAD_F(0x059ae3f3) /* 0.350315048 */, 15 }, - /* 1110 */ { MAD_F(0x059c9da8) /* 0.350736290 */, 15 }, - /* 1111 */ { MAD_F(0x059e577e) /* 0.351157658 */, 15 }, - /* 1112 */ { MAD_F(0x05a01176) /* 0.351579152 */, 15 }, - /* 1113 */ { MAD_F(0x05a1cb90) /* 0.352000773 */, 15 }, - /* 1114 */ { MAD_F(0x05a385cc) /* 0.352422520 */, 15 }, - /* 1115 */ { MAD_F(0x05a5402a) /* 0.352844394 */, 15 }, - /* 1116 */ { MAD_F(0x05a6faa9) /* 0.353266393 */, 15 }, - /* 1117 */ { MAD_F(0x05a8b54b) /* 0.353688519 */, 15 }, - /* 1118 */ { MAD_F(0x05aa700e) /* 0.354110771 */, 15 }, - /* 1119 */ { MAD_F(0x05ac2af3) /* 0.354533148 */, 15 }, - - /* 1120 */ { MAD_F(0x05ade5fa) /* 0.354955651 */, 15 }, - /* 1121 */ { MAD_F(0x05afa123) /* 0.355378281 */, 15 }, - /* 1122 */ { MAD_F(0x05b15c6d) /* 0.355801035 */, 15 }, - /* 1123 */ { MAD_F(0x05b317d9) /* 0.356223916 */, 15 }, - /* 1124 */ { MAD_F(0x05b4d367) /* 0.356646922 */, 15 }, - /* 1125 */ { MAD_F(0x05b68f16) /* 0.357070053 */, 15 }, - /* 1126 */ { MAD_F(0x05b84ae7) /* 0.357493310 */, 15 }, - /* 1127 */ { MAD_F(0x05ba06da) /* 0.357916692 */, 15 }, - /* 1128 */ { MAD_F(0x05bbc2ef) /* 0.358340200 */, 15 }, - /* 1129 */ { MAD_F(0x05bd7f25) /* 0.358763832 */, 15 }, - /* 1130 */ { MAD_F(0x05bf3b7c) /* 0.359187590 */, 15 }, - /* 1131 */ { MAD_F(0x05c0f7f5) /* 0.359611472 */, 15 }, - /* 1132 */ { MAD_F(0x05c2b490) /* 0.360035480 */, 15 }, - /* 1133 */ { MAD_F(0x05c4714c) /* 0.360459613 */, 15 }, - /* 1134 */ { MAD_F(0x05c62e2a) /* 0.360883870 */, 15 }, - /* 1135 */ { MAD_F(0x05c7eb29) /* 0.361308252 */, 15 }, - - /* 1136 */ { MAD_F(0x05c9a84a) /* 0.361732758 */, 15 }, - /* 1137 */ { MAD_F(0x05cb658c) /* 0.362157390 */, 15 }, - /* 1138 */ { MAD_F(0x05cd22ef) /* 0.362582145 */, 15 }, - /* 1139 */ { MAD_F(0x05cee074) /* 0.363007026 */, 15 }, - /* 1140 */ { MAD_F(0x05d09e1b) /* 0.363432030 */, 15 }, - /* 1141 */ { MAD_F(0x05d25be2) /* 0.363857159 */, 15 }, - /* 1142 */ { MAD_F(0x05d419cb) /* 0.364282412 */, 15 }, - /* 1143 */ { MAD_F(0x05d5d7d5) /* 0.364707789 */, 15 }, - /* 1144 */ { MAD_F(0x05d79601) /* 0.365133291 */, 15 }, - /* 1145 */ { MAD_F(0x05d9544e) /* 0.365558916 */, 15 }, - /* 1146 */ { MAD_F(0x05db12bc) /* 0.365984665 */, 15 }, - /* 1147 */ { MAD_F(0x05dcd14c) /* 0.366410538 */, 15 }, - /* 1148 */ { MAD_F(0x05de8ffc) /* 0.366836535 */, 15 }, - /* 1149 */ { MAD_F(0x05e04ece) /* 0.367262655 */, 15 }, - /* 1150 */ { MAD_F(0x05e20dc1) /* 0.367688900 */, 15 }, - /* 1151 */ { MAD_F(0x05e3ccd5) /* 0.368115267 */, 15 }, - - /* 1152 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 15 }, - /* 1153 */ { MAD_F(0x05e74b61) /* 0.368968373 */, 15 }, - /* 1154 */ { MAD_F(0x05e90ad9) /* 0.369395111 */, 15 }, - /* 1155 */ { MAD_F(0x05eaca72) /* 0.369821973 */, 15 }, - /* 1156 */ { MAD_F(0x05ec8a2b) /* 0.370248957 */, 15 }, - /* 1157 */ { MAD_F(0x05ee4a06) /* 0.370676065 */, 15 }, - /* 1158 */ { MAD_F(0x05f00a02) /* 0.371103295 */, 15 }, - /* 1159 */ { MAD_F(0x05f1ca1f) /* 0.371530649 */, 15 }, - /* 1160 */ { MAD_F(0x05f38a5d) /* 0.371958126 */, 15 }, - /* 1161 */ { MAD_F(0x05f54abc) /* 0.372385725 */, 15 }, - /* 1162 */ { MAD_F(0x05f70b3c) /* 0.372813448 */, 15 }, - /* 1163 */ { MAD_F(0x05f8cbdc) /* 0.373241292 */, 15 }, - /* 1164 */ { MAD_F(0x05fa8c9e) /* 0.373669260 */, 15 }, - /* 1165 */ { MAD_F(0x05fc4d81) /* 0.374097350 */, 15 }, - /* 1166 */ { MAD_F(0x05fe0e84) /* 0.374525563 */, 15 }, - /* 1167 */ { MAD_F(0x05ffcfa8) /* 0.374953898 */, 15 }, - - /* 1168 */ { MAD_F(0x060190ee) /* 0.375382356 */, 15 }, - /* 1169 */ { MAD_F(0x06035254) /* 0.375810936 */, 15 }, - /* 1170 */ { MAD_F(0x060513da) /* 0.376239638 */, 15 }, - /* 1171 */ { MAD_F(0x0606d582) /* 0.376668462 */, 15 }, - /* 1172 */ { MAD_F(0x0608974a) /* 0.377097408 */, 15 }, - /* 1173 */ { MAD_F(0x060a5934) /* 0.377526476 */, 15 }, - /* 1174 */ { MAD_F(0x060c1b3d) /* 0.377955667 */, 15 }, - /* 1175 */ { MAD_F(0x060ddd68) /* 0.378384979 */, 15 }, - /* 1176 */ { MAD_F(0x060f9fb3) /* 0.378814413 */, 15 }, - /* 1177 */ { MAD_F(0x0611621f) /* 0.379243968 */, 15 }, - /* 1178 */ { MAD_F(0x061324ac) /* 0.379673646 */, 15 }, - /* 1179 */ { MAD_F(0x0614e759) /* 0.380103444 */, 15 }, - /* 1180 */ { MAD_F(0x0616aa27) /* 0.380533365 */, 15 }, - /* 1181 */ { MAD_F(0x06186d16) /* 0.380963407 */, 15 }, - /* 1182 */ { MAD_F(0x061a3025) /* 0.381393570 */, 15 }, - /* 1183 */ { MAD_F(0x061bf354) /* 0.381823855 */, 15 }, - - /* 1184 */ { MAD_F(0x061db6a5) /* 0.382254261 */, 15 }, - /* 1185 */ { MAD_F(0x061f7a15) /* 0.382684788 */, 15 }, - /* 1186 */ { MAD_F(0x06213da7) /* 0.383115436 */, 15 }, - /* 1187 */ { MAD_F(0x06230158) /* 0.383546205 */, 15 }, - /* 1188 */ { MAD_F(0x0624c52a) /* 0.383977096 */, 15 }, - /* 1189 */ { MAD_F(0x0626891d) /* 0.384408107 */, 15 }, - /* 1190 */ { MAD_F(0x06284d30) /* 0.384839239 */, 15 }, - /* 1191 */ { MAD_F(0x062a1164) /* 0.385270492 */, 15 }, - /* 1192 */ { MAD_F(0x062bd5b8) /* 0.385701865 */, 15 }, - /* 1193 */ { MAD_F(0x062d9a2c) /* 0.386133359 */, 15 }, - /* 1194 */ { MAD_F(0x062f5ec1) /* 0.386564974 */, 15 }, - /* 1195 */ { MAD_F(0x06312376) /* 0.386996709 */, 15 }, - /* 1196 */ { MAD_F(0x0632e84b) /* 0.387428565 */, 15 }, - /* 1197 */ { MAD_F(0x0634ad41) /* 0.387860541 */, 15 }, - /* 1198 */ { MAD_F(0x06367257) /* 0.388292637 */, 15 }, - /* 1199 */ { MAD_F(0x0638378d) /* 0.388724854 */, 15 }, - - /* 1200 */ { MAD_F(0x0639fce4) /* 0.389157191 */, 15 }, - /* 1201 */ { MAD_F(0x063bc25b) /* 0.389589648 */, 15 }, - /* 1202 */ { MAD_F(0x063d87f2) /* 0.390022225 */, 15 }, - /* 1203 */ { MAD_F(0x063f4da9) /* 0.390454922 */, 15 }, - /* 1204 */ { MAD_F(0x06411380) /* 0.390887739 */, 15 }, - /* 1205 */ { MAD_F(0x0642d978) /* 0.391320675 */, 15 }, - /* 1206 */ { MAD_F(0x06449f8f) /* 0.391753732 */, 15 }, - /* 1207 */ { MAD_F(0x064665c7) /* 0.392186908 */, 15 }, - /* 1208 */ { MAD_F(0x06482c1f) /* 0.392620204 */, 15 }, - /* 1209 */ { MAD_F(0x0649f297) /* 0.393053619 */, 15 }, - /* 1210 */ { MAD_F(0x064bb92f) /* 0.393487154 */, 15 }, - /* 1211 */ { MAD_F(0x064d7fe8) /* 0.393920808 */, 15 }, - /* 1212 */ { MAD_F(0x064f46c0) /* 0.394354582 */, 15 }, - /* 1213 */ { MAD_F(0x06510db8) /* 0.394788475 */, 15 }, - /* 1214 */ { MAD_F(0x0652d4d0) /* 0.395222488 */, 15 }, - /* 1215 */ { MAD_F(0x06549c09) /* 0.395656619 */, 15 }, - - /* 1216 */ { MAD_F(0x06566361) /* 0.396090870 */, 15 }, - /* 1217 */ { MAD_F(0x06582ad9) /* 0.396525239 */, 15 }, - /* 1218 */ { MAD_F(0x0659f271) /* 0.396959728 */, 15 }, - /* 1219 */ { MAD_F(0x065bba29) /* 0.397394336 */, 15 }, - /* 1220 */ { MAD_F(0x065d8201) /* 0.397829062 */, 15 }, - /* 1221 */ { MAD_F(0x065f49f9) /* 0.398263907 */, 15 }, - /* 1222 */ { MAD_F(0x06611211) /* 0.398698871 */, 15 }, - /* 1223 */ { MAD_F(0x0662da49) /* 0.399133954 */, 15 }, - /* 1224 */ { MAD_F(0x0664a2a0) /* 0.399569155 */, 15 }, - /* 1225 */ { MAD_F(0x06666b17) /* 0.400004475 */, 15 }, - /* 1226 */ { MAD_F(0x066833ae) /* 0.400439913 */, 15 }, - /* 1227 */ { MAD_F(0x0669fc65) /* 0.400875470 */, 15 }, - /* 1228 */ { MAD_F(0x066bc53c) /* 0.401311145 */, 15 }, - /* 1229 */ { MAD_F(0x066d8e32) /* 0.401746938 */, 15 }, - /* 1230 */ { MAD_F(0x066f5748) /* 0.402182850 */, 15 }, - /* 1231 */ { MAD_F(0x0671207e) /* 0.402618879 */, 15 }, - - /* 1232 */ { MAD_F(0x0672e9d4) /* 0.403055027 */, 15 }, - /* 1233 */ { MAD_F(0x0674b349) /* 0.403491293 */, 15 }, - /* 1234 */ { MAD_F(0x06767cde) /* 0.403927676 */, 15 }, - /* 1235 */ { MAD_F(0x06784692) /* 0.404364178 */, 15 }, - /* 1236 */ { MAD_F(0x067a1066) /* 0.404800797 */, 15 }, - /* 1237 */ { MAD_F(0x067bda5a) /* 0.405237535 */, 15 }, - /* 1238 */ { MAD_F(0x067da46d) /* 0.405674390 */, 15 }, - /* 1239 */ { MAD_F(0x067f6ea0) /* 0.406111362 */, 15 }, - /* 1240 */ { MAD_F(0x068138f3) /* 0.406548452 */, 15 }, - /* 1241 */ { MAD_F(0x06830365) /* 0.406985660 */, 15 }, - /* 1242 */ { MAD_F(0x0684cdf6) /* 0.407422985 */, 15 }, - /* 1243 */ { MAD_F(0x068698a8) /* 0.407860427 */, 15 }, - /* 1244 */ { MAD_F(0x06886378) /* 0.408297987 */, 15 }, - /* 1245 */ { MAD_F(0x068a2e68) /* 0.408735664 */, 15 }, - /* 1246 */ { MAD_F(0x068bf978) /* 0.409173458 */, 15 }, - /* 1247 */ { MAD_F(0x068dc4a7) /* 0.409611370 */, 15 }, - - /* 1248 */ { MAD_F(0x068f8ff5) /* 0.410049398 */, 15 }, - /* 1249 */ { MAD_F(0x06915b63) /* 0.410487544 */, 15 }, - /* 1250 */ { MAD_F(0x069326f0) /* 0.410925806 */, 15 }, - /* 1251 */ { MAD_F(0x0694f29c) /* 0.411364185 */, 15 }, - /* 1252 */ { MAD_F(0x0696be68) /* 0.411802681 */, 15 }, - /* 1253 */ { MAD_F(0x06988a54) /* 0.412241294 */, 15 }, - /* 1254 */ { MAD_F(0x069a565e) /* 0.412680024 */, 15 }, - /* 1255 */ { MAD_F(0x069c2288) /* 0.413118870 */, 15 }, - /* 1256 */ { MAD_F(0x069deed1) /* 0.413557833 */, 15 }, - /* 1257 */ { MAD_F(0x069fbb3a) /* 0.413996912 */, 15 }, - /* 1258 */ { MAD_F(0x06a187c1) /* 0.414436108 */, 15 }, - /* 1259 */ { MAD_F(0x06a35468) /* 0.414875420 */, 15 }, - /* 1260 */ { MAD_F(0x06a5212f) /* 0.415314849 */, 15 }, - /* 1261 */ { MAD_F(0x06a6ee14) /* 0.415754393 */, 15 }, - /* 1262 */ { MAD_F(0x06a8bb18) /* 0.416194054 */, 15 }, - /* 1263 */ { MAD_F(0x06aa883c) /* 0.416633831 */, 15 }, - - /* 1264 */ { MAD_F(0x06ac557f) /* 0.417073724 */, 15 }, - /* 1265 */ { MAD_F(0x06ae22e1) /* 0.417513734 */, 15 }, - /* 1266 */ { MAD_F(0x06aff062) /* 0.417953859 */, 15 }, - /* 1267 */ { MAD_F(0x06b1be03) /* 0.418394100 */, 15 }, - /* 1268 */ { MAD_F(0x06b38bc2) /* 0.418834457 */, 15 }, - /* 1269 */ { MAD_F(0x06b559a1) /* 0.419274929 */, 15 }, - /* 1270 */ { MAD_F(0x06b7279e) /* 0.419715518 */, 15 }, - /* 1271 */ { MAD_F(0x06b8f5bb) /* 0.420156222 */, 15 }, - /* 1272 */ { MAD_F(0x06bac3f6) /* 0.420597041 */, 15 }, - /* 1273 */ { MAD_F(0x06bc9251) /* 0.421037977 */, 15 }, - /* 1274 */ { MAD_F(0x06be60cb) /* 0.421479027 */, 15 }, - /* 1275 */ { MAD_F(0x06c02f63) /* 0.421920193 */, 15 }, - /* 1276 */ { MAD_F(0x06c1fe1b) /* 0.422361475 */, 15 }, - /* 1277 */ { MAD_F(0x06c3ccf1) /* 0.422802871 */, 15 }, - /* 1278 */ { MAD_F(0x06c59be7) /* 0.423244383 */, 15 }, - /* 1279 */ { MAD_F(0x06c76afb) /* 0.423686010 */, 15 }, - - /* 1280 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 15 }, - /* 1281 */ { MAD_F(0x06cb0981) /* 0.424569610 */, 15 }, - /* 1282 */ { MAD_F(0x06ccd8f2) /* 0.425011582 */, 15 }, - /* 1283 */ { MAD_F(0x06cea881) /* 0.425453669 */, 15 }, - /* 1284 */ { MAD_F(0x06d07830) /* 0.425895871 */, 15 }, - /* 1285 */ { MAD_F(0x06d247fe) /* 0.426338188 */, 15 }, - /* 1286 */ { MAD_F(0x06d417ea) /* 0.426780620 */, 15 }, - /* 1287 */ { MAD_F(0x06d5e7f5) /* 0.427223166 */, 15 }, - /* 1288 */ { MAD_F(0x06d7b81f) /* 0.427665827 */, 15 }, - /* 1289 */ { MAD_F(0x06d98868) /* 0.428108603 */, 15 }, - /* 1290 */ { MAD_F(0x06db58cf) /* 0.428551493 */, 15 }, - /* 1291 */ { MAD_F(0x06dd2955) /* 0.428994497 */, 15 }, - /* 1292 */ { MAD_F(0x06def9fa) /* 0.429437616 */, 15 }, - /* 1293 */ { MAD_F(0x06e0cabe) /* 0.429880849 */, 15 }, - /* 1294 */ { MAD_F(0x06e29ba0) /* 0.430324197 */, 15 }, - /* 1295 */ { MAD_F(0x06e46ca1) /* 0.430767659 */, 15 }, - - /* 1296 */ { MAD_F(0x06e63dc0) /* 0.431211234 */, 15 }, - /* 1297 */ { MAD_F(0x06e80efe) /* 0.431654924 */, 15 }, - /* 1298 */ { MAD_F(0x06e9e05b) /* 0.432098728 */, 15 }, - /* 1299 */ { MAD_F(0x06ebb1d6) /* 0.432542647 */, 15 }, - /* 1300 */ { MAD_F(0x06ed8370) /* 0.432986678 */, 15 }, - /* 1301 */ { MAD_F(0x06ef5529) /* 0.433430824 */, 15 }, - /* 1302 */ { MAD_F(0x06f12700) /* 0.433875084 */, 15 }, - /* 1303 */ { MAD_F(0x06f2f8f5) /* 0.434319457 */, 15 }, - /* 1304 */ { MAD_F(0x06f4cb09) /* 0.434763944 */, 15 }, - /* 1305 */ { MAD_F(0x06f69d3c) /* 0.435208545 */, 15 }, - /* 1306 */ { MAD_F(0x06f86f8d) /* 0.435653259 */, 15 }, - /* 1307 */ { MAD_F(0x06fa41fd) /* 0.436098087 */, 15 }, - /* 1308 */ { MAD_F(0x06fc148b) /* 0.436543029 */, 15 }, - /* 1309 */ { MAD_F(0x06fde737) /* 0.436988083 */, 15 }, - /* 1310 */ { MAD_F(0x06ffba02) /* 0.437433251 */, 15 }, - /* 1311 */ { MAD_F(0x07018ceb) /* 0.437878533 */, 15 }, - - /* 1312 */ { MAD_F(0x07035ff3) /* 0.438323927 */, 15 }, - /* 1313 */ { MAD_F(0x07053319) /* 0.438769435 */, 15 }, - /* 1314 */ { MAD_F(0x0707065d) /* 0.439215056 */, 15 }, - /* 1315 */ { MAD_F(0x0708d9c0) /* 0.439660790 */, 15 }, - /* 1316 */ { MAD_F(0x070aad41) /* 0.440106636 */, 15 }, - /* 1317 */ { MAD_F(0x070c80e1) /* 0.440552596 */, 15 }, - /* 1318 */ { MAD_F(0x070e549f) /* 0.440998669 */, 15 }, - /* 1319 */ { MAD_F(0x0710287b) /* 0.441444855 */, 15 }, - /* 1320 */ { MAD_F(0x0711fc75) /* 0.441891153 */, 15 }, - /* 1321 */ { MAD_F(0x0713d08d) /* 0.442337564 */, 15 }, - /* 1322 */ { MAD_F(0x0715a4c4) /* 0.442784088 */, 15 }, - /* 1323 */ { MAD_F(0x07177919) /* 0.443230724 */, 15 }, - /* 1324 */ { MAD_F(0x07194d8c) /* 0.443677473 */, 15 }, - /* 1325 */ { MAD_F(0x071b221e) /* 0.444124334 */, 15 }, - /* 1326 */ { MAD_F(0x071cf6ce) /* 0.444571308 */, 15 }, - /* 1327 */ { MAD_F(0x071ecb9b) /* 0.445018394 */, 15 }, - - /* 1328 */ { MAD_F(0x0720a087) /* 0.445465593 */, 15 }, - /* 1329 */ { MAD_F(0x07227591) /* 0.445912903 */, 15 }, - /* 1330 */ { MAD_F(0x07244ab9) /* 0.446360326 */, 15 }, - /* 1331 */ { MAD_F(0x07262000) /* 0.446807861 */, 15 }, - /* 1332 */ { MAD_F(0x0727f564) /* 0.447255509 */, 15 }, - /* 1333 */ { MAD_F(0x0729cae7) /* 0.447703268 */, 15 }, - /* 1334 */ { MAD_F(0x072ba087) /* 0.448151139 */, 15 }, - /* 1335 */ { MAD_F(0x072d7646) /* 0.448599122 */, 15 }, - /* 1336 */ { MAD_F(0x072f4c22) /* 0.449047217 */, 15 }, - /* 1337 */ { MAD_F(0x0731221d) /* 0.449495424 */, 15 }, - /* 1338 */ { MAD_F(0x0732f835) /* 0.449943742 */, 15 }, - /* 1339 */ { MAD_F(0x0734ce6c) /* 0.450392173 */, 15 }, - /* 1340 */ { MAD_F(0x0736a4c1) /* 0.450840715 */, 15 }, - /* 1341 */ { MAD_F(0x07387b33) /* 0.451289368 */, 15 }, - /* 1342 */ { MAD_F(0x073a51c4) /* 0.451738133 */, 15 }, - /* 1343 */ { MAD_F(0x073c2872) /* 0.452187010 */, 15 }, - - /* 1344 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 15 }, - /* 1345 */ { MAD_F(0x073fd628) /* 0.453085097 */, 15 }, - /* 1346 */ { MAD_F(0x0741ad30) /* 0.453534308 */, 15 }, - /* 1347 */ { MAD_F(0x07438456) /* 0.453983630 */, 15 }, - /* 1348 */ { MAD_F(0x07455b9a) /* 0.454433063 */, 15 }, - /* 1349 */ { MAD_F(0x074732fc) /* 0.454882607 */, 15 }, - /* 1350 */ { MAD_F(0x07490a7b) /* 0.455332262 */, 15 }, - /* 1351 */ { MAD_F(0x074ae218) /* 0.455782029 */, 15 }, - /* 1352 */ { MAD_F(0x074cb9d3) /* 0.456231906 */, 15 }, - /* 1353 */ { MAD_F(0x074e91ac) /* 0.456681894 */, 15 }, - /* 1354 */ { MAD_F(0x075069a3) /* 0.457131993 */, 15 }, - /* 1355 */ { MAD_F(0x075241b7) /* 0.457582203 */, 15 }, - /* 1356 */ { MAD_F(0x075419e9) /* 0.458032524 */, 15 }, - /* 1357 */ { MAD_F(0x0755f239) /* 0.458482956 */, 15 }, - /* 1358 */ { MAD_F(0x0757caa7) /* 0.458933498 */, 15 }, - /* 1359 */ { MAD_F(0x0759a332) /* 0.459384151 */, 15 }, - - /* 1360 */ { MAD_F(0x075b7bdb) /* 0.459834914 */, 15 }, - /* 1361 */ { MAD_F(0x075d54a1) /* 0.460285788 */, 15 }, - /* 1362 */ { MAD_F(0x075f2d85) /* 0.460736772 */, 15 }, - /* 1363 */ { MAD_F(0x07610687) /* 0.461187867 */, 15 }, - /* 1364 */ { MAD_F(0x0762dfa6) /* 0.461639071 */, 15 }, - /* 1365 */ { MAD_F(0x0764b8e3) /* 0.462090387 */, 15 }, - /* 1366 */ { MAD_F(0x0766923e) /* 0.462541812 */, 15 }, - /* 1367 */ { MAD_F(0x07686bb6) /* 0.462993348 */, 15 }, - /* 1368 */ { MAD_F(0x076a454c) /* 0.463444993 */, 15 }, - /* 1369 */ { MAD_F(0x076c1eff) /* 0.463896749 */, 15 }, - /* 1370 */ { MAD_F(0x076df8d0) /* 0.464348615 */, 15 }, - /* 1371 */ { MAD_F(0x076fd2be) /* 0.464800591 */, 15 }, - /* 1372 */ { MAD_F(0x0771acca) /* 0.465252676 */, 15 }, - /* 1373 */ { MAD_F(0x077386f3) /* 0.465704872 */, 15 }, - /* 1374 */ { MAD_F(0x0775613a) /* 0.466157177 */, 15 }, - /* 1375 */ { MAD_F(0x07773b9e) /* 0.466609592 */, 15 }, - - /* 1376 */ { MAD_F(0x07791620) /* 0.467062117 */, 15 }, - /* 1377 */ { MAD_F(0x077af0bf) /* 0.467514751 */, 15 }, - /* 1378 */ { MAD_F(0x077ccb7c) /* 0.467967495 */, 15 }, - /* 1379 */ { MAD_F(0x077ea656) /* 0.468420349 */, 15 }, - /* 1380 */ { MAD_F(0x0780814d) /* 0.468873312 */, 15 }, - /* 1381 */ { MAD_F(0x07825c62) /* 0.469326384 */, 15 }, - /* 1382 */ { MAD_F(0x07843794) /* 0.469779566 */, 15 }, - /* 1383 */ { MAD_F(0x078612e3) /* 0.470232857 */, 15 }, - /* 1384 */ { MAD_F(0x0787ee50) /* 0.470686258 */, 15 }, - /* 1385 */ { MAD_F(0x0789c9da) /* 0.471139767 */, 15 }, - /* 1386 */ { MAD_F(0x078ba581) /* 0.471593386 */, 15 }, - /* 1387 */ { MAD_F(0x078d8146) /* 0.472047114 */, 15 }, - /* 1388 */ { MAD_F(0x078f5d28) /* 0.472500951 */, 15 }, - /* 1389 */ { MAD_F(0x07913927) /* 0.472954896 */, 15 }, - /* 1390 */ { MAD_F(0x07931543) /* 0.473408951 */, 15 }, - /* 1391 */ { MAD_F(0x0794f17d) /* 0.473863115 */, 15 }, - - /* 1392 */ { MAD_F(0x0796cdd4) /* 0.474317388 */, 15 }, - /* 1393 */ { MAD_F(0x0798aa48) /* 0.474771769 */, 15 }, - /* 1394 */ { MAD_F(0x079a86d9) /* 0.475226259 */, 15 }, - /* 1395 */ { MAD_F(0x079c6388) /* 0.475680858 */, 15 }, - /* 1396 */ { MAD_F(0x079e4053) /* 0.476135565 */, 15 }, - /* 1397 */ { MAD_F(0x07a01d3c) /* 0.476590381 */, 15 }, - /* 1398 */ { MAD_F(0x07a1fa42) /* 0.477045306 */, 15 }, - /* 1399 */ { MAD_F(0x07a3d765) /* 0.477500339 */, 15 }, - /* 1400 */ { MAD_F(0x07a5b4a5) /* 0.477955481 */, 15 }, - /* 1401 */ { MAD_F(0x07a79202) /* 0.478410731 */, 15 }, - /* 1402 */ { MAD_F(0x07a96f7d) /* 0.478866089 */, 15 }, - /* 1403 */ { MAD_F(0x07ab4d14) /* 0.479321555 */, 15 }, - /* 1404 */ { MAD_F(0x07ad2ac8) /* 0.479777130 */, 15 }, - /* 1405 */ { MAD_F(0x07af089a) /* 0.480232813 */, 15 }, - /* 1406 */ { MAD_F(0x07b0e688) /* 0.480688604 */, 15 }, - /* 1407 */ { MAD_F(0x07b2c494) /* 0.481144503 */, 15 }, - - /* 1408 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 15 }, - /* 1409 */ { MAD_F(0x07b68102) /* 0.482056625 */, 15 }, - /* 1410 */ { MAD_F(0x07b85f64) /* 0.482512848 */, 15 }, - /* 1411 */ { MAD_F(0x07ba3de4) /* 0.482969179 */, 15 }, - /* 1412 */ { MAD_F(0x07bc1c80) /* 0.483425618 */, 15 }, - /* 1413 */ { MAD_F(0x07bdfb39) /* 0.483882164 */, 15 }, - /* 1414 */ { MAD_F(0x07bfda0f) /* 0.484338818 */, 15 }, - /* 1415 */ { MAD_F(0x07c1b902) /* 0.484795580 */, 15 }, - /* 1416 */ { MAD_F(0x07c39812) /* 0.485252449 */, 15 }, - /* 1417 */ { MAD_F(0x07c5773f) /* 0.485709426 */, 15 }, - /* 1418 */ { MAD_F(0x07c75689) /* 0.486166511 */, 15 }, - /* 1419 */ { MAD_F(0x07c935ef) /* 0.486623703 */, 15 }, - /* 1420 */ { MAD_F(0x07cb1573) /* 0.487081002 */, 15 }, - /* 1421 */ { MAD_F(0x07ccf513) /* 0.487538409 */, 15 }, - /* 1422 */ { MAD_F(0x07ced4d0) /* 0.487995923 */, 15 }, - /* 1423 */ { MAD_F(0x07d0b4aa) /* 0.488453544 */, 15 }, - - /* 1424 */ { MAD_F(0x07d294a0) /* 0.488911273 */, 15 }, - /* 1425 */ { MAD_F(0x07d474b3) /* 0.489369108 */, 15 }, - /* 1426 */ { MAD_F(0x07d654e4) /* 0.489827051 */, 15 }, - /* 1427 */ { MAD_F(0x07d83530) /* 0.490285101 */, 15 }, - /* 1428 */ { MAD_F(0x07da159a) /* 0.490743258 */, 15 }, - /* 1429 */ { MAD_F(0x07dbf620) /* 0.491201522 */, 15 }, - /* 1430 */ { MAD_F(0x07ddd6c3) /* 0.491659892 */, 15 }, - /* 1431 */ { MAD_F(0x07dfb783) /* 0.492118370 */, 15 }, - /* 1432 */ { MAD_F(0x07e1985f) /* 0.492576954 */, 15 }, - /* 1433 */ { MAD_F(0x07e37958) /* 0.493035645 */, 15 }, - /* 1434 */ { MAD_F(0x07e55a6e) /* 0.493494443 */, 15 }, - /* 1435 */ { MAD_F(0x07e73ba0) /* 0.493953348 */, 15 }, - /* 1436 */ { MAD_F(0x07e91cef) /* 0.494412359 */, 15 }, - /* 1437 */ { MAD_F(0x07eafe5a) /* 0.494871476 */, 15 }, - /* 1438 */ { MAD_F(0x07ecdfe2) /* 0.495330701 */, 15 }, - /* 1439 */ { MAD_F(0x07eec187) /* 0.495790031 */, 15 }, - - /* 1440 */ { MAD_F(0x07f0a348) /* 0.496249468 */, 15 }, - /* 1441 */ { MAD_F(0x07f28526) /* 0.496709012 */, 15 }, - /* 1442 */ { MAD_F(0x07f46720) /* 0.497168662 */, 15 }, - /* 1443 */ { MAD_F(0x07f64937) /* 0.497628418 */, 15 }, - /* 1444 */ { MAD_F(0x07f82b6a) /* 0.498088280 */, 15 }, - /* 1445 */ { MAD_F(0x07fa0dba) /* 0.498548248 */, 15 }, - /* 1446 */ { MAD_F(0x07fbf026) /* 0.499008323 */, 15 }, - /* 1447 */ { MAD_F(0x07fdd2af) /* 0.499468503 */, 15 }, - /* 1448 */ { MAD_F(0x07ffb554) /* 0.499928790 */, 15 }, - /* 1449 */ { MAD_F(0x0400cc0b) /* 0.250194591 */, 16 }, - /* 1450 */ { MAD_F(0x0401bd7a) /* 0.250424840 */, 16 }, - /* 1451 */ { MAD_F(0x0402aef7) /* 0.250655143 */, 16 }, - /* 1452 */ { MAD_F(0x0403a083) /* 0.250885498 */, 16 }, - /* 1453 */ { MAD_F(0x0404921c) /* 0.251115906 */, 16 }, - /* 1454 */ { MAD_F(0x040583c4) /* 0.251346367 */, 16 }, - /* 1455 */ { MAD_F(0x0406757a) /* 0.251576880 */, 16 }, - - /* 1456 */ { MAD_F(0x0407673f) /* 0.251807447 */, 16 }, - /* 1457 */ { MAD_F(0x04085911) /* 0.252038066 */, 16 }, - /* 1458 */ { MAD_F(0x04094af1) /* 0.252268738 */, 16 }, - /* 1459 */ { MAD_F(0x040a3ce0) /* 0.252499463 */, 16 }, - /* 1460 */ { MAD_F(0x040b2edd) /* 0.252730240 */, 16 }, - /* 1461 */ { MAD_F(0x040c20e8) /* 0.252961071 */, 16 }, - /* 1462 */ { MAD_F(0x040d1301) /* 0.253191953 */, 16 }, - /* 1463 */ { MAD_F(0x040e0529) /* 0.253422889 */, 16 }, - /* 1464 */ { MAD_F(0x040ef75e) /* 0.253653877 */, 16 }, - /* 1465 */ { MAD_F(0x040fe9a1) /* 0.253884918 */, 16 }, - /* 1466 */ { MAD_F(0x0410dbf3) /* 0.254116011 */, 16 }, - /* 1467 */ { MAD_F(0x0411ce53) /* 0.254347157 */, 16 }, - /* 1468 */ { MAD_F(0x0412c0c1) /* 0.254578356 */, 16 }, - /* 1469 */ { MAD_F(0x0413b33d) /* 0.254809606 */, 16 }, - /* 1470 */ { MAD_F(0x0414a5c7) /* 0.255040910 */, 16 }, - /* 1471 */ { MAD_F(0x0415985f) /* 0.255272266 */, 16 }, - - /* 1472 */ { MAD_F(0x04168b05) /* 0.255503674 */, 16 }, - /* 1473 */ { MAD_F(0x04177db9) /* 0.255735135 */, 16 }, - /* 1474 */ { MAD_F(0x0418707c) /* 0.255966648 */, 16 }, - /* 1475 */ { MAD_F(0x0419634c) /* 0.256198213 */, 16 }, - /* 1476 */ { MAD_F(0x041a562a) /* 0.256429831 */, 16 }, - /* 1477 */ { MAD_F(0x041b4917) /* 0.256661501 */, 16 }, - /* 1478 */ { MAD_F(0x041c3c11) /* 0.256893223 */, 16 }, - /* 1479 */ { MAD_F(0x041d2f1a) /* 0.257124998 */, 16 }, - /* 1480 */ { MAD_F(0x041e2230) /* 0.257356825 */, 16 }, - /* 1481 */ { MAD_F(0x041f1555) /* 0.257588704 */, 16 }, - /* 1482 */ { MAD_F(0x04200888) /* 0.257820635 */, 16 }, - /* 1483 */ { MAD_F(0x0420fbc8) /* 0.258052619 */, 16 }, - /* 1484 */ { MAD_F(0x0421ef17) /* 0.258284654 */, 16 }, - /* 1485 */ { MAD_F(0x0422e273) /* 0.258516742 */, 16 }, - /* 1486 */ { MAD_F(0x0423d5de) /* 0.258748882 */, 16 }, - /* 1487 */ { MAD_F(0x0424c956) /* 0.258981074 */, 16 }, - - /* 1488 */ { MAD_F(0x0425bcdd) /* 0.259213318 */, 16 }, - /* 1489 */ { MAD_F(0x0426b071) /* 0.259445614 */, 16 }, - /* 1490 */ { MAD_F(0x0427a414) /* 0.259677962 */, 16 }, - /* 1491 */ { MAD_F(0x042897c4) /* 0.259910362 */, 16 }, - /* 1492 */ { MAD_F(0x04298b83) /* 0.260142814 */, 16 }, - /* 1493 */ { MAD_F(0x042a7f4f) /* 0.260375318 */, 16 }, - /* 1494 */ { MAD_F(0x042b7329) /* 0.260607874 */, 16 }, - /* 1495 */ { MAD_F(0x042c6711) /* 0.260840481 */, 16 }, - /* 1496 */ { MAD_F(0x042d5b07) /* 0.261073141 */, 16 }, - /* 1497 */ { MAD_F(0x042e4f0b) /* 0.261305852 */, 16 }, - /* 1498 */ { MAD_F(0x042f431d) /* 0.261538616 */, 16 }, - /* 1499 */ { MAD_F(0x0430373d) /* 0.261771431 */, 16 }, - /* 1500 */ { MAD_F(0x04312b6b) /* 0.262004297 */, 16 }, - /* 1501 */ { MAD_F(0x04321fa6) /* 0.262237216 */, 16 }, - /* 1502 */ { MAD_F(0x043313f0) /* 0.262470186 */, 16 }, - /* 1503 */ { MAD_F(0x04340847) /* 0.262703208 */, 16 }, - - /* 1504 */ { MAD_F(0x0434fcad) /* 0.262936282 */, 16 }, - /* 1505 */ { MAD_F(0x0435f120) /* 0.263169407 */, 16 }, - /* 1506 */ { MAD_F(0x0436e5a1) /* 0.263402584 */, 16 }, - /* 1507 */ { MAD_F(0x0437da2f) /* 0.263635813 */, 16 }, - /* 1508 */ { MAD_F(0x0438cecc) /* 0.263869093 */, 16 }, - /* 1509 */ { MAD_F(0x0439c377) /* 0.264102425 */, 16 }, - /* 1510 */ { MAD_F(0x043ab82f) /* 0.264335808 */, 16 }, - /* 1511 */ { MAD_F(0x043bacf5) /* 0.264569243 */, 16 }, - /* 1512 */ { MAD_F(0x043ca1c9) /* 0.264802730 */, 16 }, - /* 1513 */ { MAD_F(0x043d96ab) /* 0.265036267 */, 16 }, - /* 1514 */ { MAD_F(0x043e8b9b) /* 0.265269857 */, 16 }, - /* 1515 */ { MAD_F(0x043f8098) /* 0.265503498 */, 16 }, - /* 1516 */ { MAD_F(0x044075a3) /* 0.265737190 */, 16 }, - /* 1517 */ { MAD_F(0x04416abc) /* 0.265970933 */, 16 }, - /* 1518 */ { MAD_F(0x04425fe3) /* 0.266204728 */, 16 }, - /* 1519 */ { MAD_F(0x04435518) /* 0.266438574 */, 16 }, - - /* 1520 */ { MAD_F(0x04444a5a) /* 0.266672472 */, 16 }, - /* 1521 */ { MAD_F(0x04453fab) /* 0.266906421 */, 16 }, - /* 1522 */ { MAD_F(0x04463508) /* 0.267140421 */, 16 }, - /* 1523 */ { MAD_F(0x04472a74) /* 0.267374472 */, 16 }, - /* 1524 */ { MAD_F(0x04481fee) /* 0.267608575 */, 16 }, - /* 1525 */ { MAD_F(0x04491575) /* 0.267842729 */, 16 }, - /* 1526 */ { MAD_F(0x044a0b0a) /* 0.268076934 */, 16 }, - /* 1527 */ { MAD_F(0x044b00ac) /* 0.268311190 */, 16 }, - /* 1528 */ { MAD_F(0x044bf65d) /* 0.268545497 */, 16 }, - /* 1529 */ { MAD_F(0x044cec1b) /* 0.268779856 */, 16 }, - /* 1530 */ { MAD_F(0x044de1e7) /* 0.269014265 */, 16 }, - /* 1531 */ { MAD_F(0x044ed7c0) /* 0.269248726 */, 16 }, - /* 1532 */ { MAD_F(0x044fcda8) /* 0.269483238 */, 16 }, - /* 1533 */ { MAD_F(0x0450c39c) /* 0.269717800 */, 16 }, - /* 1534 */ { MAD_F(0x0451b99f) /* 0.269952414 */, 16 }, - /* 1535 */ { MAD_F(0x0452afaf) /* 0.270187079 */, 16 }, - - /* 1536 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 16 }, - /* 1537 */ { MAD_F(0x04549bf9) /* 0.270656561 */, 16 }, - /* 1538 */ { MAD_F(0x04559232) /* 0.270891379 */, 16 }, - /* 1539 */ { MAD_F(0x04568879) /* 0.271126247 */, 16 }, - /* 1540 */ { MAD_F(0x04577ece) /* 0.271361166 */, 16 }, - /* 1541 */ { MAD_F(0x04587530) /* 0.271596136 */, 16 }, - /* 1542 */ { MAD_F(0x04596ba0) /* 0.271831157 */, 16 }, - /* 1543 */ { MAD_F(0x045a621e) /* 0.272066229 */, 16 }, - /* 1544 */ { MAD_F(0x045b58a9) /* 0.272301352 */, 16 }, - /* 1545 */ { MAD_F(0x045c4f42) /* 0.272536525 */, 16 }, - /* 1546 */ { MAD_F(0x045d45e9) /* 0.272771749 */, 16 }, - /* 1547 */ { MAD_F(0x045e3c9d) /* 0.273007024 */, 16 }, - /* 1548 */ { MAD_F(0x045f335e) /* 0.273242350 */, 16 }, - /* 1549 */ { MAD_F(0x04602a2e) /* 0.273477726 */, 16 }, - /* 1550 */ { MAD_F(0x0461210b) /* 0.273713153 */, 16 }, - /* 1551 */ { MAD_F(0x046217f5) /* 0.273948630 */, 16 }, - - /* 1552 */ { MAD_F(0x04630eed) /* 0.274184158 */, 16 }, - /* 1553 */ { MAD_F(0x046405f3) /* 0.274419737 */, 16 }, - /* 1554 */ { MAD_F(0x0464fd06) /* 0.274655366 */, 16 }, - /* 1555 */ { MAD_F(0x0465f427) /* 0.274891046 */, 16 }, - /* 1556 */ { MAD_F(0x0466eb55) /* 0.275126776 */, 16 }, - /* 1557 */ { MAD_F(0x0467e291) /* 0.275362557 */, 16 }, - /* 1558 */ { MAD_F(0x0468d9db) /* 0.275598389 */, 16 }, - /* 1559 */ { MAD_F(0x0469d132) /* 0.275834270 */, 16 }, - /* 1560 */ { MAD_F(0x046ac896) /* 0.276070203 */, 16 }, - /* 1561 */ { MAD_F(0x046bc009) /* 0.276306185 */, 16 }, - /* 1562 */ { MAD_F(0x046cb788) /* 0.276542218 */, 16 }, - /* 1563 */ { MAD_F(0x046daf15) /* 0.276778302 */, 16 }, - /* 1564 */ { MAD_F(0x046ea6b0) /* 0.277014435 */, 16 }, - /* 1565 */ { MAD_F(0x046f9e58) /* 0.277250619 */, 16 }, - /* 1566 */ { MAD_F(0x0470960e) /* 0.277486854 */, 16 }, - /* 1567 */ { MAD_F(0x04718dd1) /* 0.277723139 */, 16 }, - - /* 1568 */ { MAD_F(0x047285a2) /* 0.277959474 */, 16 }, - /* 1569 */ { MAD_F(0x04737d80) /* 0.278195859 */, 16 }, - /* 1570 */ { MAD_F(0x0474756c) /* 0.278432294 */, 16 }, - /* 1571 */ { MAD_F(0x04756d65) /* 0.278668780 */, 16 }, - /* 1572 */ { MAD_F(0x0476656b) /* 0.278905316 */, 16 }, - /* 1573 */ { MAD_F(0x04775d7f) /* 0.279141902 */, 16 }, - /* 1574 */ { MAD_F(0x047855a1) /* 0.279378538 */, 16 }, - /* 1575 */ { MAD_F(0x04794dd0) /* 0.279615224 */, 16 }, - /* 1576 */ { MAD_F(0x047a460c) /* 0.279851960 */, 16 }, - /* 1577 */ { MAD_F(0x047b3e56) /* 0.280088747 */, 16 }, - /* 1578 */ { MAD_F(0x047c36ae) /* 0.280325583 */, 16 }, - /* 1579 */ { MAD_F(0x047d2f12) /* 0.280562470 */, 16 }, - /* 1580 */ { MAD_F(0x047e2784) /* 0.280799406 */, 16 }, - /* 1581 */ { MAD_F(0x047f2004) /* 0.281036393 */, 16 }, - /* 1582 */ { MAD_F(0x04801891) /* 0.281273429 */, 16 }, - /* 1583 */ { MAD_F(0x0481112b) /* 0.281510516 */, 16 }, - - /* 1584 */ { MAD_F(0x048209d3) /* 0.281747652 */, 16 }, - /* 1585 */ { MAD_F(0x04830288) /* 0.281984838 */, 16 }, - /* 1586 */ { MAD_F(0x0483fb4b) /* 0.282222075 */, 16 }, - /* 1587 */ { MAD_F(0x0484f41b) /* 0.282459361 */, 16 }, - /* 1588 */ { MAD_F(0x0485ecf8) /* 0.282696697 */, 16 }, - /* 1589 */ { MAD_F(0x0486e5e3) /* 0.282934082 */, 16 }, - /* 1590 */ { MAD_F(0x0487dedb) /* 0.283171518 */, 16 }, - /* 1591 */ { MAD_F(0x0488d7e1) /* 0.283409003 */, 16 }, - /* 1592 */ { MAD_F(0x0489d0f4) /* 0.283646538 */, 16 }, - /* 1593 */ { MAD_F(0x048aca14) /* 0.283884123 */, 16 }, - /* 1594 */ { MAD_F(0x048bc341) /* 0.284121757 */, 16 }, - /* 1595 */ { MAD_F(0x048cbc7c) /* 0.284359441 */, 16 }, - /* 1596 */ { MAD_F(0x048db5c4) /* 0.284597175 */, 16 }, - /* 1597 */ { MAD_F(0x048eaf1a) /* 0.284834959 */, 16 }, - /* 1598 */ { MAD_F(0x048fa87d) /* 0.285072792 */, 16 }, - /* 1599 */ { MAD_F(0x0490a1ed) /* 0.285310675 */, 16 }, - - /* 1600 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 16 }, - /* 1601 */ { MAD_F(0x049294f5) /* 0.285786589 */, 16 }, - /* 1602 */ { MAD_F(0x04938e8d) /* 0.286024621 */, 16 }, - /* 1603 */ { MAD_F(0x04948833) /* 0.286262702 */, 16 }, - /* 1604 */ { MAD_F(0x049581e5) /* 0.286500832 */, 16 }, - /* 1605 */ { MAD_F(0x04967ba5) /* 0.286739012 */, 16 }, - /* 1606 */ { MAD_F(0x04977573) /* 0.286977242 */, 16 }, - /* 1607 */ { MAD_F(0x04986f4d) /* 0.287215521 */, 16 }, - /* 1608 */ { MAD_F(0x04996935) /* 0.287453849 */, 16 }, - /* 1609 */ { MAD_F(0x049a632a) /* 0.287692227 */, 16 }, - /* 1610 */ { MAD_F(0x049b5d2c) /* 0.287930654 */, 16 }, - /* 1611 */ { MAD_F(0x049c573c) /* 0.288169131 */, 16 }, - /* 1612 */ { MAD_F(0x049d5159) /* 0.288407657 */, 16 }, - /* 1613 */ { MAD_F(0x049e4b83) /* 0.288646232 */, 16 }, - /* 1614 */ { MAD_F(0x049f45ba) /* 0.288884857 */, 16 }, - /* 1615 */ { MAD_F(0x04a03ffe) /* 0.289123530 */, 16 }, - - /* 1616 */ { MAD_F(0x04a13a50) /* 0.289362253 */, 16 }, - /* 1617 */ { MAD_F(0x04a234af) /* 0.289601026 */, 16 }, - /* 1618 */ { MAD_F(0x04a32f1b) /* 0.289839847 */, 16 }, - /* 1619 */ { MAD_F(0x04a42995) /* 0.290078718 */, 16 }, - /* 1620 */ { MAD_F(0x04a5241b) /* 0.290317638 */, 16 }, - /* 1621 */ { MAD_F(0x04a61eaf) /* 0.290556607 */, 16 }, - /* 1622 */ { MAD_F(0x04a71950) /* 0.290795626 */, 16 }, - /* 1623 */ { MAD_F(0x04a813fe) /* 0.291034693 */, 16 }, - /* 1624 */ { MAD_F(0x04a90eba) /* 0.291273810 */, 16 }, - /* 1625 */ { MAD_F(0x04aa0982) /* 0.291512975 */, 16 }, - /* 1626 */ { MAD_F(0x04ab0458) /* 0.291752190 */, 16 }, - /* 1627 */ { MAD_F(0x04abff3b) /* 0.291991453 */, 16 }, - /* 1628 */ { MAD_F(0x04acfa2b) /* 0.292230766 */, 16 }, - /* 1629 */ { MAD_F(0x04adf528) /* 0.292470128 */, 16 }, - /* 1630 */ { MAD_F(0x04aef032) /* 0.292709539 */, 16 }, - /* 1631 */ { MAD_F(0x04afeb4a) /* 0.292948998 */, 16 }, - - /* 1632 */ { MAD_F(0x04b0e66e) /* 0.293188507 */, 16 }, - /* 1633 */ { MAD_F(0x04b1e1a0) /* 0.293428065 */, 16 }, - /* 1634 */ { MAD_F(0x04b2dcdf) /* 0.293667671 */, 16 }, - /* 1635 */ { MAD_F(0x04b3d82b) /* 0.293907326 */, 16 }, - /* 1636 */ { MAD_F(0x04b4d384) /* 0.294147031 */, 16 }, - /* 1637 */ { MAD_F(0x04b5ceea) /* 0.294386784 */, 16 }, - /* 1638 */ { MAD_F(0x04b6ca5e) /* 0.294626585 */, 16 }, - /* 1639 */ { MAD_F(0x04b7c5de) /* 0.294866436 */, 16 }, - /* 1640 */ { MAD_F(0x04b8c16c) /* 0.295106336 */, 16 }, - /* 1641 */ { MAD_F(0x04b9bd06) /* 0.295346284 */, 16 }, - /* 1642 */ { MAD_F(0x04bab8ae) /* 0.295586281 */, 16 }, - /* 1643 */ { MAD_F(0x04bbb463) /* 0.295826327 */, 16 }, - /* 1644 */ { MAD_F(0x04bcb024) /* 0.296066421 */, 16 }, - /* 1645 */ { MAD_F(0x04bdabf3) /* 0.296306564 */, 16 }, - /* 1646 */ { MAD_F(0x04bea7cf) /* 0.296546756 */, 16 }, - /* 1647 */ { MAD_F(0x04bfa3b8) /* 0.296786996 */, 16 }, - - /* 1648 */ { MAD_F(0x04c09faf) /* 0.297027285 */, 16 }, - /* 1649 */ { MAD_F(0x04c19bb2) /* 0.297267623 */, 16 }, - /* 1650 */ { MAD_F(0x04c297c2) /* 0.297508009 */, 16 }, - /* 1651 */ { MAD_F(0x04c393df) /* 0.297748444 */, 16 }, - /* 1652 */ { MAD_F(0x04c49009) /* 0.297988927 */, 16 }, - /* 1653 */ { MAD_F(0x04c58c41) /* 0.298229459 */, 16 }, - /* 1654 */ { MAD_F(0x04c68885) /* 0.298470039 */, 16 }, - /* 1655 */ { MAD_F(0x04c784d6) /* 0.298710668 */, 16 }, - /* 1656 */ { MAD_F(0x04c88135) /* 0.298951346 */, 16 }, - /* 1657 */ { MAD_F(0x04c97da0) /* 0.299192071 */, 16 }, - /* 1658 */ { MAD_F(0x04ca7a18) /* 0.299432846 */, 16 }, - /* 1659 */ { MAD_F(0x04cb769e) /* 0.299673668 */, 16 }, - /* 1660 */ { MAD_F(0x04cc7330) /* 0.299914539 */, 16 }, - /* 1661 */ { MAD_F(0x04cd6fcf) /* 0.300155459 */, 16 }, - /* 1662 */ { MAD_F(0x04ce6c7b) /* 0.300396426 */, 16 }, - /* 1663 */ { MAD_F(0x04cf6935) /* 0.300637443 */, 16 }, - - /* 1664 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 16 }, - /* 1665 */ { MAD_F(0x04d162ce) /* 0.301119620 */, 16 }, - /* 1666 */ { MAD_F(0x04d25fae) /* 0.301360781 */, 16 }, - /* 1667 */ { MAD_F(0x04d35c9b) /* 0.301601990 */, 16 }, - /* 1668 */ { MAD_F(0x04d45995) /* 0.301843247 */, 16 }, - /* 1669 */ { MAD_F(0x04d5569c) /* 0.302084553 */, 16 }, - /* 1670 */ { MAD_F(0x04d653b0) /* 0.302325907 */, 16 }, - /* 1671 */ { MAD_F(0x04d750d1) /* 0.302567309 */, 16 }, - /* 1672 */ { MAD_F(0x04d84dff) /* 0.302808759 */, 16 }, - /* 1673 */ { MAD_F(0x04d94b3a) /* 0.303050257 */, 16 }, - /* 1674 */ { MAD_F(0x04da4881) /* 0.303291804 */, 16 }, - /* 1675 */ { MAD_F(0x04db45d6) /* 0.303533399 */, 16 }, - /* 1676 */ { MAD_F(0x04dc4337) /* 0.303775041 */, 16 }, - /* 1677 */ { MAD_F(0x04dd40a6) /* 0.304016732 */, 16 }, - /* 1678 */ { MAD_F(0x04de3e21) /* 0.304258471 */, 16 }, - /* 1679 */ { MAD_F(0x04df3ba9) /* 0.304500257 */, 16 }, - - /* 1680 */ { MAD_F(0x04e0393e) /* 0.304742092 */, 16 }, - /* 1681 */ { MAD_F(0x04e136e0) /* 0.304983975 */, 16 }, - /* 1682 */ { MAD_F(0x04e2348f) /* 0.305225906 */, 16 }, - /* 1683 */ { MAD_F(0x04e3324b) /* 0.305467885 */, 16 }, - /* 1684 */ { MAD_F(0x04e43013) /* 0.305709911 */, 16 }, - /* 1685 */ { MAD_F(0x04e52de9) /* 0.305951986 */, 16 }, - /* 1686 */ { MAD_F(0x04e62bcb) /* 0.306194108 */, 16 }, - /* 1687 */ { MAD_F(0x04e729ba) /* 0.306436279 */, 16 }, - /* 1688 */ { MAD_F(0x04e827b6) /* 0.306678497 */, 16 }, - /* 1689 */ { MAD_F(0x04e925bf) /* 0.306920763 */, 16 }, - /* 1690 */ { MAD_F(0x04ea23d4) /* 0.307163077 */, 16 }, - /* 1691 */ { MAD_F(0x04eb21f7) /* 0.307405438 */, 16 }, - /* 1692 */ { MAD_F(0x04ec2026) /* 0.307647848 */, 16 }, - /* 1693 */ { MAD_F(0x04ed1e62) /* 0.307890305 */, 16 }, - /* 1694 */ { MAD_F(0x04ee1cab) /* 0.308132810 */, 16 }, - /* 1695 */ { MAD_F(0x04ef1b01) /* 0.308375362 */, 16 }, - - /* 1696 */ { MAD_F(0x04f01963) /* 0.308617963 */, 16 }, - /* 1697 */ { MAD_F(0x04f117d3) /* 0.308860611 */, 16 }, - /* 1698 */ { MAD_F(0x04f2164f) /* 0.309103306 */, 16 }, - /* 1699 */ { MAD_F(0x04f314d8) /* 0.309346050 */, 16 }, - /* 1700 */ { MAD_F(0x04f4136d) /* 0.309588841 */, 16 }, - /* 1701 */ { MAD_F(0x04f51210) /* 0.309831679 */, 16 }, - /* 1702 */ { MAD_F(0x04f610bf) /* 0.310074565 */, 16 }, - /* 1703 */ { MAD_F(0x04f70f7b) /* 0.310317499 */, 16 }, - /* 1704 */ { MAD_F(0x04f80e44) /* 0.310560480 */, 16 }, - /* 1705 */ { MAD_F(0x04f90d19) /* 0.310803509 */, 16 }, - /* 1706 */ { MAD_F(0x04fa0bfc) /* 0.311046586 */, 16 }, - /* 1707 */ { MAD_F(0x04fb0aeb) /* 0.311289710 */, 16 }, - /* 1708 */ { MAD_F(0x04fc09e7) /* 0.311532881 */, 16 }, - /* 1709 */ { MAD_F(0x04fd08ef) /* 0.311776100 */, 16 }, - /* 1710 */ { MAD_F(0x04fe0805) /* 0.312019366 */, 16 }, - /* 1711 */ { MAD_F(0x04ff0727) /* 0.312262680 */, 16 }, - - /* 1712 */ { MAD_F(0x05000655) /* 0.312506041 */, 16 }, - /* 1713 */ { MAD_F(0x05010591) /* 0.312749449 */, 16 }, - /* 1714 */ { MAD_F(0x050204d9) /* 0.312992905 */, 16 }, - /* 1715 */ { MAD_F(0x0503042e) /* 0.313236408 */, 16 }, - /* 1716 */ { MAD_F(0x0504038f) /* 0.313479959 */, 16 }, - /* 1717 */ { MAD_F(0x050502fe) /* 0.313723556 */, 16 }, - /* 1718 */ { MAD_F(0x05060279) /* 0.313967202 */, 16 }, - /* 1719 */ { MAD_F(0x05070200) /* 0.314210894 */, 16 }, - /* 1720 */ { MAD_F(0x05080195) /* 0.314454634 */, 16 }, - /* 1721 */ { MAD_F(0x05090136) /* 0.314698420 */, 16 }, - /* 1722 */ { MAD_F(0x050a00e3) /* 0.314942255 */, 16 }, - /* 1723 */ { MAD_F(0x050b009e) /* 0.315186136 */, 16 }, - /* 1724 */ { MAD_F(0x050c0065) /* 0.315430064 */, 16 }, - /* 1725 */ { MAD_F(0x050d0039) /* 0.315674040 */, 16 }, - /* 1726 */ { MAD_F(0x050e0019) /* 0.315918063 */, 16 }, - /* 1727 */ { MAD_F(0x050f0006) /* 0.316162133 */, 16 }, - - /* 1728 */ { MAD_F(0x05100000) /* 0.316406250 */, 16 }, - /* 1729 */ { MAD_F(0x05110006) /* 0.316650414 */, 16 }, - /* 1730 */ { MAD_F(0x05120019) /* 0.316894625 */, 16 }, - /* 1731 */ { MAD_F(0x05130039) /* 0.317138884 */, 16 }, - /* 1732 */ { MAD_F(0x05140065) /* 0.317383189 */, 16 }, - /* 1733 */ { MAD_F(0x0515009e) /* 0.317627541 */, 16 }, - /* 1734 */ { MAD_F(0x051600e3) /* 0.317871941 */, 16 }, - /* 1735 */ { MAD_F(0x05170135) /* 0.318116387 */, 16 }, - /* 1736 */ { MAD_F(0x05180194) /* 0.318360880 */, 16 }, - /* 1737 */ { MAD_F(0x051901ff) /* 0.318605421 */, 16 }, - /* 1738 */ { MAD_F(0x051a0277) /* 0.318850008 */, 16 }, - /* 1739 */ { MAD_F(0x051b02fc) /* 0.319094642 */, 16 }, - /* 1740 */ { MAD_F(0x051c038d) /* 0.319339323 */, 16 }, - /* 1741 */ { MAD_F(0x051d042a) /* 0.319584051 */, 16 }, - /* 1742 */ { MAD_F(0x051e04d4) /* 0.319828826 */, 16 }, - /* 1743 */ { MAD_F(0x051f058b) /* 0.320073647 */, 16 }, - - /* 1744 */ { MAD_F(0x0520064f) /* 0.320318516 */, 16 }, - /* 1745 */ { MAD_F(0x0521071f) /* 0.320563431 */, 16 }, - /* 1746 */ { MAD_F(0x052207fb) /* 0.320808393 */, 16 }, - /* 1747 */ { MAD_F(0x052308e4) /* 0.321053402 */, 16 }, - /* 1748 */ { MAD_F(0x052409da) /* 0.321298457 */, 16 }, - /* 1749 */ { MAD_F(0x05250adc) /* 0.321543560 */, 16 }, - /* 1750 */ { MAD_F(0x05260bea) /* 0.321788709 */, 16 }, - /* 1751 */ { MAD_F(0x05270d06) /* 0.322033904 */, 16 }, - /* 1752 */ { MAD_F(0x05280e2d) /* 0.322279147 */, 16 }, - /* 1753 */ { MAD_F(0x05290f62) /* 0.322524436 */, 16 }, - /* 1754 */ { MAD_F(0x052a10a3) /* 0.322769771 */, 16 }, - /* 1755 */ { MAD_F(0x052b11f0) /* 0.323015154 */, 16 }, - /* 1756 */ { MAD_F(0x052c134a) /* 0.323260583 */, 16 }, - /* 1757 */ { MAD_F(0x052d14b0) /* 0.323506058 */, 16 }, - /* 1758 */ { MAD_F(0x052e1623) /* 0.323751580 */, 16 }, - /* 1759 */ { MAD_F(0x052f17a2) /* 0.323997149 */, 16 }, - - /* 1760 */ { MAD_F(0x0530192e) /* 0.324242764 */, 16 }, - /* 1761 */ { MAD_F(0x05311ac6) /* 0.324488426 */, 16 }, - /* 1762 */ { MAD_F(0x05321c6b) /* 0.324734134 */, 16 }, - /* 1763 */ { MAD_F(0x05331e1c) /* 0.324979889 */, 16 }, - /* 1764 */ { MAD_F(0x05341fda) /* 0.325225690 */, 16 }, - /* 1765 */ { MAD_F(0x053521a4) /* 0.325471538 */, 16 }, - /* 1766 */ { MAD_F(0x0536237b) /* 0.325717432 */, 16 }, - /* 1767 */ { MAD_F(0x0537255e) /* 0.325963372 */, 16 }, - /* 1768 */ { MAD_F(0x0538274e) /* 0.326209359 */, 16 }, - /* 1769 */ { MAD_F(0x0539294a) /* 0.326455392 */, 16 }, - /* 1770 */ { MAD_F(0x053a2b52) /* 0.326701472 */, 16 }, - /* 1771 */ { MAD_F(0x053b2d67) /* 0.326947598 */, 16 }, - /* 1772 */ { MAD_F(0x053c2f89) /* 0.327193770 */, 16 }, - /* 1773 */ { MAD_F(0x053d31b6) /* 0.327439989 */, 16 }, - /* 1774 */ { MAD_F(0x053e33f1) /* 0.327686254 */, 16 }, - /* 1775 */ { MAD_F(0x053f3637) /* 0.327932565 */, 16 }, - - /* 1776 */ { MAD_F(0x0540388a) /* 0.328178922 */, 16 }, - /* 1777 */ { MAD_F(0x05413aea) /* 0.328425326 */, 16 }, - /* 1778 */ { MAD_F(0x05423d56) /* 0.328671776 */, 16 }, - /* 1779 */ { MAD_F(0x05433fce) /* 0.328918272 */, 16 }, - /* 1780 */ { MAD_F(0x05444253) /* 0.329164814 */, 16 }, - /* 1781 */ { MAD_F(0x054544e4) /* 0.329411403 */, 16 }, - /* 1782 */ { MAD_F(0x05464781) /* 0.329658038 */, 16 }, - /* 1783 */ { MAD_F(0x05474a2b) /* 0.329904718 */, 16 }, - /* 1784 */ { MAD_F(0x05484ce2) /* 0.330151445 */, 16 }, - /* 1785 */ { MAD_F(0x05494fa4) /* 0.330398218 */, 16 }, - /* 1786 */ { MAD_F(0x054a5273) /* 0.330645037 */, 16 }, - /* 1787 */ { MAD_F(0x054b554e) /* 0.330891903 */, 16 }, - /* 1788 */ { MAD_F(0x054c5836) /* 0.331138814 */, 16 }, - /* 1789 */ { MAD_F(0x054d5b2a) /* 0.331385771 */, 16 }, - /* 1790 */ { MAD_F(0x054e5e2b) /* 0.331632774 */, 16 }, - /* 1791 */ { MAD_F(0x054f6138) /* 0.331879824 */, 16 }, - - /* 1792 */ { MAD_F(0x05506451) /* 0.332126919 */, 16 }, - /* 1793 */ { MAD_F(0x05516776) /* 0.332374060 */, 16 }, - /* 1794 */ { MAD_F(0x05526aa8) /* 0.332621247 */, 16 }, - /* 1795 */ { MAD_F(0x05536de6) /* 0.332868480 */, 16 }, - /* 1796 */ { MAD_F(0x05547131) /* 0.333115759 */, 16 }, - /* 1797 */ { MAD_F(0x05557487) /* 0.333363084 */, 16 }, - /* 1798 */ { MAD_F(0x055677ea) /* 0.333610455 */, 16 }, - /* 1799 */ { MAD_F(0x05577b5a) /* 0.333857872 */, 16 }, - /* 1800 */ { MAD_F(0x05587ed5) /* 0.334105334 */, 16 }, - /* 1801 */ { MAD_F(0x0559825e) /* 0.334352843 */, 16 }, - /* 1802 */ { MAD_F(0x055a85f2) /* 0.334600397 */, 16 }, - /* 1803 */ { MAD_F(0x055b8992) /* 0.334847997 */, 16 }, - /* 1804 */ { MAD_F(0x055c8d3f) /* 0.335095642 */, 16 }, - /* 1805 */ { MAD_F(0x055d90f9) /* 0.335343334 */, 16 }, - /* 1806 */ { MAD_F(0x055e94be) /* 0.335591071 */, 16 }, - /* 1807 */ { MAD_F(0x055f9890) /* 0.335838854 */, 16 }, - - /* 1808 */ { MAD_F(0x05609c6e) /* 0.336086683 */, 16 }, - /* 1809 */ { MAD_F(0x0561a058) /* 0.336334557 */, 16 }, - /* 1810 */ { MAD_F(0x0562a44f) /* 0.336582477 */, 16 }, - /* 1811 */ { MAD_F(0x0563a851) /* 0.336830443 */, 16 }, - /* 1812 */ { MAD_F(0x0564ac60) /* 0.337078454 */, 16 }, - /* 1813 */ { MAD_F(0x0565b07c) /* 0.337326511 */, 16 }, - /* 1814 */ { MAD_F(0x0566b4a3) /* 0.337574614 */, 16 }, - /* 1815 */ { MAD_F(0x0567b8d7) /* 0.337822762 */, 16 }, - /* 1816 */ { MAD_F(0x0568bd17) /* 0.338070956 */, 16 }, - /* 1817 */ { MAD_F(0x0569c163) /* 0.338319195 */, 16 }, - /* 1818 */ { MAD_F(0x056ac5bc) /* 0.338567480 */, 16 }, - /* 1819 */ { MAD_F(0x056bca20) /* 0.338815811 */, 16 }, - /* 1820 */ { MAD_F(0x056cce91) /* 0.339064186 */, 16 }, - /* 1821 */ { MAD_F(0x056dd30e) /* 0.339312608 */, 16 }, - /* 1822 */ { MAD_F(0x056ed798) /* 0.339561075 */, 16 }, - /* 1823 */ { MAD_F(0x056fdc2d) /* 0.339809587 */, 16 }, - - /* 1824 */ { MAD_F(0x0570e0cf) /* 0.340058145 */, 16 }, - /* 1825 */ { MAD_F(0x0571e57d) /* 0.340306748 */, 16 }, - /* 1826 */ { MAD_F(0x0572ea37) /* 0.340555397 */, 16 }, - /* 1827 */ { MAD_F(0x0573eefd) /* 0.340804091 */, 16 }, - /* 1828 */ { MAD_F(0x0574f3d0) /* 0.341052830 */, 16 }, - /* 1829 */ { MAD_F(0x0575f8ae) /* 0.341301615 */, 16 }, - /* 1830 */ { MAD_F(0x0576fd99) /* 0.341550445 */, 16 }, - /* 1831 */ { MAD_F(0x05780290) /* 0.341799321 */, 16 }, - /* 1832 */ { MAD_F(0x05790793) /* 0.342048241 */, 16 }, - /* 1833 */ { MAD_F(0x057a0ca3) /* 0.342297207 */, 16 }, - /* 1834 */ { MAD_F(0x057b11be) /* 0.342546219 */, 16 }, - /* 1835 */ { MAD_F(0x057c16e6) /* 0.342795275 */, 16 }, - /* 1836 */ { MAD_F(0x057d1c1a) /* 0.343044377 */, 16 }, - /* 1837 */ { MAD_F(0x057e2159) /* 0.343293524 */, 16 }, - /* 1838 */ { MAD_F(0x057f26a6) /* 0.343542717 */, 16 }, - /* 1839 */ { MAD_F(0x05802bfe) /* 0.343791954 */, 16 }, - - /* 1840 */ { MAD_F(0x05813162) /* 0.344041237 */, 16 }, - /* 1841 */ { MAD_F(0x058236d2) /* 0.344290564 */, 16 }, - /* 1842 */ { MAD_F(0x05833c4f) /* 0.344539937 */, 16 }, - /* 1843 */ { MAD_F(0x058441d8) /* 0.344789356 */, 16 }, - /* 1844 */ { MAD_F(0x0585476c) /* 0.345038819 */, 16 }, - /* 1845 */ { MAD_F(0x05864d0d) /* 0.345288327 */, 16 }, - /* 1846 */ { MAD_F(0x058752ba) /* 0.345537880 */, 16 }, - /* 1847 */ { MAD_F(0x05885873) /* 0.345787479 */, 16 }, - /* 1848 */ { MAD_F(0x05895e39) /* 0.346037122 */, 16 }, - /* 1849 */ { MAD_F(0x058a640a) /* 0.346286811 */, 16 }, - /* 1850 */ { MAD_F(0x058b69e7) /* 0.346536545 */, 16 }, - /* 1851 */ { MAD_F(0x058c6fd1) /* 0.346786323 */, 16 }, - /* 1852 */ { MAD_F(0x058d75c6) /* 0.347036147 */, 16 }, - /* 1853 */ { MAD_F(0x058e7bc8) /* 0.347286015 */, 16 }, - /* 1854 */ { MAD_F(0x058f81d5) /* 0.347535929 */, 16 }, - /* 1855 */ { MAD_F(0x059087ef) /* 0.347785887 */, 16 }, - - /* 1856 */ { MAD_F(0x05918e15) /* 0.348035890 */, 16 }, - /* 1857 */ { MAD_F(0x05929447) /* 0.348285939 */, 16 }, - /* 1858 */ { MAD_F(0x05939a84) /* 0.348536032 */, 16 }, - /* 1859 */ { MAD_F(0x0594a0ce) /* 0.348786170 */, 16 }, - /* 1860 */ { MAD_F(0x0595a724) /* 0.349036353 */, 16 }, - /* 1861 */ { MAD_F(0x0596ad86) /* 0.349286580 */, 16 }, - /* 1862 */ { MAD_F(0x0597b3f4) /* 0.349536853 */, 16 }, - /* 1863 */ { MAD_F(0x0598ba6e) /* 0.349787170 */, 16 }, - /* 1864 */ { MAD_F(0x0599c0f4) /* 0.350037532 */, 16 }, - /* 1865 */ { MAD_F(0x059ac786) /* 0.350287939 */, 16 }, - /* 1866 */ { MAD_F(0x059bce25) /* 0.350538391 */, 16 }, - /* 1867 */ { MAD_F(0x059cd4cf) /* 0.350788887 */, 16 }, - /* 1868 */ { MAD_F(0x059ddb85) /* 0.351039428 */, 16 }, - /* 1869 */ { MAD_F(0x059ee247) /* 0.351290014 */, 16 }, - /* 1870 */ { MAD_F(0x059fe915) /* 0.351540645 */, 16 }, - /* 1871 */ { MAD_F(0x05a0efef) /* 0.351791320 */, 16 }, - - /* 1872 */ { MAD_F(0x05a1f6d5) /* 0.352042040 */, 16 }, - /* 1873 */ { MAD_F(0x05a2fdc7) /* 0.352292804 */, 16 }, - /* 1874 */ { MAD_F(0x05a404c5) /* 0.352543613 */, 16 }, - /* 1875 */ { MAD_F(0x05a50bcf) /* 0.352794467 */, 16 }, - /* 1876 */ { MAD_F(0x05a612e5) /* 0.353045365 */, 16 }, - /* 1877 */ { MAD_F(0x05a71a07) /* 0.353296308 */, 16 }, - /* 1878 */ { MAD_F(0x05a82135) /* 0.353547296 */, 16 }, - /* 1879 */ { MAD_F(0x05a9286f) /* 0.353798328 */, 16 }, - /* 1880 */ { MAD_F(0x05aa2fb5) /* 0.354049405 */, 16 }, - /* 1881 */ { MAD_F(0x05ab3707) /* 0.354300526 */, 16 }, - /* 1882 */ { MAD_F(0x05ac3e65) /* 0.354551691 */, 16 }, - /* 1883 */ { MAD_F(0x05ad45ce) /* 0.354802901 */, 16 }, - /* 1884 */ { MAD_F(0x05ae4d44) /* 0.355054156 */, 16 }, - /* 1885 */ { MAD_F(0x05af54c6) /* 0.355305455 */, 16 }, - /* 1886 */ { MAD_F(0x05b05c53) /* 0.355556799 */, 16 }, - /* 1887 */ { MAD_F(0x05b163ed) /* 0.355808187 */, 16 }, - - /* 1888 */ { MAD_F(0x05b26b92) /* 0.356059619 */, 16 }, - /* 1889 */ { MAD_F(0x05b37343) /* 0.356311096 */, 16 }, - /* 1890 */ { MAD_F(0x05b47b00) /* 0.356562617 */, 16 }, - /* 1891 */ { MAD_F(0x05b582c9) /* 0.356814182 */, 16 }, - /* 1892 */ { MAD_F(0x05b68a9e) /* 0.357065792 */, 16 }, - /* 1893 */ { MAD_F(0x05b7927f) /* 0.357317446 */, 16 }, - /* 1894 */ { MAD_F(0x05b89a6c) /* 0.357569145 */, 16 }, - /* 1895 */ { MAD_F(0x05b9a265) /* 0.357820887 */, 16 }, - /* 1896 */ { MAD_F(0x05baaa69) /* 0.358072674 */, 16 }, - /* 1897 */ { MAD_F(0x05bbb27a) /* 0.358324506 */, 16 }, - /* 1898 */ { MAD_F(0x05bcba96) /* 0.358576381 */, 16 }, - /* 1899 */ { MAD_F(0x05bdc2be) /* 0.358828301 */, 16 }, - /* 1900 */ { MAD_F(0x05becaf2) /* 0.359080265 */, 16 }, - /* 1901 */ { MAD_F(0x05bfd332) /* 0.359332273 */, 16 }, - /* 1902 */ { MAD_F(0x05c0db7e) /* 0.359584326 */, 16 }, - /* 1903 */ { MAD_F(0x05c1e3d6) /* 0.359836423 */, 16 }, - - /* 1904 */ { MAD_F(0x05c2ec39) /* 0.360088563 */, 16 }, - /* 1905 */ { MAD_F(0x05c3f4a9) /* 0.360340748 */, 16 }, - /* 1906 */ { MAD_F(0x05c4fd24) /* 0.360592977 */, 16 }, - /* 1907 */ { MAD_F(0x05c605ab) /* 0.360845251 */, 16 }, - /* 1908 */ { MAD_F(0x05c70e3e) /* 0.361097568 */, 16 }, - /* 1909 */ { MAD_F(0x05c816dd) /* 0.361349929 */, 16 }, - /* 1910 */ { MAD_F(0x05c91f87) /* 0.361602335 */, 16 }, - /* 1911 */ { MAD_F(0x05ca283e) /* 0.361854784 */, 16 }, - /* 1912 */ { MAD_F(0x05cb3100) /* 0.362107278 */, 16 }, - /* 1913 */ { MAD_F(0x05cc39ce) /* 0.362359815 */, 16 }, - /* 1914 */ { MAD_F(0x05cd42a8) /* 0.362612397 */, 16 }, - /* 1915 */ { MAD_F(0x05ce4b8d) /* 0.362865022 */, 16 }, - /* 1916 */ { MAD_F(0x05cf547f) /* 0.363117692 */, 16 }, - /* 1917 */ { MAD_F(0x05d05d7c) /* 0.363370405 */, 16 }, - /* 1918 */ { MAD_F(0x05d16685) /* 0.363623163 */, 16 }, - /* 1919 */ { MAD_F(0x05d26f9a) /* 0.363875964 */, 16 }, - - /* 1920 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 16 }, - /* 1921 */ { MAD_F(0x05d481e7) /* 0.364381698 */, 16 }, - /* 1922 */ { MAD_F(0x05d58b1f) /* 0.364634632 */, 16 }, - /* 1923 */ { MAD_F(0x05d69463) /* 0.364887608 */, 16 }, - /* 1924 */ { MAD_F(0x05d79db3) /* 0.365140629 */, 16 }, - /* 1925 */ { MAD_F(0x05d8a70f) /* 0.365393694 */, 16 }, - /* 1926 */ { MAD_F(0x05d9b076) /* 0.365646802 */, 16 }, - /* 1927 */ { MAD_F(0x05dab9e9) /* 0.365899955 */, 16 }, - /* 1928 */ { MAD_F(0x05dbc368) /* 0.366153151 */, 16 }, - /* 1929 */ { MAD_F(0x05dcccf2) /* 0.366406390 */, 16 }, - /* 1930 */ { MAD_F(0x05ddd689) /* 0.366659674 */, 16 }, - /* 1931 */ { MAD_F(0x05dee02b) /* 0.366913001 */, 16 }, - /* 1932 */ { MAD_F(0x05dfe9d8) /* 0.367166372 */, 16 }, - /* 1933 */ { MAD_F(0x05e0f392) /* 0.367419787 */, 16 }, - /* 1934 */ { MAD_F(0x05e1fd57) /* 0.367673246 */, 16 }, - /* 1935 */ { MAD_F(0x05e30728) /* 0.367926748 */, 16 }, - - /* 1936 */ { MAD_F(0x05e41105) /* 0.368180294 */, 16 }, - /* 1937 */ { MAD_F(0x05e51aed) /* 0.368433883 */, 16 }, - /* 1938 */ { MAD_F(0x05e624e1) /* 0.368687517 */, 16 }, - /* 1939 */ { MAD_F(0x05e72ee1) /* 0.368941193 */, 16 }, - /* 1940 */ { MAD_F(0x05e838ed) /* 0.369194914 */, 16 }, - /* 1941 */ { MAD_F(0x05e94304) /* 0.369448678 */, 16 }, - /* 1942 */ { MAD_F(0x05ea4d27) /* 0.369702485 */, 16 }, - /* 1943 */ { MAD_F(0x05eb5756) /* 0.369956336 */, 16 }, - /* 1944 */ { MAD_F(0x05ec6190) /* 0.370210231 */, 16 }, - /* 1945 */ { MAD_F(0x05ed6bd6) /* 0.370464169 */, 16 }, - /* 1946 */ { MAD_F(0x05ee7628) /* 0.370718151 */, 16 }, - /* 1947 */ { MAD_F(0x05ef8085) /* 0.370972177 */, 16 }, - /* 1948 */ { MAD_F(0x05f08aee) /* 0.371226245 */, 16 }, - /* 1949 */ { MAD_F(0x05f19563) /* 0.371480358 */, 16 }, - /* 1950 */ { MAD_F(0x05f29fe3) /* 0.371734513 */, 16 }, - /* 1951 */ { MAD_F(0x05f3aa6f) /* 0.371988712 */, 16 }, - - /* 1952 */ { MAD_F(0x05f4b507) /* 0.372242955 */, 16 }, - /* 1953 */ { MAD_F(0x05f5bfab) /* 0.372497241 */, 16 }, - /* 1954 */ { MAD_F(0x05f6ca5a) /* 0.372751570 */, 16 }, - /* 1955 */ { MAD_F(0x05f7d514) /* 0.373005943 */, 16 }, - /* 1956 */ { MAD_F(0x05f8dfdb) /* 0.373260359 */, 16 }, - /* 1957 */ { MAD_F(0x05f9eaad) /* 0.373514819 */, 16 }, - /* 1958 */ { MAD_F(0x05faf58a) /* 0.373769322 */, 16 }, - /* 1959 */ { MAD_F(0x05fc0073) /* 0.374023868 */, 16 }, - /* 1960 */ { MAD_F(0x05fd0b68) /* 0.374278458 */, 16 }, - /* 1961 */ { MAD_F(0x05fe1669) /* 0.374533091 */, 16 }, - /* 1962 */ { MAD_F(0x05ff2175) /* 0.374787767 */, 16 }, - /* 1963 */ { MAD_F(0x06002c8d) /* 0.375042486 */, 16 }, - /* 1964 */ { MAD_F(0x060137b0) /* 0.375297249 */, 16 }, - /* 1965 */ { MAD_F(0x060242df) /* 0.375552055 */, 16 }, - /* 1966 */ { MAD_F(0x06034e19) /* 0.375806904 */, 16 }, - /* 1967 */ { MAD_F(0x0604595f) /* 0.376061796 */, 16 }, - - /* 1968 */ { MAD_F(0x060564b1) /* 0.376316732 */, 16 }, - /* 1969 */ { MAD_F(0x0606700f) /* 0.376571710 */, 16 }, - /* 1970 */ { MAD_F(0x06077b77) /* 0.376826732 */, 16 }, - /* 1971 */ { MAD_F(0x060886ec) /* 0.377081797 */, 16 }, - /* 1972 */ { MAD_F(0x0609926c) /* 0.377336905 */, 16 }, - /* 1973 */ { MAD_F(0x060a9df8) /* 0.377592057 */, 16 }, - /* 1974 */ { MAD_F(0x060ba98f) /* 0.377847251 */, 16 }, - /* 1975 */ { MAD_F(0x060cb532) /* 0.378102489 */, 16 }, - /* 1976 */ { MAD_F(0x060dc0e0) /* 0.378357769 */, 16 }, - /* 1977 */ { MAD_F(0x060ecc9a) /* 0.378613093 */, 16 }, - /* 1978 */ { MAD_F(0x060fd860) /* 0.378868460 */, 16 }, - /* 1979 */ { MAD_F(0x0610e431) /* 0.379123870 */, 16 }, - /* 1980 */ { MAD_F(0x0611f00d) /* 0.379379322 */, 16 }, - /* 1981 */ { MAD_F(0x0612fbf5) /* 0.379634818 */, 16 }, - /* 1982 */ { MAD_F(0x061407e9) /* 0.379890357 */, 16 }, - /* 1983 */ { MAD_F(0x061513e8) /* 0.380145939 */, 16 }, - - /* 1984 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 16 }, - /* 1985 */ { MAD_F(0x06172c09) /* 0.380657231 */, 16 }, - /* 1986 */ { MAD_F(0x0618382b) /* 0.380912942 */, 16 }, - /* 1987 */ { MAD_F(0x06194458) /* 0.381168695 */, 16 }, - /* 1988 */ { MAD_F(0x061a5091) /* 0.381424492 */, 16 }, - /* 1989 */ { MAD_F(0x061b5cd5) /* 0.381680331 */, 16 }, - /* 1990 */ { MAD_F(0x061c6925) /* 0.381936213 */, 16 }, - /* 1991 */ { MAD_F(0x061d7581) /* 0.382192138 */, 16 }, - /* 1992 */ { MAD_F(0x061e81e8) /* 0.382448106 */, 16 }, - /* 1993 */ { MAD_F(0x061f8e5a) /* 0.382704117 */, 16 }, - /* 1994 */ { MAD_F(0x06209ad8) /* 0.382960171 */, 16 }, - /* 1995 */ { MAD_F(0x0621a761) /* 0.383216267 */, 16 }, - /* 1996 */ { MAD_F(0x0622b3f6) /* 0.383472406 */, 16 }, - /* 1997 */ { MAD_F(0x0623c096) /* 0.383728588 */, 16 }, - /* 1998 */ { MAD_F(0x0624cd42) /* 0.383984813 */, 16 }, - /* 1999 */ { MAD_F(0x0625d9f9) /* 0.384241080 */, 16 }, - - /* 2000 */ { MAD_F(0x0626e6bc) /* 0.384497391 */, 16 }, - /* 2001 */ { MAD_F(0x0627f38a) /* 0.384753744 */, 16 }, - /* 2002 */ { MAD_F(0x06290064) /* 0.385010139 */, 16 }, - /* 2003 */ { MAD_F(0x062a0d49) /* 0.385266578 */, 16 }, - /* 2004 */ { MAD_F(0x062b1a3a) /* 0.385523059 */, 16 }, - /* 2005 */ { MAD_F(0x062c2736) /* 0.385779582 */, 16 }, - /* 2006 */ { MAD_F(0x062d343d) /* 0.386036149 */, 16 }, - /* 2007 */ { MAD_F(0x062e4150) /* 0.386292758 */, 16 }, - /* 2008 */ { MAD_F(0x062f4e6f) /* 0.386549409 */, 16 }, - /* 2009 */ { MAD_F(0x06305b99) /* 0.386806104 */, 16 }, - /* 2010 */ { MAD_F(0x063168ce) /* 0.387062840 */, 16 }, - /* 2011 */ { MAD_F(0x0632760f) /* 0.387319620 */, 16 }, - /* 2012 */ { MAD_F(0x0633835b) /* 0.387576442 */, 16 }, - /* 2013 */ { MAD_F(0x063490b2) /* 0.387833306 */, 16 }, - /* 2014 */ { MAD_F(0x06359e15) /* 0.388090213 */, 16 }, - /* 2015 */ { MAD_F(0x0636ab83) /* 0.388347163 */, 16 }, - - /* 2016 */ { MAD_F(0x0637b8fd) /* 0.388604155 */, 16 }, - /* 2017 */ { MAD_F(0x0638c682) /* 0.388861190 */, 16 }, - /* 2018 */ { MAD_F(0x0639d413) /* 0.389118267 */, 16 }, - /* 2019 */ { MAD_F(0x063ae1af) /* 0.389375386 */, 16 }, - /* 2020 */ { MAD_F(0x063bef56) /* 0.389632548 */, 16 }, - /* 2021 */ { MAD_F(0x063cfd09) /* 0.389889752 */, 16 }, - /* 2022 */ { MAD_F(0x063e0ac7) /* 0.390146999 */, 16 }, - /* 2023 */ { MAD_F(0x063f1891) /* 0.390404289 */, 16 }, - /* 2024 */ { MAD_F(0x06402666) /* 0.390661620 */, 16 }, - /* 2025 */ { MAD_F(0x06413446) /* 0.390918994 */, 16 }, - /* 2026 */ { MAD_F(0x06424232) /* 0.391176411 */, 16 }, - /* 2027 */ { MAD_F(0x06435029) /* 0.391433869 */, 16 }, - /* 2028 */ { MAD_F(0x06445e2b) /* 0.391691371 */, 16 }, - /* 2029 */ { MAD_F(0x06456c39) /* 0.391948914 */, 16 }, - /* 2030 */ { MAD_F(0x06467a52) /* 0.392206500 */, 16 }, - /* 2031 */ { MAD_F(0x06478877) /* 0.392464128 */, 16 }, - - /* 2032 */ { MAD_F(0x064896a7) /* 0.392721798 */, 16 }, - /* 2033 */ { MAD_F(0x0649a4e2) /* 0.392979511 */, 16 }, - /* 2034 */ { MAD_F(0x064ab328) /* 0.393237266 */, 16 }, - /* 2035 */ { MAD_F(0x064bc17a) /* 0.393495063 */, 16 }, - /* 2036 */ { MAD_F(0x064ccfd8) /* 0.393752902 */, 16 }, - /* 2037 */ { MAD_F(0x064dde40) /* 0.394010784 */, 16 }, - /* 2038 */ { MAD_F(0x064eecb4) /* 0.394268707 */, 16 }, - /* 2039 */ { MAD_F(0x064ffb33) /* 0.394526673 */, 16 }, - /* 2040 */ { MAD_F(0x065109be) /* 0.394784681 */, 16 }, - /* 2041 */ { MAD_F(0x06521854) /* 0.395042732 */, 16 }, - /* 2042 */ { MAD_F(0x065326f5) /* 0.395300824 */, 16 }, - /* 2043 */ { MAD_F(0x065435a1) /* 0.395558959 */, 16 }, - /* 2044 */ { MAD_F(0x06554459) /* 0.395817135 */, 16 }, - /* 2045 */ { MAD_F(0x0656531c) /* 0.396075354 */, 16 }, - /* 2046 */ { MAD_F(0x065761ea) /* 0.396333615 */, 16 }, - /* 2047 */ { MAD_F(0x065870c4) /* 0.396591918 */, 16 }, - - /* 2048 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 16 }, - /* 2049 */ { MAD_F(0x065a8e99) /* 0.397108650 */, 16 }, - /* 2050 */ { MAD_F(0x065b9d95) /* 0.397367079 */, 16 }, - /* 2051 */ { MAD_F(0x065cac9c) /* 0.397625550 */, 16 }, - /* 2052 */ { MAD_F(0x065dbbae) /* 0.397884063 */, 16 }, - /* 2053 */ { MAD_F(0x065ecacb) /* 0.398142619 */, 16 }, - /* 2054 */ { MAD_F(0x065fd9f4) /* 0.398401216 */, 16 }, - /* 2055 */ { MAD_F(0x0660e928) /* 0.398659855 */, 16 }, - /* 2056 */ { MAD_F(0x0661f867) /* 0.398918536 */, 16 }, - /* 2057 */ { MAD_F(0x066307b1) /* 0.399177259 */, 16 }, - /* 2058 */ { MAD_F(0x06641707) /* 0.399436024 */, 16 }, - /* 2059 */ { MAD_F(0x06652668) /* 0.399694831 */, 16 }, - /* 2060 */ { MAD_F(0x066635d4) /* 0.399953679 */, 16 }, - /* 2061 */ { MAD_F(0x0667454c) /* 0.400212570 */, 16 }, - /* 2062 */ { MAD_F(0x066854ce) /* 0.400471503 */, 16 }, - /* 2063 */ { MAD_F(0x0669645c) /* 0.400730477 */, 16 }, - - /* 2064 */ { MAD_F(0x066a73f5) /* 0.400989493 */, 16 }, - /* 2065 */ { MAD_F(0x066b839a) /* 0.401248551 */, 16 }, - /* 2066 */ { MAD_F(0x066c9349) /* 0.401507651 */, 16 }, - /* 2067 */ { MAD_F(0x066da304) /* 0.401766793 */, 16 }, - /* 2068 */ { MAD_F(0x066eb2ca) /* 0.402025976 */, 16 }, - /* 2069 */ { MAD_F(0x066fc29b) /* 0.402285202 */, 16 }, - /* 2070 */ { MAD_F(0x0670d278) /* 0.402544469 */, 16 }, - /* 2071 */ { MAD_F(0x0671e25f) /* 0.402803777 */, 16 }, - /* 2072 */ { MAD_F(0x0672f252) /* 0.403063128 */, 16 }, - /* 2073 */ { MAD_F(0x06740250) /* 0.403322520 */, 16 }, - /* 2074 */ { MAD_F(0x0675125a) /* 0.403581954 */, 16 }, - /* 2075 */ { MAD_F(0x0676226e) /* 0.403841430 */, 16 }, - /* 2076 */ { MAD_F(0x0677328e) /* 0.404100947 */, 16 }, - /* 2077 */ { MAD_F(0x067842b9) /* 0.404360506 */, 16 }, - /* 2078 */ { MAD_F(0x067952ef) /* 0.404620107 */, 16 }, - /* 2079 */ { MAD_F(0x067a6330) /* 0.404879749 */, 16 }, - - /* 2080 */ { MAD_F(0x067b737c) /* 0.405139433 */, 16 }, - /* 2081 */ { MAD_F(0x067c83d4) /* 0.405399159 */, 16 }, - /* 2082 */ { MAD_F(0x067d9436) /* 0.405658926 */, 16 }, - /* 2083 */ { MAD_F(0x067ea4a4) /* 0.405918735 */, 16 }, - /* 2084 */ { MAD_F(0x067fb51d) /* 0.406178585 */, 16 }, - /* 2085 */ { MAD_F(0x0680c5a2) /* 0.406438477 */, 16 }, - /* 2086 */ { MAD_F(0x0681d631) /* 0.406698410 */, 16 }, - /* 2087 */ { MAD_F(0x0682e6cb) /* 0.406958385 */, 16 }, - /* 2088 */ { MAD_F(0x0683f771) /* 0.407218402 */, 16 }, - /* 2089 */ { MAD_F(0x06850822) /* 0.407478460 */, 16 }, - /* 2090 */ { MAD_F(0x068618de) /* 0.407738559 */, 16 }, - /* 2091 */ { MAD_F(0x068729a5) /* 0.407998700 */, 16 }, - /* 2092 */ { MAD_F(0x06883a77) /* 0.408258883 */, 16 }, - /* 2093 */ { MAD_F(0x06894b55) /* 0.408519107 */, 16 }, - /* 2094 */ { MAD_F(0x068a5c3d) /* 0.408779372 */, 16 }, - /* 2095 */ { MAD_F(0x068b6d31) /* 0.409039679 */, 16 }, - - /* 2096 */ { MAD_F(0x068c7e2f) /* 0.409300027 */, 16 }, - /* 2097 */ { MAD_F(0x068d8f39) /* 0.409560417 */, 16 }, - /* 2098 */ { MAD_F(0x068ea04e) /* 0.409820848 */, 16 }, - /* 2099 */ { MAD_F(0x068fb16e) /* 0.410081321 */, 16 }, - /* 2100 */ { MAD_F(0x0690c299) /* 0.410341834 */, 16 }, - /* 2101 */ { MAD_F(0x0691d3cf) /* 0.410602390 */, 16 }, - /* 2102 */ { MAD_F(0x0692e511) /* 0.410862986 */, 16 }, - /* 2103 */ { MAD_F(0x0693f65d) /* 0.411123624 */, 16 }, - /* 2104 */ { MAD_F(0x069507b5) /* 0.411384303 */, 16 }, - /* 2105 */ { MAD_F(0x06961917) /* 0.411645024 */, 16 }, - /* 2106 */ { MAD_F(0x06972a85) /* 0.411905785 */, 16 }, - /* 2107 */ { MAD_F(0x06983bfe) /* 0.412166588 */, 16 }, - /* 2108 */ { MAD_F(0x06994d82) /* 0.412427433 */, 16 }, - /* 2109 */ { MAD_F(0x069a5f11) /* 0.412688318 */, 16 }, - /* 2110 */ { MAD_F(0x069b70ab) /* 0.412949245 */, 16 }, - /* 2111 */ { MAD_F(0x069c8250) /* 0.413210213 */, 16 }, - - /* 2112 */ { MAD_F(0x069d9400) /* 0.413471222 */, 16 }, - /* 2113 */ { MAD_F(0x069ea5bb) /* 0.413732273 */, 16 }, - /* 2114 */ { MAD_F(0x069fb781) /* 0.413993364 */, 16 }, - /* 2115 */ { MAD_F(0x06a0c953) /* 0.414254497 */, 16 }, - /* 2116 */ { MAD_F(0x06a1db2f) /* 0.414515671 */, 16 }, - /* 2117 */ { MAD_F(0x06a2ed16) /* 0.414776886 */, 16 }, - /* 2118 */ { MAD_F(0x06a3ff09) /* 0.415038142 */, 16 }, - /* 2119 */ { MAD_F(0x06a51106) /* 0.415299440 */, 16 }, - /* 2120 */ { MAD_F(0x06a6230f) /* 0.415560778 */, 16 }, - /* 2121 */ { MAD_F(0x06a73522) /* 0.415822157 */, 16 }, - /* 2122 */ { MAD_F(0x06a84741) /* 0.416083578 */, 16 }, - /* 2123 */ { MAD_F(0x06a9596a) /* 0.416345040 */, 16 }, - /* 2124 */ { MAD_F(0x06aa6b9f) /* 0.416606542 */, 16 }, - /* 2125 */ { MAD_F(0x06ab7ddf) /* 0.416868086 */, 16 }, - /* 2126 */ { MAD_F(0x06ac9029) /* 0.417129671 */, 16 }, - /* 2127 */ { MAD_F(0x06ada27f) /* 0.417391297 */, 16 }, - - /* 2128 */ { MAD_F(0x06aeb4e0) /* 0.417652964 */, 16 }, - /* 2129 */ { MAD_F(0x06afc74b) /* 0.417914672 */, 16 }, - /* 2130 */ { MAD_F(0x06b0d9c2) /* 0.418176420 */, 16 }, - /* 2131 */ { MAD_F(0x06b1ec43) /* 0.418438210 */, 16 }, - /* 2132 */ { MAD_F(0x06b2fed0) /* 0.418700041 */, 16 }, - /* 2133 */ { MAD_F(0x06b41168) /* 0.418961912 */, 16 }, - /* 2134 */ { MAD_F(0x06b5240a) /* 0.419223825 */, 16 }, - /* 2135 */ { MAD_F(0x06b636b8) /* 0.419485778 */, 16 }, - /* 2136 */ { MAD_F(0x06b74971) /* 0.419747773 */, 16 }, - /* 2137 */ { MAD_F(0x06b85c34) /* 0.420009808 */, 16 }, - /* 2138 */ { MAD_F(0x06b96f03) /* 0.420271884 */, 16 }, - /* 2139 */ { MAD_F(0x06ba81dc) /* 0.420534001 */, 16 }, - /* 2140 */ { MAD_F(0x06bb94c1) /* 0.420796159 */, 16 }, - /* 2141 */ { MAD_F(0x06bca7b0) /* 0.421058358 */, 16 }, - /* 2142 */ { MAD_F(0x06bdbaaa) /* 0.421320597 */, 16 }, - /* 2143 */ { MAD_F(0x06becdb0) /* 0.421582878 */, 16 }, - - /* 2144 */ { MAD_F(0x06bfe0c0) /* 0.421845199 */, 16 }, - /* 2145 */ { MAD_F(0x06c0f3db) /* 0.422107561 */, 16 }, - /* 2146 */ { MAD_F(0x06c20702) /* 0.422369964 */, 16 }, - /* 2147 */ { MAD_F(0x06c31a33) /* 0.422632407 */, 16 }, - /* 2148 */ { MAD_F(0x06c42d6f) /* 0.422894891 */, 16 }, - /* 2149 */ { MAD_F(0x06c540b6) /* 0.423157416 */, 16 }, - /* 2150 */ { MAD_F(0x06c65408) /* 0.423419982 */, 16 }, - /* 2151 */ { MAD_F(0x06c76765) /* 0.423682588 */, 16 }, - /* 2152 */ { MAD_F(0x06c87acc) /* 0.423945235 */, 16 }, - /* 2153 */ { MAD_F(0x06c98e3f) /* 0.424207923 */, 16 }, - /* 2154 */ { MAD_F(0x06caa1bd) /* 0.424470652 */, 16 }, - /* 2155 */ { MAD_F(0x06cbb545) /* 0.424733421 */, 16 }, - /* 2156 */ { MAD_F(0x06ccc8d9) /* 0.424996230 */, 16 }, - /* 2157 */ { MAD_F(0x06cddc77) /* 0.425259081 */, 16 }, - /* 2158 */ { MAD_F(0x06cef020) /* 0.425521972 */, 16 }, - /* 2159 */ { MAD_F(0x06d003d4) /* 0.425784903 */, 16 }, - - /* 2160 */ { MAD_F(0x06d11794) /* 0.426047876 */, 16 }, - /* 2161 */ { MAD_F(0x06d22b5e) /* 0.426310889 */, 16 }, - /* 2162 */ { MAD_F(0x06d33f32) /* 0.426573942 */, 16 }, - /* 2163 */ { MAD_F(0x06d45312) /* 0.426837036 */, 16 }, - /* 2164 */ { MAD_F(0x06d566fd) /* 0.427100170 */, 16 }, - /* 2165 */ { MAD_F(0x06d67af2) /* 0.427363345 */, 16 }, - /* 2166 */ { MAD_F(0x06d78ef3) /* 0.427626561 */, 16 }, - /* 2167 */ { MAD_F(0x06d8a2fe) /* 0.427889817 */, 16 }, - /* 2168 */ { MAD_F(0x06d9b714) /* 0.428153114 */, 16 }, - /* 2169 */ { MAD_F(0x06dacb35) /* 0.428416451 */, 16 }, - /* 2170 */ { MAD_F(0x06dbdf61) /* 0.428679828 */, 16 }, - /* 2171 */ { MAD_F(0x06dcf398) /* 0.428943246 */, 16 }, - /* 2172 */ { MAD_F(0x06de07d9) /* 0.429206704 */, 16 }, - /* 2173 */ { MAD_F(0x06df1c26) /* 0.429470203 */, 16 }, - /* 2174 */ { MAD_F(0x06e0307d) /* 0.429733743 */, 16 }, - /* 2175 */ { MAD_F(0x06e144df) /* 0.429997322 */, 16 }, - - /* 2176 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 16 }, - /* 2177 */ { MAD_F(0x06e36dc4) /* 0.430524603 */, 16 }, - /* 2178 */ { MAD_F(0x06e48246) /* 0.430788304 */, 16 }, - /* 2179 */ { MAD_F(0x06e596d4) /* 0.431052045 */, 16 }, - /* 2180 */ { MAD_F(0x06e6ab6c) /* 0.431315826 */, 16 }, - /* 2181 */ { MAD_F(0x06e7c00f) /* 0.431579648 */, 16 }, - /* 2182 */ { MAD_F(0x06e8d4bd) /* 0.431843511 */, 16 }, - /* 2183 */ { MAD_F(0x06e9e976) /* 0.432107413 */, 16 }, - /* 2184 */ { MAD_F(0x06eafe3a) /* 0.432371356 */, 16 }, - /* 2185 */ { MAD_F(0x06ec1308) /* 0.432635339 */, 16 }, - /* 2186 */ { MAD_F(0x06ed27e2) /* 0.432899362 */, 16 }, - /* 2187 */ { MAD_F(0x06ee3cc6) /* 0.433163426 */, 16 }, - /* 2188 */ { MAD_F(0x06ef51b4) /* 0.433427530 */, 16 }, - /* 2189 */ { MAD_F(0x06f066ae) /* 0.433691674 */, 16 }, - /* 2190 */ { MAD_F(0x06f17bb3) /* 0.433955859 */, 16 }, - /* 2191 */ { MAD_F(0x06f290c2) /* 0.434220083 */, 16 }, - - /* 2192 */ { MAD_F(0x06f3a5dc) /* 0.434484348 */, 16 }, - /* 2193 */ { MAD_F(0x06f4bb01) /* 0.434748653 */, 16 }, - /* 2194 */ { MAD_F(0x06f5d030) /* 0.435012998 */, 16 }, - /* 2195 */ { MAD_F(0x06f6e56b) /* 0.435277383 */, 16 }, - /* 2196 */ { MAD_F(0x06f7fab0) /* 0.435541809 */, 16 }, - /* 2197 */ { MAD_F(0x06f91000) /* 0.435806274 */, 16 }, - /* 2198 */ { MAD_F(0x06fa255a) /* 0.436070780 */, 16 }, - /* 2199 */ { MAD_F(0x06fb3ac0) /* 0.436335326 */, 16 }, - /* 2200 */ { MAD_F(0x06fc5030) /* 0.436599912 */, 16 }, - /* 2201 */ { MAD_F(0x06fd65ab) /* 0.436864538 */, 16 }, - /* 2202 */ { MAD_F(0x06fe7b31) /* 0.437129204 */, 16 }, - /* 2203 */ { MAD_F(0x06ff90c2) /* 0.437393910 */, 16 }, - /* 2204 */ { MAD_F(0x0700a65d) /* 0.437658657 */, 16 }, - /* 2205 */ { MAD_F(0x0701bc03) /* 0.437923443 */, 16 }, - /* 2206 */ { MAD_F(0x0702d1b4) /* 0.438188269 */, 16 }, - /* 2207 */ { MAD_F(0x0703e76f) /* 0.438453136 */, 16 }, - - /* 2208 */ { MAD_F(0x0704fd35) /* 0.438718042 */, 16 }, - /* 2209 */ { MAD_F(0x07061306) /* 0.438982988 */, 16 }, - /* 2210 */ { MAD_F(0x070728e2) /* 0.439247975 */, 16 }, - /* 2211 */ { MAD_F(0x07083ec9) /* 0.439513001 */, 16 }, - /* 2212 */ { MAD_F(0x070954ba) /* 0.439778067 */, 16 }, - /* 2213 */ { MAD_F(0x070a6ab6) /* 0.440043173 */, 16 }, - /* 2214 */ { MAD_F(0x070b80bc) /* 0.440308320 */, 16 }, - /* 2215 */ { MAD_F(0x070c96ce) /* 0.440573506 */, 16 }, - /* 2216 */ { MAD_F(0x070dacea) /* 0.440838732 */, 16 }, - /* 2217 */ { MAD_F(0x070ec310) /* 0.441103997 */, 16 }, - /* 2218 */ { MAD_F(0x070fd942) /* 0.441369303 */, 16 }, - /* 2219 */ { MAD_F(0x0710ef7e) /* 0.441634649 */, 16 }, - /* 2220 */ { MAD_F(0x071205c5) /* 0.441900034 */, 16 }, - /* 2221 */ { MAD_F(0x07131c17) /* 0.442165460 */, 16 }, - /* 2222 */ { MAD_F(0x07143273) /* 0.442430925 */, 16 }, - /* 2223 */ { MAD_F(0x071548da) /* 0.442696430 */, 16 }, - - /* 2224 */ { MAD_F(0x07165f4b) /* 0.442961975 */, 16 }, - /* 2225 */ { MAD_F(0x071775c8) /* 0.443227559 */, 16 }, - /* 2226 */ { MAD_F(0x07188c4f) /* 0.443493184 */, 16 }, - /* 2227 */ { MAD_F(0x0719a2e0) /* 0.443758848 */, 16 }, - /* 2228 */ { MAD_F(0x071ab97d) /* 0.444024552 */, 16 }, - /* 2229 */ { MAD_F(0x071bd024) /* 0.444290296 */, 16 }, - /* 2230 */ { MAD_F(0x071ce6d6) /* 0.444556079 */, 16 }, - /* 2231 */ { MAD_F(0x071dfd92) /* 0.444821902 */, 16 }, - /* 2232 */ { MAD_F(0x071f1459) /* 0.445087765 */, 16 }, - /* 2233 */ { MAD_F(0x07202b2b) /* 0.445353668 */, 16 }, - /* 2234 */ { MAD_F(0x07214207) /* 0.445619610 */, 16 }, - /* 2235 */ { MAD_F(0x072258ee) /* 0.445885592 */, 16 }, - /* 2236 */ { MAD_F(0x07236fe0) /* 0.446151614 */, 16 }, - /* 2237 */ { MAD_F(0x072486dc) /* 0.446417675 */, 16 }, - /* 2238 */ { MAD_F(0x07259de3) /* 0.446683776 */, 16 }, - /* 2239 */ { MAD_F(0x0726b4f4) /* 0.446949917 */, 16 }, - - /* 2240 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 16 }, - /* 2241 */ { MAD_F(0x0728e338) /* 0.447482317 */, 16 }, - /* 2242 */ { MAD_F(0x0729fa69) /* 0.447748576 */, 16 }, - /* 2243 */ { MAD_F(0x072b11a5) /* 0.448014875 */, 16 }, - /* 2244 */ { MAD_F(0x072c28ec) /* 0.448281214 */, 16 }, - /* 2245 */ { MAD_F(0x072d403d) /* 0.448547592 */, 16 }, - /* 2246 */ { MAD_F(0x072e5799) /* 0.448814010 */, 16 }, - /* 2247 */ { MAD_F(0x072f6f00) /* 0.449080467 */, 16 }, - /* 2248 */ { MAD_F(0x07308671) /* 0.449346964 */, 16 }, - /* 2249 */ { MAD_F(0x07319ded) /* 0.449613501 */, 16 }, - /* 2250 */ { MAD_F(0x0732b573) /* 0.449880076 */, 16 }, - /* 2251 */ { MAD_F(0x0733cd04) /* 0.450146692 */, 16 }, - /* 2252 */ { MAD_F(0x0734e4a0) /* 0.450413347 */, 16 }, - /* 2253 */ { MAD_F(0x0735fc46) /* 0.450680041 */, 16 }, - /* 2254 */ { MAD_F(0x073713f7) /* 0.450946775 */, 16 }, - /* 2255 */ { MAD_F(0x07382bb2) /* 0.451213548 */, 16 }, - - /* 2256 */ { MAD_F(0x07394378) /* 0.451480360 */, 16 }, - /* 2257 */ { MAD_F(0x073a5b49) /* 0.451747213 */, 16 }, - /* 2258 */ { MAD_F(0x073b7324) /* 0.452014104 */, 16 }, - /* 2259 */ { MAD_F(0x073c8b0a) /* 0.452281035 */, 16 }, - /* 2260 */ { MAD_F(0x073da2fa) /* 0.452548005 */, 16 }, - /* 2261 */ { MAD_F(0x073ebaf5) /* 0.452815015 */, 16 }, - /* 2262 */ { MAD_F(0x073fd2fa) /* 0.453082064 */, 16 }, - /* 2263 */ { MAD_F(0x0740eb0a) /* 0.453349152 */, 16 }, - /* 2264 */ { MAD_F(0x07420325) /* 0.453616280 */, 16 }, - /* 2265 */ { MAD_F(0x07431b4a) /* 0.453883447 */, 16 }, - /* 2266 */ { MAD_F(0x0744337a) /* 0.454150653 */, 16 }, - /* 2267 */ { MAD_F(0x07454bb4) /* 0.454417899 */, 16 }, - /* 2268 */ { MAD_F(0x074663f8) /* 0.454685184 */, 16 }, - /* 2269 */ { MAD_F(0x07477c48) /* 0.454952508 */, 16 }, - /* 2270 */ { MAD_F(0x074894a2) /* 0.455219872 */, 16 }, - /* 2271 */ { MAD_F(0x0749ad06) /* 0.455487275 */, 16 }, - - /* 2272 */ { MAD_F(0x074ac575) /* 0.455754717 */, 16 }, - /* 2273 */ { MAD_F(0x074bddee) /* 0.456022198 */, 16 }, - /* 2274 */ { MAD_F(0x074cf672) /* 0.456289719 */, 16 }, - /* 2275 */ { MAD_F(0x074e0f01) /* 0.456557278 */, 16 }, - /* 2276 */ { MAD_F(0x074f279a) /* 0.456824877 */, 16 }, - /* 2277 */ { MAD_F(0x0750403e) /* 0.457092516 */, 16 }, - /* 2278 */ { MAD_F(0x075158ec) /* 0.457360193 */, 16 }, - /* 2279 */ { MAD_F(0x075271a4) /* 0.457627909 */, 16 }, - /* 2280 */ { MAD_F(0x07538a67) /* 0.457895665 */, 16 }, - /* 2281 */ { MAD_F(0x0754a335) /* 0.458163460 */, 16 }, - /* 2282 */ { MAD_F(0x0755bc0d) /* 0.458431294 */, 16 }, - /* 2283 */ { MAD_F(0x0756d4f0) /* 0.458699167 */, 16 }, - /* 2284 */ { MAD_F(0x0757eddd) /* 0.458967079 */, 16 }, - /* 2285 */ { MAD_F(0x075906d5) /* 0.459235030 */, 16 }, - /* 2286 */ { MAD_F(0x075a1fd7) /* 0.459503021 */, 16 }, - /* 2287 */ { MAD_F(0x075b38e3) /* 0.459771050 */, 16 }, - - /* 2288 */ { MAD_F(0x075c51fa) /* 0.460039119 */, 16 }, - /* 2289 */ { MAD_F(0x075d6b1c) /* 0.460307226 */, 16 }, - /* 2290 */ { MAD_F(0x075e8448) /* 0.460575373 */, 16 }, - /* 2291 */ { MAD_F(0x075f9d7f) /* 0.460843559 */, 16 }, - /* 2292 */ { MAD_F(0x0760b6c0) /* 0.461111783 */, 16 }, - /* 2293 */ { MAD_F(0x0761d00b) /* 0.461380047 */, 16 }, - /* 2294 */ { MAD_F(0x0762e961) /* 0.461648350 */, 16 }, - /* 2295 */ { MAD_F(0x076402c1) /* 0.461916691 */, 16 }, - /* 2296 */ { MAD_F(0x07651c2c) /* 0.462185072 */, 16 }, - /* 2297 */ { MAD_F(0x076635a2) /* 0.462453492 */, 16 }, - /* 2298 */ { MAD_F(0x07674f22) /* 0.462721950 */, 16 }, - /* 2299 */ { MAD_F(0x076868ac) /* 0.462990448 */, 16 }, - /* 2300 */ { MAD_F(0x07698240) /* 0.463258984 */, 16 }, - /* 2301 */ { MAD_F(0x076a9be0) /* 0.463527560 */, 16 }, - /* 2302 */ { MAD_F(0x076bb589) /* 0.463796174 */, 16 }, - /* 2303 */ { MAD_F(0x076ccf3d) /* 0.464064827 */, 16 }, - - /* 2304 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 16 }, - /* 2305 */ { MAD_F(0x076f02c5) /* 0.464602250 */, 16 }, - /* 2306 */ { MAD_F(0x07701c98) /* 0.464871020 */, 16 }, - /* 2307 */ { MAD_F(0x07713676) /* 0.465139829 */, 16 }, - /* 2308 */ { MAD_F(0x0772505e) /* 0.465408676 */, 16 }, - /* 2309 */ { MAD_F(0x07736a51) /* 0.465677563 */, 16 }, - /* 2310 */ { MAD_F(0x0774844e) /* 0.465946488 */, 16 }, - /* 2311 */ { MAD_F(0x07759e55) /* 0.466215452 */, 16 }, - /* 2312 */ { MAD_F(0x0776b867) /* 0.466484455 */, 16 }, - /* 2313 */ { MAD_F(0x0777d283) /* 0.466753496 */, 16 }, - /* 2314 */ { MAD_F(0x0778ecaa) /* 0.467022577 */, 16 }, - /* 2315 */ { MAD_F(0x077a06db) /* 0.467291696 */, 16 }, - /* 2316 */ { MAD_F(0x077b2117) /* 0.467560854 */, 16 }, - /* 2317 */ { MAD_F(0x077c3b5d) /* 0.467830050 */, 16 }, - /* 2318 */ { MAD_F(0x077d55ad) /* 0.468099285 */, 16 }, - /* 2319 */ { MAD_F(0x077e7008) /* 0.468368560 */, 16 }, - - /* 2320 */ { MAD_F(0x077f8a6d) /* 0.468637872 */, 16 }, - /* 2321 */ { MAD_F(0x0780a4dc) /* 0.468907224 */, 16 }, - /* 2322 */ { MAD_F(0x0781bf56) /* 0.469176614 */, 16 }, - /* 2323 */ { MAD_F(0x0782d9da) /* 0.469446043 */, 16 }, - /* 2324 */ { MAD_F(0x0783f469) /* 0.469715510 */, 16 }, - /* 2325 */ { MAD_F(0x07850f02) /* 0.469985016 */, 16 }, - /* 2326 */ { MAD_F(0x078629a5) /* 0.470254561 */, 16 }, - /* 2327 */ { MAD_F(0x07874453) /* 0.470524145 */, 16 }, - /* 2328 */ { MAD_F(0x07885f0b) /* 0.470793767 */, 16 }, - /* 2329 */ { MAD_F(0x078979ce) /* 0.471063427 */, 16 }, - /* 2330 */ { MAD_F(0x078a949a) /* 0.471333126 */, 16 }, - /* 2331 */ { MAD_F(0x078baf72) /* 0.471602864 */, 16 }, - /* 2332 */ { MAD_F(0x078cca53) /* 0.471872641 */, 16 }, - /* 2333 */ { MAD_F(0x078de53f) /* 0.472142456 */, 16 }, - /* 2334 */ { MAD_F(0x078f0035) /* 0.472412309 */, 16 }, - /* 2335 */ { MAD_F(0x07901b36) /* 0.472682201 */, 16 }, - - /* 2336 */ { MAD_F(0x07913641) /* 0.472952132 */, 16 }, - /* 2337 */ { MAD_F(0x07925156) /* 0.473222101 */, 16 }, - /* 2338 */ { MAD_F(0x07936c76) /* 0.473492108 */, 16 }, - /* 2339 */ { MAD_F(0x079487a0) /* 0.473762155 */, 16 }, - /* 2340 */ { MAD_F(0x0795a2d4) /* 0.474032239 */, 16 }, - /* 2341 */ { MAD_F(0x0796be13) /* 0.474302362 */, 16 }, - /* 2342 */ { MAD_F(0x0797d95c) /* 0.474572524 */, 16 }, - /* 2343 */ { MAD_F(0x0798f4af) /* 0.474842724 */, 16 }, - /* 2344 */ { MAD_F(0x079a100c) /* 0.475112962 */, 16 }, - /* 2345 */ { MAD_F(0x079b2b74) /* 0.475383239 */, 16 }, - /* 2346 */ { MAD_F(0x079c46e7) /* 0.475653554 */, 16 }, - /* 2347 */ { MAD_F(0x079d6263) /* 0.475923908 */, 16 }, - /* 2348 */ { MAD_F(0x079e7dea) /* 0.476194300 */, 16 }, - /* 2349 */ { MAD_F(0x079f997b) /* 0.476464731 */, 16 }, - /* 2350 */ { MAD_F(0x07a0b516) /* 0.476735200 */, 16 }, - /* 2351 */ { MAD_F(0x07a1d0bc) /* 0.477005707 */, 16 }, - - /* 2352 */ { MAD_F(0x07a2ec6c) /* 0.477276252 */, 16 }, - /* 2353 */ { MAD_F(0x07a40827) /* 0.477546836 */, 16 }, - /* 2354 */ { MAD_F(0x07a523eb) /* 0.477817459 */, 16 }, - /* 2355 */ { MAD_F(0x07a63fba) /* 0.478088119 */, 16 }, - /* 2356 */ { MAD_F(0x07a75b93) /* 0.478358818 */, 16 }, - /* 2357 */ { MAD_F(0x07a87777) /* 0.478629555 */, 16 }, - /* 2358 */ { MAD_F(0x07a99364) /* 0.478900331 */, 16 }, - /* 2359 */ { MAD_F(0x07aaaf5c) /* 0.479171145 */, 16 }, - /* 2360 */ { MAD_F(0x07abcb5f) /* 0.479441997 */, 16 }, - /* 2361 */ { MAD_F(0x07ace76b) /* 0.479712887 */, 16 }, - /* 2362 */ { MAD_F(0x07ae0382) /* 0.479983816 */, 16 }, - /* 2363 */ { MAD_F(0x07af1fa3) /* 0.480254782 */, 16 }, - /* 2364 */ { MAD_F(0x07b03bcf) /* 0.480525787 */, 16 }, - /* 2365 */ { MAD_F(0x07b15804) /* 0.480796831 */, 16 }, - /* 2366 */ { MAD_F(0x07b27444) /* 0.481067912 */, 16 }, - /* 2367 */ { MAD_F(0x07b3908e) /* 0.481339032 */, 16 }, - - /* 2368 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 16 }, - /* 2369 */ { MAD_F(0x07b5c941) /* 0.481881385 */, 16 }, - /* 2370 */ { MAD_F(0x07b6e5aa) /* 0.482152620 */, 16 }, - /* 2371 */ { MAD_F(0x07b8021d) /* 0.482423892 */, 16 }, - /* 2372 */ { MAD_F(0x07b91e9b) /* 0.482695202 */, 16 }, - /* 2373 */ { MAD_F(0x07ba3b22) /* 0.482966551 */, 16 }, - /* 2374 */ { MAD_F(0x07bb57b4) /* 0.483237938 */, 16 }, - /* 2375 */ { MAD_F(0x07bc7450) /* 0.483509362 */, 16 }, - /* 2376 */ { MAD_F(0x07bd90f6) /* 0.483780825 */, 16 }, - /* 2377 */ { MAD_F(0x07beada7) /* 0.484052326 */, 16 }, - /* 2378 */ { MAD_F(0x07bfca61) /* 0.484323865 */, 16 }, - /* 2379 */ { MAD_F(0x07c0e726) /* 0.484595443 */, 16 }, - /* 2380 */ { MAD_F(0x07c203f5) /* 0.484867058 */, 16 }, - /* 2381 */ { MAD_F(0x07c320cf) /* 0.485138711 */, 16 }, - /* 2382 */ { MAD_F(0x07c43db2) /* 0.485410402 */, 16 }, - /* 2383 */ { MAD_F(0x07c55aa0) /* 0.485682131 */, 16 }, - - /* 2384 */ { MAD_F(0x07c67798) /* 0.485953899 */, 16 }, - /* 2385 */ { MAD_F(0x07c7949a) /* 0.486225704 */, 16 }, - /* 2386 */ { MAD_F(0x07c8b1a7) /* 0.486497547 */, 16 }, - /* 2387 */ { MAD_F(0x07c9cebd) /* 0.486769429 */, 16 }, - /* 2388 */ { MAD_F(0x07caebde) /* 0.487041348 */, 16 }, - /* 2389 */ { MAD_F(0x07cc0909) /* 0.487313305 */, 16 }, - /* 2390 */ { MAD_F(0x07cd263e) /* 0.487585300 */, 16 }, - /* 2391 */ { MAD_F(0x07ce437d) /* 0.487857333 */, 16 }, - /* 2392 */ { MAD_F(0x07cf60c7) /* 0.488129404 */, 16 }, - /* 2393 */ { MAD_F(0x07d07e1b) /* 0.488401513 */, 16 }, - /* 2394 */ { MAD_F(0x07d19b79) /* 0.488673660 */, 16 }, - /* 2395 */ { MAD_F(0x07d2b8e1) /* 0.488945845 */, 16 }, - /* 2396 */ { MAD_F(0x07d3d653) /* 0.489218067 */, 16 }, - /* 2397 */ { MAD_F(0x07d4f3cf) /* 0.489490328 */, 16 }, - /* 2398 */ { MAD_F(0x07d61156) /* 0.489762626 */, 16 }, - /* 2399 */ { MAD_F(0x07d72ee6) /* 0.490034962 */, 16 }, - - /* 2400 */ { MAD_F(0x07d84c81) /* 0.490307336 */, 16 }, - /* 2401 */ { MAD_F(0x07d96a26) /* 0.490579748 */, 16 }, - /* 2402 */ { MAD_F(0x07da87d5) /* 0.490852198 */, 16 }, - /* 2403 */ { MAD_F(0x07dba58f) /* 0.491124686 */, 16 }, - /* 2404 */ { MAD_F(0x07dcc352) /* 0.491397211 */, 16 }, - /* 2405 */ { MAD_F(0x07dde120) /* 0.491669774 */, 16 }, - /* 2406 */ { MAD_F(0x07defef7) /* 0.491942375 */, 16 }, - /* 2407 */ { MAD_F(0x07e01cd9) /* 0.492215014 */, 16 }, - /* 2408 */ { MAD_F(0x07e13ac5) /* 0.492487690 */, 16 }, - /* 2409 */ { MAD_F(0x07e258bc) /* 0.492760404 */, 16 }, - /* 2410 */ { MAD_F(0x07e376bc) /* 0.493033156 */, 16 }, - /* 2411 */ { MAD_F(0x07e494c6) /* 0.493305946 */, 16 }, - /* 2412 */ { MAD_F(0x07e5b2db) /* 0.493578773 */, 16 }, - /* 2413 */ { MAD_F(0x07e6d0f9) /* 0.493851638 */, 16 }, - /* 2414 */ { MAD_F(0x07e7ef22) /* 0.494124541 */, 16 }, - /* 2415 */ { MAD_F(0x07e90d55) /* 0.494397481 */, 16 }, - - /* 2416 */ { MAD_F(0x07ea2b92) /* 0.494670459 */, 16 }, - /* 2417 */ { MAD_F(0x07eb49d9) /* 0.494943475 */, 16 }, - /* 2418 */ { MAD_F(0x07ec682a) /* 0.495216529 */, 16 }, - /* 2419 */ { MAD_F(0x07ed8686) /* 0.495489620 */, 16 }, - /* 2420 */ { MAD_F(0x07eea4eb) /* 0.495762748 */, 16 }, - /* 2421 */ { MAD_F(0x07efc35b) /* 0.496035915 */, 16 }, - /* 2422 */ { MAD_F(0x07f0e1d4) /* 0.496309119 */, 16 }, - /* 2423 */ { MAD_F(0x07f20058) /* 0.496582360 */, 16 }, - /* 2424 */ { MAD_F(0x07f31ee6) /* 0.496855639 */, 16 }, - /* 2425 */ { MAD_F(0x07f43d7e) /* 0.497128956 */, 16 }, - /* 2426 */ { MAD_F(0x07f55c20) /* 0.497402310 */, 16 }, - /* 2427 */ { MAD_F(0x07f67acc) /* 0.497675702 */, 16 }, - /* 2428 */ { MAD_F(0x07f79982) /* 0.497949132 */, 16 }, - /* 2429 */ { MAD_F(0x07f8b842) /* 0.498222598 */, 16 }, - /* 2430 */ { MAD_F(0x07f9d70c) /* 0.498496103 */, 16 }, - /* 2431 */ { MAD_F(0x07faf5e1) /* 0.498769645 */, 16 }, - - /* 2432 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 16 }, - /* 2433 */ { MAD_F(0x07fd33a8) /* 0.499316841 */, 16 }, - /* 2434 */ { MAD_F(0x07fe529a) /* 0.499590496 */, 16 }, - /* 2435 */ { MAD_F(0x07ff7197) /* 0.499864188 */, 16 }, - /* 2436 */ { MAD_F(0x0400484f) /* 0.250068959 */, 17 }, - /* 2437 */ { MAD_F(0x0400d7d7) /* 0.250205842 */, 17 }, - /* 2438 */ { MAD_F(0x04016764) /* 0.250342744 */, 17 }, - /* 2439 */ { MAD_F(0x0401f6f7) /* 0.250479665 */, 17 }, - /* 2440 */ { MAD_F(0x0402868e) /* 0.250616605 */, 17 }, - /* 2441 */ { MAD_F(0x0403162b) /* 0.250753563 */, 17 }, - /* 2442 */ { MAD_F(0x0403a5cc) /* 0.250890540 */, 17 }, - /* 2443 */ { MAD_F(0x04043573) /* 0.251027536 */, 17 }, - /* 2444 */ { MAD_F(0x0404c51e) /* 0.251164550 */, 17 }, - /* 2445 */ { MAD_F(0x040554cf) /* 0.251301583 */, 17 }, - /* 2446 */ { MAD_F(0x0405e484) /* 0.251438635 */, 17 }, - /* 2447 */ { MAD_F(0x0406743f) /* 0.251575706 */, 17 }, - - /* 2448 */ { MAD_F(0x040703ff) /* 0.251712795 */, 17 }, - /* 2449 */ { MAD_F(0x040793c3) /* 0.251849903 */, 17 }, - /* 2450 */ { MAD_F(0x0408238d) /* 0.251987029 */, 17 }, - /* 2451 */ { MAD_F(0x0408b35b) /* 0.252124174 */, 17 }, - /* 2452 */ { MAD_F(0x0409432f) /* 0.252261338 */, 17 }, - /* 2453 */ { MAD_F(0x0409d308) /* 0.252398520 */, 17 }, - /* 2454 */ { MAD_F(0x040a62e5) /* 0.252535721 */, 17 }, - /* 2455 */ { MAD_F(0x040af2c8) /* 0.252672941 */, 17 }, - /* 2456 */ { MAD_F(0x040b82b0) /* 0.252810180 */, 17 }, - /* 2457 */ { MAD_F(0x040c129c) /* 0.252947436 */, 17 }, - /* 2458 */ { MAD_F(0x040ca28e) /* 0.253084712 */, 17 }, - /* 2459 */ { MAD_F(0x040d3284) /* 0.253222006 */, 17 }, - /* 2460 */ { MAD_F(0x040dc280) /* 0.253359319 */, 17 }, - /* 2461 */ { MAD_F(0x040e5281) /* 0.253496651 */, 17 }, - /* 2462 */ { MAD_F(0x040ee286) /* 0.253634001 */, 17 }, - /* 2463 */ { MAD_F(0x040f7291) /* 0.253771369 */, 17 }, - - /* 2464 */ { MAD_F(0x041002a1) /* 0.253908756 */, 17 }, - /* 2465 */ { MAD_F(0x041092b5) /* 0.254046162 */, 17 }, - /* 2466 */ { MAD_F(0x041122cf) /* 0.254183587 */, 17 }, - /* 2467 */ { MAD_F(0x0411b2ed) /* 0.254321030 */, 17 }, - /* 2468 */ { MAD_F(0x04124311) /* 0.254458491 */, 17 }, - /* 2469 */ { MAD_F(0x0412d339) /* 0.254595971 */, 17 }, - /* 2470 */ { MAD_F(0x04136367) /* 0.254733470 */, 17 }, - /* 2471 */ { MAD_F(0x0413f399) /* 0.254870987 */, 17 }, - /* 2472 */ { MAD_F(0x041483d1) /* 0.255008523 */, 17 }, - /* 2473 */ { MAD_F(0x0415140d) /* 0.255146077 */, 17 }, - /* 2474 */ { MAD_F(0x0415a44f) /* 0.255283650 */, 17 }, - /* 2475 */ { MAD_F(0x04163495) /* 0.255421241 */, 17 }, - /* 2476 */ { MAD_F(0x0416c4e1) /* 0.255558851 */, 17 }, - /* 2477 */ { MAD_F(0x04175531) /* 0.255696480 */, 17 }, - /* 2478 */ { MAD_F(0x0417e586) /* 0.255834127 */, 17 }, - /* 2479 */ { MAD_F(0x041875e1) /* 0.255971792 */, 17 }, - - /* 2480 */ { MAD_F(0x04190640) /* 0.256109476 */, 17 }, - /* 2481 */ { MAD_F(0x041996a4) /* 0.256247179 */, 17 }, - /* 2482 */ { MAD_F(0x041a270d) /* 0.256384900 */, 17 }, - /* 2483 */ { MAD_F(0x041ab77b) /* 0.256522639 */, 17 }, - /* 2484 */ { MAD_F(0x041b47ef) /* 0.256660397 */, 17 }, - /* 2485 */ { MAD_F(0x041bd867) /* 0.256798174 */, 17 }, - /* 2486 */ { MAD_F(0x041c68e4) /* 0.256935969 */, 17 }, - /* 2487 */ { MAD_F(0x041cf966) /* 0.257073782 */, 17 }, - /* 2488 */ { MAD_F(0x041d89ed) /* 0.257211614 */, 17 }, - /* 2489 */ { MAD_F(0x041e1a79) /* 0.257349465 */, 17 }, - /* 2490 */ { MAD_F(0x041eab0a) /* 0.257487334 */, 17 }, - /* 2491 */ { MAD_F(0x041f3b9f) /* 0.257625221 */, 17 }, - /* 2492 */ { MAD_F(0x041fcc3a) /* 0.257763127 */, 17 }, - /* 2493 */ { MAD_F(0x04205cda) /* 0.257901051 */, 17 }, - /* 2494 */ { MAD_F(0x0420ed7f) /* 0.258038994 */, 17 }, - /* 2495 */ { MAD_F(0x04217e28) /* 0.258176955 */, 17 }, - - /* 2496 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 17 }, - /* 2497 */ { MAD_F(0x04229f8a) /* 0.258452932 */, 17 }, - /* 2498 */ { MAD_F(0x04233043) /* 0.258590948 */, 17 }, - /* 2499 */ { MAD_F(0x0423c100) /* 0.258728983 */, 17 }, - /* 2500 */ { MAD_F(0x042451c3) /* 0.258867036 */, 17 }, - /* 2501 */ { MAD_F(0x0424e28a) /* 0.259005108 */, 17 }, - /* 2502 */ { MAD_F(0x04257356) /* 0.259143198 */, 17 }, - /* 2503 */ { MAD_F(0x04260428) /* 0.259281307 */, 17 }, - /* 2504 */ { MAD_F(0x042694fe) /* 0.259419433 */, 17 }, - /* 2505 */ { MAD_F(0x042725d9) /* 0.259557579 */, 17 }, - /* 2506 */ { MAD_F(0x0427b6b9) /* 0.259695742 */, 17 }, - /* 2507 */ { MAD_F(0x0428479e) /* 0.259833924 */, 17 }, - /* 2508 */ { MAD_F(0x0428d888) /* 0.259972124 */, 17 }, - /* 2509 */ { MAD_F(0x04296976) /* 0.260110343 */, 17 }, - /* 2510 */ { MAD_F(0x0429fa6a) /* 0.260248580 */, 17 }, - /* 2511 */ { MAD_F(0x042a8b63) /* 0.260386836 */, 17 }, - - /* 2512 */ { MAD_F(0x042b1c60) /* 0.260525110 */, 17 }, - /* 2513 */ { MAD_F(0x042bad63) /* 0.260663402 */, 17 }, - /* 2514 */ { MAD_F(0x042c3e6a) /* 0.260801712 */, 17 }, - /* 2515 */ { MAD_F(0x042ccf77) /* 0.260940041 */, 17 }, - /* 2516 */ { MAD_F(0x042d6088) /* 0.261078388 */, 17 }, - /* 2517 */ { MAD_F(0x042df19e) /* 0.261216754 */, 17 }, - /* 2518 */ { MAD_F(0x042e82b9) /* 0.261355137 */, 17 }, - /* 2519 */ { MAD_F(0x042f13d9) /* 0.261493540 */, 17 }, - /* 2520 */ { MAD_F(0x042fa4fe) /* 0.261631960 */, 17 }, - /* 2521 */ { MAD_F(0x04303628) /* 0.261770399 */, 17 }, - /* 2522 */ { MAD_F(0x0430c757) /* 0.261908856 */, 17 }, - /* 2523 */ { MAD_F(0x0431588b) /* 0.262047331 */, 17 }, - /* 2524 */ { MAD_F(0x0431e9c3) /* 0.262185825 */, 17 }, - /* 2525 */ { MAD_F(0x04327b01) /* 0.262324337 */, 17 }, - /* 2526 */ { MAD_F(0x04330c43) /* 0.262462867 */, 17 }, - /* 2527 */ { MAD_F(0x04339d8a) /* 0.262601416 */, 17 }, - - /* 2528 */ { MAD_F(0x04342ed7) /* 0.262739982 */, 17 }, - /* 2529 */ { MAD_F(0x0434c028) /* 0.262878568 */, 17 }, - /* 2530 */ { MAD_F(0x0435517e) /* 0.263017171 */, 17 }, - /* 2531 */ { MAD_F(0x0435e2d9) /* 0.263155792 */, 17 }, - /* 2532 */ { MAD_F(0x04367439) /* 0.263294432 */, 17 }, - /* 2533 */ { MAD_F(0x0437059e) /* 0.263433090 */, 17 }, - /* 2534 */ { MAD_F(0x04379707) /* 0.263571767 */, 17 }, - /* 2535 */ { MAD_F(0x04382876) /* 0.263710461 */, 17 }, - /* 2536 */ { MAD_F(0x0438b9e9) /* 0.263849174 */, 17 }, - /* 2537 */ { MAD_F(0x04394b61) /* 0.263987905 */, 17 }, - /* 2538 */ { MAD_F(0x0439dcdf) /* 0.264126655 */, 17 }, - /* 2539 */ { MAD_F(0x043a6e61) /* 0.264265422 */, 17 }, - /* 2540 */ { MAD_F(0x043affe8) /* 0.264404208 */, 17 }, - /* 2541 */ { MAD_F(0x043b9174) /* 0.264543012 */, 17 }, - /* 2542 */ { MAD_F(0x043c2305) /* 0.264681834 */, 17 }, - /* 2543 */ { MAD_F(0x043cb49a) /* 0.264820674 */, 17 }, - - /* 2544 */ { MAD_F(0x043d4635) /* 0.264959533 */, 17 }, - /* 2545 */ { MAD_F(0x043dd7d4) /* 0.265098410 */, 17 }, - /* 2546 */ { MAD_F(0x043e6979) /* 0.265237305 */, 17 }, - /* 2547 */ { MAD_F(0x043efb22) /* 0.265376218 */, 17 }, - /* 2548 */ { MAD_F(0x043f8cd0) /* 0.265515149 */, 17 }, - /* 2549 */ { MAD_F(0x04401e83) /* 0.265654099 */, 17 }, - /* 2550 */ { MAD_F(0x0440b03b) /* 0.265793066 */, 17 }, - /* 2551 */ { MAD_F(0x044141f7) /* 0.265932052 */, 17 }, - /* 2552 */ { MAD_F(0x0441d3b9) /* 0.266071056 */, 17 }, - /* 2553 */ { MAD_F(0x04426580) /* 0.266210078 */, 17 }, - /* 2554 */ { MAD_F(0x0442f74b) /* 0.266349119 */, 17 }, - /* 2555 */ { MAD_F(0x0443891b) /* 0.266488177 */, 17 }, - /* 2556 */ { MAD_F(0x04441af0) /* 0.266627254 */, 17 }, - /* 2557 */ { MAD_F(0x0444acca) /* 0.266766349 */, 17 }, - /* 2558 */ { MAD_F(0x04453ea9) /* 0.266905462 */, 17 }, - /* 2559 */ { MAD_F(0x0445d08d) /* 0.267044593 */, 17 }, - - /* 2560 */ { MAD_F(0x04466275) /* 0.267183742 */, 17 }, - /* 2561 */ { MAD_F(0x0446f463) /* 0.267322909 */, 17 }, - /* 2562 */ { MAD_F(0x04478655) /* 0.267462094 */, 17 }, - /* 2563 */ { MAD_F(0x0448184c) /* 0.267601298 */, 17 }, - /* 2564 */ { MAD_F(0x0448aa48) /* 0.267740519 */, 17 }, - /* 2565 */ { MAD_F(0x04493c49) /* 0.267879759 */, 17 }, - /* 2566 */ { MAD_F(0x0449ce4f) /* 0.268019017 */, 17 }, - /* 2567 */ { MAD_F(0x044a6059) /* 0.268158293 */, 17 }, - /* 2568 */ { MAD_F(0x044af269) /* 0.268297587 */, 17 }, - /* 2569 */ { MAD_F(0x044b847d) /* 0.268436899 */, 17 }, - /* 2570 */ { MAD_F(0x044c1696) /* 0.268576229 */, 17 }, - /* 2571 */ { MAD_F(0x044ca8b4) /* 0.268715577 */, 17 }, - /* 2572 */ { MAD_F(0x044d3ad7) /* 0.268854943 */, 17 }, - /* 2573 */ { MAD_F(0x044dccff) /* 0.268994328 */, 17 }, - /* 2574 */ { MAD_F(0x044e5f2b) /* 0.269133730 */, 17 }, - /* 2575 */ { MAD_F(0x044ef15d) /* 0.269273150 */, 17 }, - - /* 2576 */ { MAD_F(0x044f8393) /* 0.269412589 */, 17 }, - /* 2577 */ { MAD_F(0x045015ce) /* 0.269552045 */, 17 }, - /* 2578 */ { MAD_F(0x0450a80e) /* 0.269691520 */, 17 }, - /* 2579 */ { MAD_F(0x04513a53) /* 0.269831013 */, 17 }, - /* 2580 */ { MAD_F(0x0451cc9c) /* 0.269970523 */, 17 }, - /* 2581 */ { MAD_F(0x04525eeb) /* 0.270110052 */, 17 }, - /* 2582 */ { MAD_F(0x0452f13e) /* 0.270249599 */, 17 }, - /* 2583 */ { MAD_F(0x04538396) /* 0.270389163 */, 17 }, - /* 2584 */ { MAD_F(0x045415f3) /* 0.270528746 */, 17 }, - /* 2585 */ { MAD_F(0x0454a855) /* 0.270668347 */, 17 }, - /* 2586 */ { MAD_F(0x04553abb) /* 0.270807965 */, 17 }, - /* 2587 */ { MAD_F(0x0455cd27) /* 0.270947602 */, 17 }, - /* 2588 */ { MAD_F(0x04565f97) /* 0.271087257 */, 17 }, - /* 2589 */ { MAD_F(0x0456f20c) /* 0.271226930 */, 17 }, - /* 2590 */ { MAD_F(0x04578486) /* 0.271366620 */, 17 }, - /* 2591 */ { MAD_F(0x04581705) /* 0.271506329 */, 17 }, - - /* 2592 */ { MAD_F(0x0458a989) /* 0.271646056 */, 17 }, - /* 2593 */ { MAD_F(0x04593c11) /* 0.271785800 */, 17 }, - /* 2594 */ { MAD_F(0x0459ce9e) /* 0.271925563 */, 17 }, - /* 2595 */ { MAD_F(0x045a6130) /* 0.272065343 */, 17 }, - /* 2596 */ { MAD_F(0x045af3c7) /* 0.272205142 */, 17 }, - /* 2597 */ { MAD_F(0x045b8663) /* 0.272344958 */, 17 }, - /* 2598 */ { MAD_F(0x045c1903) /* 0.272484793 */, 17 }, - /* 2599 */ { MAD_F(0x045caba9) /* 0.272624645 */, 17 }, - /* 2600 */ { MAD_F(0x045d3e53) /* 0.272764515 */, 17 }, - /* 2601 */ { MAD_F(0x045dd102) /* 0.272904403 */, 17 }, - /* 2602 */ { MAD_F(0x045e63b6) /* 0.273044310 */, 17 }, - /* 2603 */ { MAD_F(0x045ef66e) /* 0.273184234 */, 17 }, - /* 2604 */ { MAD_F(0x045f892b) /* 0.273324176 */, 17 }, - /* 2605 */ { MAD_F(0x04601bee) /* 0.273464136 */, 17 }, - /* 2606 */ { MAD_F(0x0460aeb5) /* 0.273604113 */, 17 }, - /* 2607 */ { MAD_F(0x04614180) /* 0.273744109 */, 17 }, - - /* 2608 */ { MAD_F(0x0461d451) /* 0.273884123 */, 17 }, - /* 2609 */ { MAD_F(0x04626727) /* 0.274024154 */, 17 }, - /* 2610 */ { MAD_F(0x0462fa01) /* 0.274164204 */, 17 }, - /* 2611 */ { MAD_F(0x04638ce0) /* 0.274304271 */, 17 }, - /* 2612 */ { MAD_F(0x04641fc4) /* 0.274444356 */, 17 }, - /* 2613 */ { MAD_F(0x0464b2ac) /* 0.274584459 */, 17 }, - /* 2614 */ { MAD_F(0x0465459a) /* 0.274724580 */, 17 }, - /* 2615 */ { MAD_F(0x0465d88c) /* 0.274864719 */, 17 }, - /* 2616 */ { MAD_F(0x04666b83) /* 0.275004875 */, 17 }, - /* 2617 */ { MAD_F(0x0466fe7f) /* 0.275145050 */, 17 }, - /* 2618 */ { MAD_F(0x0467917f) /* 0.275285242 */, 17 }, - /* 2619 */ { MAD_F(0x04682485) /* 0.275425452 */, 17 }, - /* 2620 */ { MAD_F(0x0468b78f) /* 0.275565681 */, 17 }, - /* 2621 */ { MAD_F(0x04694a9e) /* 0.275705926 */, 17 }, - /* 2622 */ { MAD_F(0x0469ddb2) /* 0.275846190 */, 17 }, - /* 2623 */ { MAD_F(0x046a70ca) /* 0.275986472 */, 17 }, - - /* 2624 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 17 }, - /* 2625 */ { MAD_F(0x046b970a) /* 0.276267088 */, 17 }, - /* 2626 */ { MAD_F(0x046c2a31) /* 0.276407423 */, 17 }, - /* 2627 */ { MAD_F(0x046cbd5c) /* 0.276547776 */, 17 }, - /* 2628 */ { MAD_F(0x046d508d) /* 0.276688147 */, 17 }, - /* 2629 */ { MAD_F(0x046de3c2) /* 0.276828535 */, 17 }, - /* 2630 */ { MAD_F(0x046e76fc) /* 0.276968942 */, 17 }, - /* 2631 */ { MAD_F(0x046f0a3b) /* 0.277109366 */, 17 }, - /* 2632 */ { MAD_F(0x046f9d7e) /* 0.277249808 */, 17 }, - /* 2633 */ { MAD_F(0x047030c7) /* 0.277390267 */, 17 }, - /* 2634 */ { MAD_F(0x0470c414) /* 0.277530745 */, 17 }, - /* 2635 */ { MAD_F(0x04715766) /* 0.277671240 */, 17 }, - /* 2636 */ { MAD_F(0x0471eabc) /* 0.277811753 */, 17 }, - /* 2637 */ { MAD_F(0x04727e18) /* 0.277952284 */, 17 }, - /* 2638 */ { MAD_F(0x04731178) /* 0.278092832 */, 17 }, - /* 2639 */ { MAD_F(0x0473a4dd) /* 0.278233399 */, 17 }, - - /* 2640 */ { MAD_F(0x04743847) /* 0.278373983 */, 17 }, - /* 2641 */ { MAD_F(0x0474cbb5) /* 0.278514584 */, 17 }, - /* 2642 */ { MAD_F(0x04755f29) /* 0.278655204 */, 17 }, - /* 2643 */ { MAD_F(0x0475f2a1) /* 0.278795841 */, 17 }, - /* 2644 */ { MAD_F(0x0476861d) /* 0.278936496 */, 17 }, - /* 2645 */ { MAD_F(0x0477199f) /* 0.279077169 */, 17 }, - /* 2646 */ { MAD_F(0x0477ad25) /* 0.279217860 */, 17 }, - /* 2647 */ { MAD_F(0x047840b0) /* 0.279358568 */, 17 }, - /* 2648 */ { MAD_F(0x0478d440) /* 0.279499294 */, 17 }, - /* 2649 */ { MAD_F(0x047967d5) /* 0.279640037 */, 17 }, - /* 2650 */ { MAD_F(0x0479fb6e) /* 0.279780799 */, 17 }, - /* 2651 */ { MAD_F(0x047a8f0c) /* 0.279921578 */, 17 }, - /* 2652 */ { MAD_F(0x047b22af) /* 0.280062375 */, 17 }, - /* 2653 */ { MAD_F(0x047bb657) /* 0.280203189 */, 17 }, - /* 2654 */ { MAD_F(0x047c4a03) /* 0.280344021 */, 17 }, - /* 2655 */ { MAD_F(0x047cddb4) /* 0.280484871 */, 17 }, - - /* 2656 */ { MAD_F(0x047d716a) /* 0.280625739 */, 17 }, - /* 2657 */ { MAD_F(0x047e0524) /* 0.280766624 */, 17 }, - /* 2658 */ { MAD_F(0x047e98e4) /* 0.280907527 */, 17 }, - /* 2659 */ { MAD_F(0x047f2ca8) /* 0.281048447 */, 17 }, - /* 2660 */ { MAD_F(0x047fc071) /* 0.281189385 */, 17 }, - /* 2661 */ { MAD_F(0x0480543e) /* 0.281330341 */, 17 }, - /* 2662 */ { MAD_F(0x0480e811) /* 0.281471315 */, 17 }, - /* 2663 */ { MAD_F(0x04817be8) /* 0.281612306 */, 17 }, - /* 2664 */ { MAD_F(0x04820fc3) /* 0.281753315 */, 17 }, - /* 2665 */ { MAD_F(0x0482a3a4) /* 0.281894341 */, 17 }, - /* 2666 */ { MAD_F(0x04833789) /* 0.282035386 */, 17 }, - /* 2667 */ { MAD_F(0x0483cb73) /* 0.282176447 */, 17 }, - /* 2668 */ { MAD_F(0x04845f62) /* 0.282317527 */, 17 }, - /* 2669 */ { MAD_F(0x0484f355) /* 0.282458624 */, 17 }, - /* 2670 */ { MAD_F(0x0485874d) /* 0.282599738 */, 17 }, - /* 2671 */ { MAD_F(0x04861b4a) /* 0.282740871 */, 17 }, - - /* 2672 */ { MAD_F(0x0486af4c) /* 0.282882021 */, 17 }, - /* 2673 */ { MAD_F(0x04874352) /* 0.283023188 */, 17 }, - /* 2674 */ { MAD_F(0x0487d75d) /* 0.283164373 */, 17 }, - /* 2675 */ { MAD_F(0x04886b6d) /* 0.283305576 */, 17 }, - /* 2676 */ { MAD_F(0x0488ff82) /* 0.283446796 */, 17 }, - /* 2677 */ { MAD_F(0x0489939b) /* 0.283588034 */, 17 }, - /* 2678 */ { MAD_F(0x048a27b9) /* 0.283729290 */, 17 }, - /* 2679 */ { MAD_F(0x048abbdc) /* 0.283870563 */, 17 }, - /* 2680 */ { MAD_F(0x048b5003) /* 0.284011853 */, 17 }, - /* 2681 */ { MAD_F(0x048be42f) /* 0.284153161 */, 17 }, - /* 2682 */ { MAD_F(0x048c7860) /* 0.284294487 */, 17 }, - /* 2683 */ { MAD_F(0x048d0c96) /* 0.284435831 */, 17 }, - /* 2684 */ { MAD_F(0x048da0d0) /* 0.284577192 */, 17 }, - /* 2685 */ { MAD_F(0x048e350f) /* 0.284718570 */, 17 }, - /* 2686 */ { MAD_F(0x048ec953) /* 0.284859966 */, 17 }, - /* 2687 */ { MAD_F(0x048f5d9b) /* 0.285001380 */, 17 }, - - /* 2688 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 17 }, - /* 2689 */ { MAD_F(0x0490863a) /* 0.285284259 */, 17 }, - /* 2690 */ { MAD_F(0x04911a91) /* 0.285425726 */, 17 }, - /* 2691 */ { MAD_F(0x0491aeec) /* 0.285567209 */, 17 }, - /* 2692 */ { MAD_F(0x0492434c) /* 0.285708711 */, 17 }, - /* 2693 */ { MAD_F(0x0492d7b0) /* 0.285850229 */, 17 }, - /* 2694 */ { MAD_F(0x04936c1a) /* 0.285991766 */, 17 }, - /* 2695 */ { MAD_F(0x04940088) /* 0.286133319 */, 17 }, - /* 2696 */ { MAD_F(0x049494fb) /* 0.286274891 */, 17 }, - /* 2697 */ { MAD_F(0x04952972) /* 0.286416480 */, 17 }, - /* 2698 */ { MAD_F(0x0495bdee) /* 0.286558086 */, 17 }, - /* 2699 */ { MAD_F(0x0496526f) /* 0.286699710 */, 17 }, - /* 2700 */ { MAD_F(0x0496e6f5) /* 0.286841351 */, 17 }, - /* 2701 */ { MAD_F(0x04977b7f) /* 0.286983010 */, 17 }, - /* 2702 */ { MAD_F(0x0498100e) /* 0.287124686 */, 17 }, - /* 2703 */ { MAD_F(0x0498a4a1) /* 0.287266380 */, 17 }, - - /* 2704 */ { MAD_F(0x0499393a) /* 0.287408091 */, 17 }, - /* 2705 */ { MAD_F(0x0499cdd7) /* 0.287549820 */, 17 }, - /* 2706 */ { MAD_F(0x049a6278) /* 0.287691566 */, 17 }, - /* 2707 */ { MAD_F(0x049af71f) /* 0.287833330 */, 17 }, - /* 2708 */ { MAD_F(0x049b8bca) /* 0.287975111 */, 17 }, - /* 2709 */ { MAD_F(0x049c207a) /* 0.288116909 */, 17 }, - /* 2710 */ { MAD_F(0x049cb52e) /* 0.288258725 */, 17 }, - /* 2711 */ { MAD_F(0x049d49e7) /* 0.288400559 */, 17 }, - /* 2712 */ { MAD_F(0x049ddea5) /* 0.288542409 */, 17 }, - /* 2713 */ { MAD_F(0x049e7367) /* 0.288684278 */, 17 }, - /* 2714 */ { MAD_F(0x049f082f) /* 0.288826163 */, 17 }, - /* 2715 */ { MAD_F(0x049f9cfa) /* 0.288968067 */, 17 }, - /* 2716 */ { MAD_F(0x04a031cb) /* 0.289109987 */, 17 }, - /* 2717 */ { MAD_F(0x04a0c6a0) /* 0.289251925 */, 17 }, - /* 2718 */ { MAD_F(0x04a15b7a) /* 0.289393881 */, 17 }, - /* 2719 */ { MAD_F(0x04a1f059) /* 0.289535854 */, 17 }, - - /* 2720 */ { MAD_F(0x04a2853c) /* 0.289677844 */, 17 }, - /* 2721 */ { MAD_F(0x04a31a24) /* 0.289819851 */, 17 }, - /* 2722 */ { MAD_F(0x04a3af10) /* 0.289961876 */, 17 }, - /* 2723 */ { MAD_F(0x04a44401) /* 0.290103919 */, 17 }, - /* 2724 */ { MAD_F(0x04a4d8f7) /* 0.290245979 */, 17 }, - /* 2725 */ { MAD_F(0x04a56df2) /* 0.290388056 */, 17 }, - /* 2726 */ { MAD_F(0x04a602f1) /* 0.290530150 */, 17 }, - /* 2727 */ { MAD_F(0x04a697f5) /* 0.290672262 */, 17 }, - /* 2728 */ { MAD_F(0x04a72cfe) /* 0.290814392 */, 17 }, - /* 2729 */ { MAD_F(0x04a7c20b) /* 0.290956538 */, 17 }, - /* 2730 */ { MAD_F(0x04a8571d) /* 0.291098703 */, 17 }, - /* 2731 */ { MAD_F(0x04a8ec33) /* 0.291240884 */, 17 }, - /* 2732 */ { MAD_F(0x04a9814e) /* 0.291383083 */, 17 }, - /* 2733 */ { MAD_F(0x04aa166e) /* 0.291525299 */, 17 }, - /* 2734 */ { MAD_F(0x04aaab93) /* 0.291667532 */, 17 }, - /* 2735 */ { MAD_F(0x04ab40bc) /* 0.291809783 */, 17 }, - - /* 2736 */ { MAD_F(0x04abd5ea) /* 0.291952051 */, 17 }, - /* 2737 */ { MAD_F(0x04ac6b1c) /* 0.292094337 */, 17 }, - /* 2738 */ { MAD_F(0x04ad0053) /* 0.292236640 */, 17 }, - /* 2739 */ { MAD_F(0x04ad958f) /* 0.292378960 */, 17 }, - /* 2740 */ { MAD_F(0x04ae2ad0) /* 0.292521297 */, 17 }, - /* 2741 */ { MAD_F(0x04aec015) /* 0.292663652 */, 17 }, - /* 2742 */ { MAD_F(0x04af555e) /* 0.292806024 */, 17 }, - /* 2743 */ { MAD_F(0x04afeaad) /* 0.292948414 */, 17 }, - /* 2744 */ { MAD_F(0x04b08000) /* 0.293090820 */, 17 }, - /* 2745 */ { MAD_F(0x04b11557) /* 0.293233244 */, 17 }, - /* 2746 */ { MAD_F(0x04b1aab4) /* 0.293375686 */, 17 }, - /* 2747 */ { MAD_F(0x04b24015) /* 0.293518144 */, 17 }, - /* 2748 */ { MAD_F(0x04b2d57a) /* 0.293660620 */, 17 }, - /* 2749 */ { MAD_F(0x04b36ae4) /* 0.293803113 */, 17 }, - /* 2750 */ { MAD_F(0x04b40053) /* 0.293945624 */, 17 }, - /* 2751 */ { MAD_F(0x04b495c7) /* 0.294088151 */, 17 }, - - /* 2752 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 17 }, - /* 2753 */ { MAD_F(0x04b5c0bc) /* 0.294373259 */, 17 }, - /* 2754 */ { MAD_F(0x04b6563d) /* 0.294515838 */, 17 }, - /* 2755 */ { MAD_F(0x04b6ebc3) /* 0.294658435 */, 17 }, - /* 2756 */ { MAD_F(0x04b7814e) /* 0.294801049 */, 17 }, - /* 2757 */ { MAD_F(0x04b816dd) /* 0.294943680 */, 17 }, - /* 2758 */ { MAD_F(0x04b8ac71) /* 0.295086329 */, 17 }, - /* 2759 */ { MAD_F(0x04b9420a) /* 0.295228995 */, 17 }, - /* 2760 */ { MAD_F(0x04b9d7a7) /* 0.295371678 */, 17 }, - /* 2761 */ { MAD_F(0x04ba6d49) /* 0.295514378 */, 17 }, - /* 2762 */ { MAD_F(0x04bb02ef) /* 0.295657095 */, 17 }, - /* 2763 */ { MAD_F(0x04bb989a) /* 0.295799830 */, 17 }, - /* 2764 */ { MAD_F(0x04bc2e4a) /* 0.295942582 */, 17 }, - /* 2765 */ { MAD_F(0x04bcc3fe) /* 0.296085351 */, 17 }, - /* 2766 */ { MAD_F(0x04bd59b7) /* 0.296228138 */, 17 }, - /* 2767 */ { MAD_F(0x04bdef74) /* 0.296370941 */, 17 }, - - /* 2768 */ { MAD_F(0x04be8537) /* 0.296513762 */, 17 }, - /* 2769 */ { MAD_F(0x04bf1afd) /* 0.296656600 */, 17 }, - /* 2770 */ { MAD_F(0x04bfb0c9) /* 0.296799455 */, 17 }, - /* 2771 */ { MAD_F(0x04c04699) /* 0.296942327 */, 17 }, - /* 2772 */ { MAD_F(0x04c0dc6d) /* 0.297085217 */, 17 }, - /* 2773 */ { MAD_F(0x04c17247) /* 0.297228124 */, 17 }, - /* 2774 */ { MAD_F(0x04c20824) /* 0.297371048 */, 17 }, - /* 2775 */ { MAD_F(0x04c29e07) /* 0.297513989 */, 17 }, - /* 2776 */ { MAD_F(0x04c333ee) /* 0.297656947 */, 17 }, - /* 2777 */ { MAD_F(0x04c3c9da) /* 0.297799922 */, 17 }, - /* 2778 */ { MAD_F(0x04c45fca) /* 0.297942915 */, 17 }, - /* 2779 */ { MAD_F(0x04c4f5bf) /* 0.298085925 */, 17 }, - /* 2780 */ { MAD_F(0x04c58bb8) /* 0.298228951 */, 17 }, - /* 2781 */ { MAD_F(0x04c621b6) /* 0.298371996 */, 17 }, - /* 2782 */ { MAD_F(0x04c6b7b9) /* 0.298515057 */, 17 }, - /* 2783 */ { MAD_F(0x04c74dc0) /* 0.298658135 */, 17 }, - - /* 2784 */ { MAD_F(0x04c7e3cc) /* 0.298801231 */, 17 }, - /* 2785 */ { MAD_F(0x04c879dd) /* 0.298944343 */, 17 }, - /* 2786 */ { MAD_F(0x04c90ff2) /* 0.299087473 */, 17 }, - /* 2787 */ { MAD_F(0x04c9a60c) /* 0.299230620 */, 17 }, - /* 2788 */ { MAD_F(0x04ca3c2a) /* 0.299373784 */, 17 }, - /* 2789 */ { MAD_F(0x04cad24d) /* 0.299516965 */, 17 }, - /* 2790 */ { MAD_F(0x04cb6874) /* 0.299660163 */, 17 }, - /* 2791 */ { MAD_F(0x04cbfea0) /* 0.299803378 */, 17 }, - /* 2792 */ { MAD_F(0x04cc94d1) /* 0.299946611 */, 17 }, - /* 2793 */ { MAD_F(0x04cd2b06) /* 0.300089860 */, 17 }, - /* 2794 */ { MAD_F(0x04cdc140) /* 0.300233127 */, 17 }, - /* 2795 */ { MAD_F(0x04ce577f) /* 0.300376411 */, 17 }, - /* 2796 */ { MAD_F(0x04ceedc2) /* 0.300519711 */, 17 }, - /* 2797 */ { MAD_F(0x04cf8409) /* 0.300663029 */, 17 }, - /* 2798 */ { MAD_F(0x04d01a55) /* 0.300806364 */, 17 }, - /* 2799 */ { MAD_F(0x04d0b0a6) /* 0.300949716 */, 17 }, - - /* 2800 */ { MAD_F(0x04d146fb) /* 0.301093085 */, 17 }, - /* 2801 */ { MAD_F(0x04d1dd55) /* 0.301236472 */, 17 }, - /* 2802 */ { MAD_F(0x04d273b4) /* 0.301379875 */, 17 }, - /* 2803 */ { MAD_F(0x04d30a17) /* 0.301523295 */, 17 }, - /* 2804 */ { MAD_F(0x04d3a07f) /* 0.301666733 */, 17 }, - /* 2805 */ { MAD_F(0x04d436eb) /* 0.301810187 */, 17 }, - /* 2806 */ { MAD_F(0x04d4cd5c) /* 0.301953659 */, 17 }, - /* 2807 */ { MAD_F(0x04d563d1) /* 0.302097147 */, 17 }, - /* 2808 */ { MAD_F(0x04d5fa4b) /* 0.302240653 */, 17 }, - /* 2809 */ { MAD_F(0x04d690ca) /* 0.302384175 */, 17 }, - /* 2810 */ { MAD_F(0x04d7274d) /* 0.302527715 */, 17 }, - /* 2811 */ { MAD_F(0x04d7bdd5) /* 0.302671271 */, 17 }, - /* 2812 */ { MAD_F(0x04d85461) /* 0.302814845 */, 17 }, - /* 2813 */ { MAD_F(0x04d8eaf2) /* 0.302958436 */, 17 }, - /* 2814 */ { MAD_F(0x04d98187) /* 0.303102044 */, 17 }, - /* 2815 */ { MAD_F(0x04da1821) /* 0.303245668 */, 17 }, - - /* 2816 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 17 }, - /* 2817 */ { MAD_F(0x04db4563) /* 0.303532969 */, 17 }, - /* 2818 */ { MAD_F(0x04dbdc0a) /* 0.303676645 */, 17 }, - /* 2819 */ { MAD_F(0x04dc72b7) /* 0.303820337 */, 17 }, - /* 2820 */ { MAD_F(0x04dd0967) /* 0.303964047 */, 17 }, - /* 2821 */ { MAD_F(0x04dda01d) /* 0.304107774 */, 17 }, - /* 2822 */ { MAD_F(0x04de36d7) /* 0.304251517 */, 17 }, - /* 2823 */ { MAD_F(0x04decd95) /* 0.304395278 */, 17 }, - /* 2824 */ { MAD_F(0x04df6458) /* 0.304539056 */, 17 }, - /* 2825 */ { MAD_F(0x04dffb20) /* 0.304682850 */, 17 }, - /* 2826 */ { MAD_F(0x04e091ec) /* 0.304826662 */, 17 }, - /* 2827 */ { MAD_F(0x04e128bc) /* 0.304970491 */, 17 }, - /* 2828 */ { MAD_F(0x04e1bf92) /* 0.305114336 */, 17 }, - /* 2829 */ { MAD_F(0x04e2566b) /* 0.305258199 */, 17 }, - /* 2830 */ { MAD_F(0x04e2ed4a) /* 0.305402078 */, 17 }, - /* 2831 */ { MAD_F(0x04e3842d) /* 0.305545974 */, 17 }, - - /* 2832 */ { MAD_F(0x04e41b14) /* 0.305689888 */, 17 }, - /* 2833 */ { MAD_F(0x04e4b200) /* 0.305833818 */, 17 }, - /* 2834 */ { MAD_F(0x04e548f1) /* 0.305977765 */, 17 }, - /* 2835 */ { MAD_F(0x04e5dfe6) /* 0.306121729 */, 17 }, - /* 2836 */ { MAD_F(0x04e676df) /* 0.306265710 */, 17 }, - /* 2837 */ { MAD_F(0x04e70dde) /* 0.306409708 */, 17 }, - /* 2838 */ { MAD_F(0x04e7a4e0) /* 0.306553723 */, 17 }, - /* 2839 */ { MAD_F(0x04e83be7) /* 0.306697755 */, 17 }, - /* 2840 */ { MAD_F(0x04e8d2f3) /* 0.306841804 */, 17 }, - /* 2841 */ { MAD_F(0x04e96a04) /* 0.306985869 */, 17 }, - /* 2842 */ { MAD_F(0x04ea0118) /* 0.307129952 */, 17 }, - /* 2843 */ { MAD_F(0x04ea9832) /* 0.307274051 */, 17 }, - /* 2844 */ { MAD_F(0x04eb2f50) /* 0.307418168 */, 17 }, - /* 2845 */ { MAD_F(0x04ebc672) /* 0.307562301 */, 17 }, - /* 2846 */ { MAD_F(0x04ec5d99) /* 0.307706451 */, 17 }, - /* 2847 */ { MAD_F(0x04ecf4c5) /* 0.307850618 */, 17 }, - - /* 2848 */ { MAD_F(0x04ed8bf5) /* 0.307994802 */, 17 }, - /* 2849 */ { MAD_F(0x04ee2329) /* 0.308139003 */, 17 }, - /* 2850 */ { MAD_F(0x04eeba63) /* 0.308283220 */, 17 }, - /* 2851 */ { MAD_F(0x04ef51a0) /* 0.308427455 */, 17 }, - /* 2852 */ { MAD_F(0x04efe8e2) /* 0.308571706 */, 17 }, - /* 2853 */ { MAD_F(0x04f08029) /* 0.308715974 */, 17 }, - /* 2854 */ { MAD_F(0x04f11774) /* 0.308860260 */, 17 }, - /* 2855 */ { MAD_F(0x04f1aec4) /* 0.309004561 */, 17 }, - /* 2856 */ { MAD_F(0x04f24618) /* 0.309148880 */, 17 }, - /* 2857 */ { MAD_F(0x04f2dd71) /* 0.309293216 */, 17 }, - /* 2858 */ { MAD_F(0x04f374cf) /* 0.309437568 */, 17 }, - /* 2859 */ { MAD_F(0x04f40c30) /* 0.309581938 */, 17 }, - /* 2860 */ { MAD_F(0x04f4a397) /* 0.309726324 */, 17 }, - /* 2861 */ { MAD_F(0x04f53b02) /* 0.309870727 */, 17 }, - /* 2862 */ { MAD_F(0x04f5d271) /* 0.310015147 */, 17 }, - /* 2863 */ { MAD_F(0x04f669e5) /* 0.310159583 */, 17 }, - - /* 2864 */ { MAD_F(0x04f7015d) /* 0.310304037 */, 17 }, - /* 2865 */ { MAD_F(0x04f798da) /* 0.310448507 */, 17 }, - /* 2866 */ { MAD_F(0x04f8305c) /* 0.310592994 */, 17 }, - /* 2867 */ { MAD_F(0x04f8c7e2) /* 0.310737498 */, 17 }, - /* 2868 */ { MAD_F(0x04f95f6c) /* 0.310882018 */, 17 }, - /* 2869 */ { MAD_F(0x04f9f6fb) /* 0.311026556 */, 17 }, - /* 2870 */ { MAD_F(0x04fa8e8f) /* 0.311171110 */, 17 }, - /* 2871 */ { MAD_F(0x04fb2627) /* 0.311315681 */, 17 }, - /* 2872 */ { MAD_F(0x04fbbdc3) /* 0.311460269 */, 17 }, - /* 2873 */ { MAD_F(0x04fc5564) /* 0.311604874 */, 17 }, - /* 2874 */ { MAD_F(0x04fced0a) /* 0.311749495 */, 17 }, - /* 2875 */ { MAD_F(0x04fd84b4) /* 0.311894133 */, 17 }, - /* 2876 */ { MAD_F(0x04fe1c62) /* 0.312038788 */, 17 }, - /* 2877 */ { MAD_F(0x04feb415) /* 0.312183460 */, 17 }, - /* 2878 */ { MAD_F(0x04ff4bcd) /* 0.312328148 */, 17 }, - /* 2879 */ { MAD_F(0x04ffe389) /* 0.312472854 */, 17 }, - - /* 2880 */ { MAD_F(0x05007b49) /* 0.312617576 */, 17 }, - /* 2881 */ { MAD_F(0x0501130e) /* 0.312762314 */, 17 }, - /* 2882 */ { MAD_F(0x0501aad8) /* 0.312907070 */, 17 }, - /* 2883 */ { MAD_F(0x050242a6) /* 0.313051842 */, 17 }, - /* 2884 */ { MAD_F(0x0502da78) /* 0.313196631 */, 17 }, - /* 2885 */ { MAD_F(0x0503724f) /* 0.313341437 */, 17 }, - /* 2886 */ { MAD_F(0x05040a2b) /* 0.313486259 */, 17 }, - /* 2887 */ { MAD_F(0x0504a20b) /* 0.313631098 */, 17 }, - /* 2888 */ { MAD_F(0x050539ef) /* 0.313775954 */, 17 }, - /* 2889 */ { MAD_F(0x0505d1d8) /* 0.313920827 */, 17 }, - /* 2890 */ { MAD_F(0x050669c5) /* 0.314065716 */, 17 }, - /* 2891 */ { MAD_F(0x050701b7) /* 0.314210622 */, 17 }, - /* 2892 */ { MAD_F(0x050799ae) /* 0.314355545 */, 17 }, - /* 2893 */ { MAD_F(0x050831a9) /* 0.314500484 */, 17 }, - /* 2894 */ { MAD_F(0x0508c9a8) /* 0.314645440 */, 17 }, - /* 2895 */ { MAD_F(0x050961ac) /* 0.314790413 */, 17 }, - - /* 2896 */ { MAD_F(0x0509f9b4) /* 0.314935403 */, 17 }, - /* 2897 */ { MAD_F(0x050a91c1) /* 0.315080409 */, 17 }, - /* 2898 */ { MAD_F(0x050b29d2) /* 0.315225432 */, 17 }, - /* 2899 */ { MAD_F(0x050bc1e8) /* 0.315370472 */, 17 }, - /* 2900 */ { MAD_F(0x050c5a02) /* 0.315515528 */, 17 }, - /* 2901 */ { MAD_F(0x050cf221) /* 0.315660601 */, 17 }, - /* 2902 */ { MAD_F(0x050d8a44) /* 0.315805690 */, 17 }, - /* 2903 */ { MAD_F(0x050e226c) /* 0.315950797 */, 17 }, - /* 2904 */ { MAD_F(0x050eba98) /* 0.316095920 */, 17 }, - /* 2905 */ { MAD_F(0x050f52c9) /* 0.316241059 */, 17 }, - /* 2906 */ { MAD_F(0x050feafe) /* 0.316386216 */, 17 }, - /* 2907 */ { MAD_F(0x05108337) /* 0.316531388 */, 17 }, - /* 2908 */ { MAD_F(0x05111b75) /* 0.316676578 */, 17 }, - /* 2909 */ { MAD_F(0x0511b3b8) /* 0.316821784 */, 17 }, - /* 2910 */ { MAD_F(0x05124bff) /* 0.316967007 */, 17 }, - /* 2911 */ { MAD_F(0x0512e44a) /* 0.317112247 */, 17 }, - - /* 2912 */ { MAD_F(0x05137c9a) /* 0.317257503 */, 17 }, - /* 2913 */ { MAD_F(0x051414ee) /* 0.317402775 */, 17 }, - /* 2914 */ { MAD_F(0x0514ad47) /* 0.317548065 */, 17 }, - /* 2915 */ { MAD_F(0x051545a5) /* 0.317693371 */, 17 }, - /* 2916 */ { MAD_F(0x0515de06) /* 0.317838693 */, 17 }, - /* 2917 */ { MAD_F(0x0516766d) /* 0.317984033 */, 17 }, - /* 2918 */ { MAD_F(0x05170ed7) /* 0.318129388 */, 17 }, - /* 2919 */ { MAD_F(0x0517a746) /* 0.318274761 */, 17 }, - /* 2920 */ { MAD_F(0x05183fba) /* 0.318420150 */, 17 }, - /* 2921 */ { MAD_F(0x0518d832) /* 0.318565555 */, 17 }, - /* 2922 */ { MAD_F(0x051970ae) /* 0.318710978 */, 17 }, - /* 2923 */ { MAD_F(0x051a092f) /* 0.318856416 */, 17 }, - /* 2924 */ { MAD_F(0x051aa1b5) /* 0.319001872 */, 17 }, - /* 2925 */ { MAD_F(0x051b3a3f) /* 0.319147344 */, 17 }, - /* 2926 */ { MAD_F(0x051bd2cd) /* 0.319292832 */, 17 }, - /* 2927 */ { MAD_F(0x051c6b60) /* 0.319438338 */, 17 }, - - /* 2928 */ { MAD_F(0x051d03f7) /* 0.319583859 */, 17 }, - /* 2929 */ { MAD_F(0x051d9c92) /* 0.319729398 */, 17 }, - /* 2930 */ { MAD_F(0x051e3532) /* 0.319874952 */, 17 }, - /* 2931 */ { MAD_F(0x051ecdd7) /* 0.320020524 */, 17 }, - /* 2932 */ { MAD_F(0x051f6680) /* 0.320166112 */, 17 }, - /* 2933 */ { MAD_F(0x051fff2d) /* 0.320311716 */, 17 }, - /* 2934 */ { MAD_F(0x052097df) /* 0.320457337 */, 17 }, - /* 2935 */ { MAD_F(0x05213095) /* 0.320602975 */, 17 }, - /* 2936 */ { MAD_F(0x0521c950) /* 0.320748629 */, 17 }, - /* 2937 */ { MAD_F(0x0522620f) /* 0.320894300 */, 17 }, - /* 2938 */ { MAD_F(0x0522fad3) /* 0.321039987 */, 17 }, - /* 2939 */ { MAD_F(0x0523939b) /* 0.321185691 */, 17 }, - /* 2940 */ { MAD_F(0x05242c68) /* 0.321331411 */, 17 }, - /* 2941 */ { MAD_F(0x0524c538) /* 0.321477148 */, 17 }, - /* 2942 */ { MAD_F(0x05255e0e) /* 0.321622901 */, 17 }, - /* 2943 */ { MAD_F(0x0525f6e8) /* 0.321768671 */, 17 }, - - /* 2944 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 17 }, - /* 2945 */ { MAD_F(0x052728a9) /* 0.322060260 */, 17 }, - /* 2946 */ { MAD_F(0x0527c190) /* 0.322206079 */, 17 }, - /* 2947 */ { MAD_F(0x05285a7b) /* 0.322351915 */, 17 }, - /* 2948 */ { MAD_F(0x0528f36b) /* 0.322497768 */, 17 }, - /* 2949 */ { MAD_F(0x05298c5f) /* 0.322643636 */, 17 }, - /* 2950 */ { MAD_F(0x052a2558) /* 0.322789522 */, 17 }, - /* 2951 */ { MAD_F(0x052abe55) /* 0.322935424 */, 17 }, - /* 2952 */ { MAD_F(0x052b5757) /* 0.323081342 */, 17 }, - /* 2953 */ { MAD_F(0x052bf05d) /* 0.323227277 */, 17 }, - /* 2954 */ { MAD_F(0x052c8968) /* 0.323373228 */, 17 }, - /* 2955 */ { MAD_F(0x052d2277) /* 0.323519196 */, 17 }, - /* 2956 */ { MAD_F(0x052dbb8a) /* 0.323665180 */, 17 }, - /* 2957 */ { MAD_F(0x052e54a2) /* 0.323811180 */, 17 }, - /* 2958 */ { MAD_F(0x052eedbe) /* 0.323957197 */, 17 }, - /* 2959 */ { MAD_F(0x052f86de) /* 0.324103231 */, 17 }, - - /* 2960 */ { MAD_F(0x05302003) /* 0.324249281 */, 17 }, - /* 2961 */ { MAD_F(0x0530b92d) /* 0.324395347 */, 17 }, - /* 2962 */ { MAD_F(0x0531525b) /* 0.324541430 */, 17 }, - /* 2963 */ { MAD_F(0x0531eb8d) /* 0.324687530 */, 17 }, - /* 2964 */ { MAD_F(0x053284c4) /* 0.324833646 */, 17 }, - /* 2965 */ { MAD_F(0x05331dff) /* 0.324979778 */, 17 }, - /* 2966 */ { MAD_F(0x0533b73e) /* 0.325125926 */, 17 }, - /* 2967 */ { MAD_F(0x05345082) /* 0.325272091 */, 17 }, - /* 2968 */ { MAD_F(0x0534e9ca) /* 0.325418273 */, 17 }, - /* 2969 */ { MAD_F(0x05358317) /* 0.325564471 */, 17 }, - /* 2970 */ { MAD_F(0x05361c68) /* 0.325710685 */, 17 }, - /* 2971 */ { MAD_F(0x0536b5be) /* 0.325856916 */, 17 }, - /* 2972 */ { MAD_F(0x05374f17) /* 0.326003163 */, 17 }, - /* 2973 */ { MAD_F(0x0537e876) /* 0.326149427 */, 17 }, - /* 2974 */ { MAD_F(0x053881d9) /* 0.326295707 */, 17 }, - /* 2975 */ { MAD_F(0x05391b40) /* 0.326442003 */, 17 }, - - /* 2976 */ { MAD_F(0x0539b4ab) /* 0.326588316 */, 17 }, - /* 2977 */ { MAD_F(0x053a4e1b) /* 0.326734645 */, 17 }, - /* 2978 */ { MAD_F(0x053ae78f) /* 0.326880990 */, 17 }, - /* 2979 */ { MAD_F(0x053b8108) /* 0.327027352 */, 17 }, - /* 2980 */ { MAD_F(0x053c1a85) /* 0.327173730 */, 17 }, - /* 2981 */ { MAD_F(0x053cb407) /* 0.327320125 */, 17 }, - /* 2982 */ { MAD_F(0x053d4d8d) /* 0.327466536 */, 17 }, - /* 2983 */ { MAD_F(0x053de717) /* 0.327612963 */, 17 }, - /* 2984 */ { MAD_F(0x053e80a6) /* 0.327759407 */, 17 }, - /* 2985 */ { MAD_F(0x053f1a39) /* 0.327905867 */, 17 }, - /* 2986 */ { MAD_F(0x053fb3d0) /* 0.328052344 */, 17 }, - /* 2987 */ { MAD_F(0x05404d6c) /* 0.328198837 */, 17 }, - /* 2988 */ { MAD_F(0x0540e70c) /* 0.328345346 */, 17 }, - /* 2989 */ { MAD_F(0x054180b1) /* 0.328491871 */, 17 }, - /* 2990 */ { MAD_F(0x05421a5a) /* 0.328638413 */, 17 }, - /* 2991 */ { MAD_F(0x0542b407) /* 0.328784971 */, 17 }, - - /* 2992 */ { MAD_F(0x05434db9) /* 0.328931546 */, 17 }, - /* 2993 */ { MAD_F(0x0543e76f) /* 0.329078137 */, 17 }, - /* 2994 */ { MAD_F(0x0544812a) /* 0.329224744 */, 17 }, - /* 2995 */ { MAD_F(0x05451ae9) /* 0.329371367 */, 17 }, - /* 2996 */ { MAD_F(0x0545b4ac) /* 0.329518007 */, 17 }, - /* 2997 */ { MAD_F(0x05464e74) /* 0.329664663 */, 17 }, - /* 2998 */ { MAD_F(0x0546e840) /* 0.329811336 */, 17 }, - /* 2999 */ { MAD_F(0x05478211) /* 0.329958024 */, 17 }, - /* 3000 */ { MAD_F(0x05481be5) /* 0.330104730 */, 17 }, - /* 3001 */ { MAD_F(0x0548b5bf) /* 0.330251451 */, 17 }, - /* 3002 */ { MAD_F(0x05494f9c) /* 0.330398189 */, 17 }, - /* 3003 */ { MAD_F(0x0549e97e) /* 0.330544943 */, 17 }, - /* 3004 */ { MAD_F(0x054a8364) /* 0.330691713 */, 17 }, - /* 3005 */ { MAD_F(0x054b1d4f) /* 0.330838499 */, 17 }, - /* 3006 */ { MAD_F(0x054bb73e) /* 0.330985302 */, 17 }, - /* 3007 */ { MAD_F(0x054c5132) /* 0.331132121 */, 17 }, - - /* 3008 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 17 }, - /* 3009 */ { MAD_F(0x054d8526) /* 0.331425808 */, 17 }, - /* 3010 */ { MAD_F(0x054e1f26) /* 0.331572676 */, 17 }, - /* 3011 */ { MAD_F(0x054eb92b) /* 0.331719560 */, 17 }, - /* 3012 */ { MAD_F(0x054f5334) /* 0.331866461 */, 17 }, - /* 3013 */ { MAD_F(0x054fed42) /* 0.332013377 */, 17 }, - /* 3014 */ { MAD_F(0x05508754) /* 0.332160310 */, 17 }, - /* 3015 */ { MAD_F(0x0551216b) /* 0.332307260 */, 17 }, - /* 3016 */ { MAD_F(0x0551bb85) /* 0.332454225 */, 17 }, - /* 3017 */ { MAD_F(0x055255a4) /* 0.332601207 */, 17 }, - /* 3018 */ { MAD_F(0x0552efc8) /* 0.332748205 */, 17 }, - /* 3019 */ { MAD_F(0x055389f0) /* 0.332895219 */, 17 }, - /* 3020 */ { MAD_F(0x0554241c) /* 0.333042249 */, 17 }, - /* 3021 */ { MAD_F(0x0554be4c) /* 0.333189296 */, 17 }, - /* 3022 */ { MAD_F(0x05555881) /* 0.333336359 */, 17 }, - /* 3023 */ { MAD_F(0x0555f2ba) /* 0.333483438 */, 17 }, - - /* 3024 */ { MAD_F(0x05568cf8) /* 0.333630533 */, 17 }, - /* 3025 */ { MAD_F(0x0557273a) /* 0.333777645 */, 17 }, - /* 3026 */ { MAD_F(0x0557c180) /* 0.333924772 */, 17 }, - /* 3027 */ { MAD_F(0x05585bcb) /* 0.334071916 */, 17 }, - /* 3028 */ { MAD_F(0x0558f61a) /* 0.334219076 */, 17 }, - /* 3029 */ { MAD_F(0x0559906d) /* 0.334366253 */, 17 }, - /* 3030 */ { MAD_F(0x055a2ac5) /* 0.334513445 */, 17 }, - /* 3031 */ { MAD_F(0x055ac521) /* 0.334660654 */, 17 }, - /* 3032 */ { MAD_F(0x055b5f81) /* 0.334807879 */, 17 }, - /* 3033 */ { MAD_F(0x055bf9e6) /* 0.334955120 */, 17 }, - /* 3034 */ { MAD_F(0x055c944f) /* 0.335102377 */, 17 }, - /* 3035 */ { MAD_F(0x055d2ebd) /* 0.335249651 */, 17 }, - /* 3036 */ { MAD_F(0x055dc92e) /* 0.335396941 */, 17 }, - /* 3037 */ { MAD_F(0x055e63a5) /* 0.335544246 */, 17 }, - /* 3038 */ { MAD_F(0x055efe1f) /* 0.335691568 */, 17 }, - /* 3039 */ { MAD_F(0x055f989e) /* 0.335838906 */, 17 }, - - /* 3040 */ { MAD_F(0x05603321) /* 0.335986261 */, 17 }, - /* 3041 */ { MAD_F(0x0560cda8) /* 0.336133631 */, 17 }, - /* 3042 */ { MAD_F(0x05616834) /* 0.336281018 */, 17 }, - /* 3043 */ { MAD_F(0x056202c4) /* 0.336428421 */, 17 }, - /* 3044 */ { MAD_F(0x05629d59) /* 0.336575840 */, 17 }, - /* 3045 */ { MAD_F(0x056337f2) /* 0.336723275 */, 17 }, - /* 3046 */ { MAD_F(0x0563d28f) /* 0.336870726 */, 17 }, - /* 3047 */ { MAD_F(0x05646d30) /* 0.337018193 */, 17 }, - /* 3048 */ { MAD_F(0x056507d6) /* 0.337165677 */, 17 }, - /* 3049 */ { MAD_F(0x0565a280) /* 0.337313176 */, 17 }, - /* 3050 */ { MAD_F(0x05663d2f) /* 0.337460692 */, 17 }, - /* 3051 */ { MAD_F(0x0566d7e1) /* 0.337608224 */, 17 }, - /* 3052 */ { MAD_F(0x05677298) /* 0.337755772 */, 17 }, - /* 3053 */ { MAD_F(0x05680d54) /* 0.337903336 */, 17 }, - /* 3054 */ { MAD_F(0x0568a814) /* 0.338050916 */, 17 }, - /* 3055 */ { MAD_F(0x056942d8) /* 0.338198513 */, 17 }, - - /* 3056 */ { MAD_F(0x0569dda0) /* 0.338346125 */, 17 }, - /* 3057 */ { MAD_F(0x056a786d) /* 0.338493753 */, 17 }, - /* 3058 */ { MAD_F(0x056b133e) /* 0.338641398 */, 17 }, - /* 3059 */ { MAD_F(0x056bae13) /* 0.338789059 */, 17 }, - /* 3060 */ { MAD_F(0x056c48ed) /* 0.338936736 */, 17 }, - /* 3061 */ { MAD_F(0x056ce3cb) /* 0.339084429 */, 17 }, - /* 3062 */ { MAD_F(0x056d7ead) /* 0.339232138 */, 17 }, - /* 3063 */ { MAD_F(0x056e1994) /* 0.339379863 */, 17 }, - /* 3064 */ { MAD_F(0x056eb47f) /* 0.339527604 */, 17 }, - /* 3065 */ { MAD_F(0x056f4f6e) /* 0.339675361 */, 17 }, - /* 3066 */ { MAD_F(0x056fea62) /* 0.339823134 */, 17 }, - /* 3067 */ { MAD_F(0x0570855a) /* 0.339970924 */, 17 }, - /* 3068 */ { MAD_F(0x05712056) /* 0.340118729 */, 17 }, - /* 3069 */ { MAD_F(0x0571bb56) /* 0.340266550 */, 17 }, - /* 3070 */ { MAD_F(0x0572565b) /* 0.340414388 */, 17 }, - /* 3071 */ { MAD_F(0x0572f164) /* 0.340562242 */, 17 }, - - /* 3072 */ { MAD_F(0x05738c72) /* 0.340710111 */, 17 }, - /* 3073 */ { MAD_F(0x05742784) /* 0.340857997 */, 17 }, - /* 3074 */ { MAD_F(0x0574c29a) /* 0.341005899 */, 17 }, - /* 3075 */ { MAD_F(0x05755db4) /* 0.341153816 */, 17 }, - /* 3076 */ { MAD_F(0x0575f8d3) /* 0.341301750 */, 17 }, - /* 3077 */ { MAD_F(0x057693f6) /* 0.341449700 */, 17 }, - /* 3078 */ { MAD_F(0x05772f1d) /* 0.341597666 */, 17 }, - /* 3079 */ { MAD_F(0x0577ca49) /* 0.341745648 */, 17 }, - /* 3080 */ { MAD_F(0x05786578) /* 0.341893646 */, 17 }, - /* 3081 */ { MAD_F(0x057900ad) /* 0.342041659 */, 17 }, - /* 3082 */ { MAD_F(0x05799be5) /* 0.342189689 */, 17 }, - /* 3083 */ { MAD_F(0x057a3722) /* 0.342337735 */, 17 }, - /* 3084 */ { MAD_F(0x057ad263) /* 0.342485797 */, 17 }, - /* 3085 */ { MAD_F(0x057b6da8) /* 0.342633875 */, 17 }, - /* 3086 */ { MAD_F(0x057c08f2) /* 0.342781969 */, 17 }, - /* 3087 */ { MAD_F(0x057ca440) /* 0.342930079 */, 17 }, - - /* 3088 */ { MAD_F(0x057d3f92) /* 0.343078205 */, 17 }, - /* 3089 */ { MAD_F(0x057ddae9) /* 0.343226347 */, 17 }, - /* 3090 */ { MAD_F(0x057e7644) /* 0.343374505 */, 17 }, - /* 3091 */ { MAD_F(0x057f11a3) /* 0.343522679 */, 17 }, - /* 3092 */ { MAD_F(0x057fad06) /* 0.343670869 */, 17 }, - /* 3093 */ { MAD_F(0x0580486e) /* 0.343819075 */, 17 }, - /* 3094 */ { MAD_F(0x0580e3da) /* 0.343967296 */, 17 }, - /* 3095 */ { MAD_F(0x05817f4a) /* 0.344115534 */, 17 }, - /* 3096 */ { MAD_F(0x05821abf) /* 0.344263788 */, 17 }, - /* 3097 */ { MAD_F(0x0582b638) /* 0.344412058 */, 17 }, - /* 3098 */ { MAD_F(0x058351b5) /* 0.344560343 */, 17 }, - /* 3099 */ { MAD_F(0x0583ed36) /* 0.344708645 */, 17 }, - /* 3100 */ { MAD_F(0x058488bc) /* 0.344856963 */, 17 }, - /* 3101 */ { MAD_F(0x05852446) /* 0.345005296 */, 17 }, - /* 3102 */ { MAD_F(0x0585bfd4) /* 0.345153646 */, 17 }, - /* 3103 */ { MAD_F(0x05865b67) /* 0.345302011 */, 17 }, - - /* 3104 */ { MAD_F(0x0586f6fd) /* 0.345450393 */, 17 }, - /* 3105 */ { MAD_F(0x05879298) /* 0.345598790 */, 17 }, - /* 3106 */ { MAD_F(0x05882e38) /* 0.345747203 */, 17 }, - /* 3107 */ { MAD_F(0x0588c9dc) /* 0.345895632 */, 17 }, - /* 3108 */ { MAD_F(0x05896583) /* 0.346044077 */, 17 }, - /* 3109 */ { MAD_F(0x058a0130) /* 0.346192538 */, 17 }, - /* 3110 */ { MAD_F(0x058a9ce0) /* 0.346341015 */, 17 }, - /* 3111 */ { MAD_F(0x058b3895) /* 0.346489508 */, 17 }, - /* 3112 */ { MAD_F(0x058bd44e) /* 0.346638017 */, 17 }, - /* 3113 */ { MAD_F(0x058c700b) /* 0.346786542 */, 17 }, - /* 3114 */ { MAD_F(0x058d0bcd) /* 0.346935082 */, 17 }, - /* 3115 */ { MAD_F(0x058da793) /* 0.347083639 */, 17 }, - /* 3116 */ { MAD_F(0x058e435d) /* 0.347232211 */, 17 }, - /* 3117 */ { MAD_F(0x058edf2b) /* 0.347380799 */, 17 }, - /* 3118 */ { MAD_F(0x058f7afe) /* 0.347529403 */, 17 }, - /* 3119 */ { MAD_F(0x059016d5) /* 0.347678023 */, 17 }, - - /* 3120 */ { MAD_F(0x0590b2b0) /* 0.347826659 */, 17 }, - /* 3121 */ { MAD_F(0x05914e8f) /* 0.347975311 */, 17 }, - /* 3122 */ { MAD_F(0x0591ea73) /* 0.348123979 */, 17 }, - /* 3123 */ { MAD_F(0x0592865b) /* 0.348272662 */, 17 }, - /* 3124 */ { MAD_F(0x05932247) /* 0.348421362 */, 17 }, - /* 3125 */ { MAD_F(0x0593be37) /* 0.348570077 */, 17 }, - /* 3126 */ { MAD_F(0x05945a2c) /* 0.348718808 */, 17 }, - /* 3127 */ { MAD_F(0x0594f625) /* 0.348867555 */, 17 }, - /* 3128 */ { MAD_F(0x05959222) /* 0.349016318 */, 17 }, - /* 3129 */ { MAD_F(0x05962e24) /* 0.349165097 */, 17 }, - /* 3130 */ { MAD_F(0x0596ca2a) /* 0.349313892 */, 17 }, - /* 3131 */ { MAD_F(0x05976634) /* 0.349462702 */, 17 }, - /* 3132 */ { MAD_F(0x05980242) /* 0.349611528 */, 17 }, - /* 3133 */ { MAD_F(0x05989e54) /* 0.349760370 */, 17 }, - /* 3134 */ { MAD_F(0x05993a6b) /* 0.349909228 */, 17 }, - /* 3135 */ { MAD_F(0x0599d686) /* 0.350058102 */, 17 }, - - /* 3136 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 17 }, - /* 3137 */ { MAD_F(0x059b0ec9) /* 0.350355897 */, 17 }, - /* 3138 */ { MAD_F(0x059baaf1) /* 0.350504818 */, 17 }, - /* 3139 */ { MAD_F(0x059c471d) /* 0.350653756 */, 17 }, - /* 3140 */ { MAD_F(0x059ce34d) /* 0.350802708 */, 17 }, - /* 3141 */ { MAD_F(0x059d7f81) /* 0.350951677 */, 17 }, - /* 3142 */ { MAD_F(0x059e1bba) /* 0.351100662 */, 17 }, - /* 3143 */ { MAD_F(0x059eb7f7) /* 0.351249662 */, 17 }, - /* 3144 */ { MAD_F(0x059f5438) /* 0.351398678 */, 17 }, - /* 3145 */ { MAD_F(0x059ff07e) /* 0.351547710 */, 17 }, - /* 3146 */ { MAD_F(0x05a08cc7) /* 0.351696758 */, 17 }, - /* 3147 */ { MAD_F(0x05a12915) /* 0.351845821 */, 17 }, - /* 3148 */ { MAD_F(0x05a1c567) /* 0.351994901 */, 17 }, - /* 3149 */ { MAD_F(0x05a261be) /* 0.352143996 */, 17 }, - /* 3150 */ { MAD_F(0x05a2fe18) /* 0.352293107 */, 17 }, - /* 3151 */ { MAD_F(0x05a39a77) /* 0.352442233 */, 17 }, - - /* 3152 */ { MAD_F(0x05a436da) /* 0.352591376 */, 17 }, - /* 3153 */ { MAD_F(0x05a4d342) /* 0.352740534 */, 17 }, - /* 3154 */ { MAD_F(0x05a56fad) /* 0.352889708 */, 17 }, - /* 3155 */ { MAD_F(0x05a60c1d) /* 0.353038898 */, 17 }, - /* 3156 */ { MAD_F(0x05a6a891) /* 0.353188103 */, 17 }, - /* 3157 */ { MAD_F(0x05a7450a) /* 0.353337325 */, 17 }, - /* 3158 */ { MAD_F(0x05a7e186) /* 0.353486562 */, 17 }, - /* 3159 */ { MAD_F(0x05a87e07) /* 0.353635814 */, 17 }, - /* 3160 */ { MAD_F(0x05a91a8c) /* 0.353785083 */, 17 }, - /* 3161 */ { MAD_F(0x05a9b715) /* 0.353934367 */, 17 }, - /* 3162 */ { MAD_F(0x05aa53a2) /* 0.354083667 */, 17 }, - /* 3163 */ { MAD_F(0x05aaf034) /* 0.354232983 */, 17 }, - /* 3164 */ { MAD_F(0x05ab8cca) /* 0.354382314 */, 17 }, - /* 3165 */ { MAD_F(0x05ac2964) /* 0.354531662 */, 17 }, - /* 3166 */ { MAD_F(0x05acc602) /* 0.354681025 */, 17 }, - /* 3167 */ { MAD_F(0x05ad62a5) /* 0.354830403 */, 17 }, - - /* 3168 */ { MAD_F(0x05adff4c) /* 0.354979798 */, 17 }, - /* 3169 */ { MAD_F(0x05ae9bf7) /* 0.355129208 */, 17 }, - /* 3170 */ { MAD_F(0x05af38a6) /* 0.355278634 */, 17 }, - /* 3171 */ { MAD_F(0x05afd559) /* 0.355428075 */, 17 }, - /* 3172 */ { MAD_F(0x05b07211) /* 0.355577533 */, 17 }, - /* 3173 */ { MAD_F(0x05b10ecd) /* 0.355727006 */, 17 }, - /* 3174 */ { MAD_F(0x05b1ab8d) /* 0.355876494 */, 17 }, - /* 3175 */ { MAD_F(0x05b24851) /* 0.356025999 */, 17 }, - /* 3176 */ { MAD_F(0x05b2e51a) /* 0.356175519 */, 17 }, - /* 3177 */ { MAD_F(0x05b381e6) /* 0.356325054 */, 17 }, - /* 3178 */ { MAD_F(0x05b41eb7) /* 0.356474606 */, 17 }, - /* 3179 */ { MAD_F(0x05b4bb8c) /* 0.356624173 */, 17 }, - /* 3180 */ { MAD_F(0x05b55866) /* 0.356773756 */, 17 }, - /* 3181 */ { MAD_F(0x05b5f543) /* 0.356923354 */, 17 }, - /* 3182 */ { MAD_F(0x05b69225) /* 0.357072969 */, 17 }, - /* 3183 */ { MAD_F(0x05b72f0b) /* 0.357222598 */, 17 }, - - /* 3184 */ { MAD_F(0x05b7cbf5) /* 0.357372244 */, 17 }, - /* 3185 */ { MAD_F(0x05b868e3) /* 0.357521905 */, 17 }, - /* 3186 */ { MAD_F(0x05b905d6) /* 0.357671582 */, 17 }, - /* 3187 */ { MAD_F(0x05b9a2cd) /* 0.357821275 */, 17 }, - /* 3188 */ { MAD_F(0x05ba3fc8) /* 0.357970983 */, 17 }, - /* 3189 */ { MAD_F(0x05badcc7) /* 0.358120707 */, 17 }, - /* 3190 */ { MAD_F(0x05bb79ca) /* 0.358270446 */, 17 }, - /* 3191 */ { MAD_F(0x05bc16d2) /* 0.358420201 */, 17 }, - /* 3192 */ { MAD_F(0x05bcb3de) /* 0.358569972 */, 17 }, - /* 3193 */ { MAD_F(0x05bd50ee) /* 0.358719758 */, 17 }, - /* 3194 */ { MAD_F(0x05bdee02) /* 0.358869560 */, 17 }, - /* 3195 */ { MAD_F(0x05be8b1a) /* 0.359019378 */, 17 }, - /* 3196 */ { MAD_F(0x05bf2837) /* 0.359169211 */, 17 }, - /* 3197 */ { MAD_F(0x05bfc558) /* 0.359319060 */, 17 }, - /* 3198 */ { MAD_F(0x05c0627d) /* 0.359468925 */, 17 }, - /* 3199 */ { MAD_F(0x05c0ffa6) /* 0.359618805 */, 17 }, - - /* 3200 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 17 }, - /* 3201 */ { MAD_F(0x05c23a05) /* 0.359918612 */, 17 }, - /* 3202 */ { MAD_F(0x05c2d73a) /* 0.360068540 */, 17 }, - /* 3203 */ { MAD_F(0x05c37474) /* 0.360218482 */, 17 }, - /* 3204 */ { MAD_F(0x05c411b2) /* 0.360368440 */, 17 }, - /* 3205 */ { MAD_F(0x05c4aef5) /* 0.360518414 */, 17 }, - /* 3206 */ { MAD_F(0x05c54c3b) /* 0.360668404 */, 17 }, - /* 3207 */ { MAD_F(0x05c5e986) /* 0.360818409 */, 17 }, - /* 3208 */ { MAD_F(0x05c686d5) /* 0.360968429 */, 17 }, - /* 3209 */ { MAD_F(0x05c72428) /* 0.361118466 */, 17 }, - /* 3210 */ { MAD_F(0x05c7c17f) /* 0.361268517 */, 17 }, - /* 3211 */ { MAD_F(0x05c85eda) /* 0.361418585 */, 17 }, - /* 3212 */ { MAD_F(0x05c8fc3a) /* 0.361568668 */, 17 }, - /* 3213 */ { MAD_F(0x05c9999e) /* 0.361718766 */, 17 }, - /* 3214 */ { MAD_F(0x05ca3706) /* 0.361868881 */, 17 }, - /* 3215 */ { MAD_F(0x05cad472) /* 0.362019010 */, 17 }, - - /* 3216 */ { MAD_F(0x05cb71e2) /* 0.362169156 */, 17 }, - /* 3217 */ { MAD_F(0x05cc0f57) /* 0.362319316 */, 17 }, - /* 3218 */ { MAD_F(0x05ccaccf) /* 0.362469493 */, 17 }, - /* 3219 */ { MAD_F(0x05cd4a4c) /* 0.362619685 */, 17 }, - /* 3220 */ { MAD_F(0x05cde7cd) /* 0.362769892 */, 17 }, - /* 3221 */ { MAD_F(0x05ce8552) /* 0.362920115 */, 17 }, - /* 3222 */ { MAD_F(0x05cf22dc) /* 0.363070354 */, 17 }, - /* 3223 */ { MAD_F(0x05cfc069) /* 0.363220608 */, 17 }, - /* 3224 */ { MAD_F(0x05d05dfb) /* 0.363370878 */, 17 }, - /* 3225 */ { MAD_F(0x05d0fb91) /* 0.363521163 */, 17 }, - /* 3226 */ { MAD_F(0x05d1992b) /* 0.363671464 */, 17 }, - /* 3227 */ { MAD_F(0x05d236c9) /* 0.363821780 */, 17 }, - /* 3228 */ { MAD_F(0x05d2d46c) /* 0.363972112 */, 17 }, - /* 3229 */ { MAD_F(0x05d37212) /* 0.364122459 */, 17 }, - /* 3230 */ { MAD_F(0x05d40fbd) /* 0.364272822 */, 17 }, - /* 3231 */ { MAD_F(0x05d4ad6c) /* 0.364423200 */, 17 }, - - /* 3232 */ { MAD_F(0x05d54b1f) /* 0.364573594 */, 17 }, - /* 3233 */ { MAD_F(0x05d5e8d6) /* 0.364724004 */, 17 }, - /* 3234 */ { MAD_F(0x05d68691) /* 0.364874429 */, 17 }, - /* 3235 */ { MAD_F(0x05d72451) /* 0.365024869 */, 17 }, - /* 3236 */ { MAD_F(0x05d7c215) /* 0.365175325 */, 17 }, - /* 3237 */ { MAD_F(0x05d85fdc) /* 0.365325796 */, 17 }, - /* 3238 */ { MAD_F(0x05d8fda8) /* 0.365476283 */, 17 }, - /* 3239 */ { MAD_F(0x05d99b79) /* 0.365626786 */, 17 }, - /* 3240 */ { MAD_F(0x05da394d) /* 0.365777304 */, 17 }, - /* 3241 */ { MAD_F(0x05dad726) /* 0.365927837 */, 17 }, - /* 3242 */ { MAD_F(0x05db7502) /* 0.366078386 */, 17 }, - /* 3243 */ { MAD_F(0x05dc12e3) /* 0.366228950 */, 17 }, - /* 3244 */ { MAD_F(0x05dcb0c8) /* 0.366379530 */, 17 }, - /* 3245 */ { MAD_F(0x05dd4eb1) /* 0.366530125 */, 17 }, - /* 3246 */ { MAD_F(0x05ddec9e) /* 0.366680736 */, 17 }, - /* 3247 */ { MAD_F(0x05de8a90) /* 0.366831362 */, 17 }, - - /* 3248 */ { MAD_F(0x05df2885) /* 0.366982004 */, 17 }, - /* 3249 */ { MAD_F(0x05dfc67f) /* 0.367132661 */, 17 }, - /* 3250 */ { MAD_F(0x05e0647d) /* 0.367283334 */, 17 }, - /* 3251 */ { MAD_F(0x05e1027f) /* 0.367434022 */, 17 }, - /* 3252 */ { MAD_F(0x05e1a085) /* 0.367584725 */, 17 }, - /* 3253 */ { MAD_F(0x05e23e8f) /* 0.367735444 */, 17 }, - /* 3254 */ { MAD_F(0x05e2dc9e) /* 0.367886179 */, 17 }, - /* 3255 */ { MAD_F(0x05e37ab0) /* 0.368036929 */, 17 }, - /* 3256 */ { MAD_F(0x05e418c7) /* 0.368187694 */, 17 }, - /* 3257 */ { MAD_F(0x05e4b6e2) /* 0.368338475 */, 17 }, - /* 3258 */ { MAD_F(0x05e55501) /* 0.368489271 */, 17 }, - /* 3259 */ { MAD_F(0x05e5f324) /* 0.368640082 */, 17 }, - /* 3260 */ { MAD_F(0x05e6914c) /* 0.368790909 */, 17 }, - /* 3261 */ { MAD_F(0x05e72f77) /* 0.368941752 */, 17 }, - /* 3262 */ { MAD_F(0x05e7cda7) /* 0.369092610 */, 17 }, - /* 3263 */ { MAD_F(0x05e86bda) /* 0.369243483 */, 17 }, - - /* 3264 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 17 }, - /* 3265 */ { MAD_F(0x05e9a84e) /* 0.369545276 */, 17 }, - /* 3266 */ { MAD_F(0x05ea468e) /* 0.369696195 */, 17 }, - /* 3267 */ { MAD_F(0x05eae4d3) /* 0.369847130 */, 17 }, - /* 3268 */ { MAD_F(0x05eb831b) /* 0.369998080 */, 17 }, - /* 3269 */ { MAD_F(0x05ec2168) /* 0.370149046 */, 17 }, - /* 3270 */ { MAD_F(0x05ecbfb8) /* 0.370300027 */, 17 }, - /* 3271 */ { MAD_F(0x05ed5e0d) /* 0.370451024 */, 17 }, - /* 3272 */ { MAD_F(0x05edfc66) /* 0.370602036 */, 17 }, - /* 3273 */ { MAD_F(0x05ee9ac3) /* 0.370753063 */, 17 }, - /* 3274 */ { MAD_F(0x05ef3924) /* 0.370904105 */, 17 }, - /* 3275 */ { MAD_F(0x05efd78a) /* 0.371055163 */, 17 }, - /* 3276 */ { MAD_F(0x05f075f3) /* 0.371206237 */, 17 }, - /* 3277 */ { MAD_F(0x05f11461) /* 0.371357326 */, 17 }, - /* 3278 */ { MAD_F(0x05f1b2d3) /* 0.371508430 */, 17 }, - /* 3279 */ { MAD_F(0x05f25148) /* 0.371659549 */, 17 }, - - /* 3280 */ { MAD_F(0x05f2efc2) /* 0.371810684 */, 17 }, - /* 3281 */ { MAD_F(0x05f38e40) /* 0.371961834 */, 17 }, - /* 3282 */ { MAD_F(0x05f42cc3) /* 0.372113000 */, 17 }, - /* 3283 */ { MAD_F(0x05f4cb49) /* 0.372264181 */, 17 }, - /* 3284 */ { MAD_F(0x05f569d3) /* 0.372415377 */, 17 }, - /* 3285 */ { MAD_F(0x05f60862) /* 0.372566589 */, 17 }, - /* 3286 */ { MAD_F(0x05f6a6f5) /* 0.372717816 */, 17 }, - /* 3287 */ { MAD_F(0x05f7458b) /* 0.372869058 */, 17 }, - /* 3288 */ { MAD_F(0x05f7e426) /* 0.373020316 */, 17 }, - /* 3289 */ { MAD_F(0x05f882c5) /* 0.373171589 */, 17 }, - /* 3290 */ { MAD_F(0x05f92169) /* 0.373322877 */, 17 }, - /* 3291 */ { MAD_F(0x05f9c010) /* 0.373474181 */, 17 }, - /* 3292 */ { MAD_F(0x05fa5ebb) /* 0.373625500 */, 17 }, - /* 3293 */ { MAD_F(0x05fafd6b) /* 0.373776834 */, 17 }, - /* 3294 */ { MAD_F(0x05fb9c1e) /* 0.373928184 */, 17 }, - /* 3295 */ { MAD_F(0x05fc3ad6) /* 0.374079549 */, 17 }, - - /* 3296 */ { MAD_F(0x05fcd992) /* 0.374230929 */, 17 }, - /* 3297 */ { MAD_F(0x05fd7852) /* 0.374382325 */, 17 }, - /* 3298 */ { MAD_F(0x05fe1716) /* 0.374533735 */, 17 }, - /* 3299 */ { MAD_F(0x05feb5de) /* 0.374685162 */, 17 }, - /* 3300 */ { MAD_F(0x05ff54aa) /* 0.374836603 */, 17 }, - /* 3301 */ { MAD_F(0x05fff37b) /* 0.374988060 */, 17 }, - /* 3302 */ { MAD_F(0x0600924f) /* 0.375139532 */, 17 }, - /* 3303 */ { MAD_F(0x06013128) /* 0.375291019 */, 17 }, - /* 3304 */ { MAD_F(0x0601d004) /* 0.375442522 */, 17 }, - /* 3305 */ { MAD_F(0x06026ee5) /* 0.375594040 */, 17 }, - /* 3306 */ { MAD_F(0x06030dca) /* 0.375745573 */, 17 }, - /* 3307 */ { MAD_F(0x0603acb3) /* 0.375897122 */, 17 }, - /* 3308 */ { MAD_F(0x06044ba0) /* 0.376048685 */, 17 }, - /* 3309 */ { MAD_F(0x0604ea91) /* 0.376200265 */, 17 }, - /* 3310 */ { MAD_F(0x06058987) /* 0.376351859 */, 17 }, - /* 3311 */ { MAD_F(0x06062880) /* 0.376503468 */, 17 }, - - /* 3312 */ { MAD_F(0x0606c77d) /* 0.376655093 */, 17 }, - /* 3313 */ { MAD_F(0x0607667f) /* 0.376806733 */, 17 }, - /* 3314 */ { MAD_F(0x06080585) /* 0.376958389 */, 17 }, - /* 3315 */ { MAD_F(0x0608a48f) /* 0.377110059 */, 17 }, - /* 3316 */ { MAD_F(0x0609439c) /* 0.377261745 */, 17 }, - /* 3317 */ { MAD_F(0x0609e2ae) /* 0.377413446 */, 17 }, - /* 3318 */ { MAD_F(0x060a81c4) /* 0.377565163 */, 17 }, - /* 3319 */ { MAD_F(0x060b20df) /* 0.377716894 */, 17 }, - /* 3320 */ { MAD_F(0x060bbffd) /* 0.377868641 */, 17 }, - /* 3321 */ { MAD_F(0x060c5f1f) /* 0.378020403 */, 17 }, - /* 3322 */ { MAD_F(0x060cfe46) /* 0.378172181 */, 17 }, - /* 3323 */ { MAD_F(0x060d9d70) /* 0.378323973 */, 17 }, - /* 3324 */ { MAD_F(0x060e3c9f) /* 0.378475781 */, 17 }, - /* 3325 */ { MAD_F(0x060edbd1) /* 0.378627604 */, 17 }, - /* 3326 */ { MAD_F(0x060f7b08) /* 0.378779442 */, 17 }, - /* 3327 */ { MAD_F(0x06101a43) /* 0.378931296 */, 17 }, - - /* 3328 */ { MAD_F(0x0610b982) /* 0.379083164 */, 17 }, - /* 3329 */ { MAD_F(0x061158c5) /* 0.379235048 */, 17 }, - /* 3330 */ { MAD_F(0x0611f80c) /* 0.379386947 */, 17 }, - /* 3331 */ { MAD_F(0x06129757) /* 0.379538862 */, 17 }, - /* 3332 */ { MAD_F(0x061336a6) /* 0.379690791 */, 17 }, - /* 3333 */ { MAD_F(0x0613d5fa) /* 0.379842736 */, 17 }, - /* 3334 */ { MAD_F(0x06147551) /* 0.379994696 */, 17 }, - /* 3335 */ { MAD_F(0x061514ad) /* 0.380146671 */, 17 }, - /* 3336 */ { MAD_F(0x0615b40c) /* 0.380298661 */, 17 }, - /* 3337 */ { MAD_F(0x06165370) /* 0.380450666 */, 17 }, - /* 3338 */ { MAD_F(0x0616f2d8) /* 0.380602687 */, 17 }, - /* 3339 */ { MAD_F(0x06179243) /* 0.380754723 */, 17 }, - /* 3340 */ { MAD_F(0x061831b3) /* 0.380906774 */, 17 }, - /* 3341 */ { MAD_F(0x0618d127) /* 0.381058840 */, 17 }, - /* 3342 */ { MAD_F(0x0619709f) /* 0.381210921 */, 17 }, - /* 3343 */ { MAD_F(0x061a101b) /* 0.381363018 */, 17 }, - - /* 3344 */ { MAD_F(0x061aaf9c) /* 0.381515130 */, 17 }, - /* 3345 */ { MAD_F(0x061b4f20) /* 0.381667257 */, 17 }, - /* 3346 */ { MAD_F(0x061beea8) /* 0.381819399 */, 17 }, - /* 3347 */ { MAD_F(0x061c8e34) /* 0.381971556 */, 17 }, - /* 3348 */ { MAD_F(0x061d2dc5) /* 0.382123728 */, 17 }, - /* 3349 */ { MAD_F(0x061dcd59) /* 0.382275916 */, 17 }, - /* 3350 */ { MAD_F(0x061e6cf2) /* 0.382428118 */, 17 }, - /* 3351 */ { MAD_F(0x061f0c8f) /* 0.382580336 */, 17 }, - /* 3352 */ { MAD_F(0x061fac2f) /* 0.382732569 */, 17 }, - /* 3353 */ { MAD_F(0x06204bd4) /* 0.382884817 */, 17 }, - /* 3354 */ { MAD_F(0x0620eb7d) /* 0.383037080 */, 17 }, - /* 3355 */ { MAD_F(0x06218b2a) /* 0.383189358 */, 17 }, - /* 3356 */ { MAD_F(0x06222adb) /* 0.383341652 */, 17 }, - /* 3357 */ { MAD_F(0x0622ca90) /* 0.383493960 */, 17 }, - /* 3358 */ { MAD_F(0x06236a49) /* 0.383646284 */, 17 }, - /* 3359 */ { MAD_F(0x06240a06) /* 0.383798623 */, 17 }, - - /* 3360 */ { MAD_F(0x0624a9c7) /* 0.383950977 */, 17 }, - /* 3361 */ { MAD_F(0x0625498d) /* 0.384103346 */, 17 }, - /* 3362 */ { MAD_F(0x0625e956) /* 0.384255730 */, 17 }, - /* 3363 */ { MAD_F(0x06268923) /* 0.384408129 */, 17 }, - /* 3364 */ { MAD_F(0x062728f5) /* 0.384560544 */, 17 }, - /* 3365 */ { MAD_F(0x0627c8ca) /* 0.384712973 */, 17 }, - /* 3366 */ { MAD_F(0x062868a4) /* 0.384865418 */, 17 }, - /* 3367 */ { MAD_F(0x06290881) /* 0.385017878 */, 17 }, - /* 3368 */ { MAD_F(0x0629a863) /* 0.385170352 */, 17 }, - /* 3369 */ { MAD_F(0x062a4849) /* 0.385322842 */, 17 }, - /* 3370 */ { MAD_F(0x062ae832) /* 0.385475347 */, 17 }, - /* 3371 */ { MAD_F(0x062b8820) /* 0.385627867 */, 17 }, - /* 3372 */ { MAD_F(0x062c2812) /* 0.385780402 */, 17 }, - /* 3373 */ { MAD_F(0x062cc808) /* 0.385932953 */, 17 }, - /* 3374 */ { MAD_F(0x062d6802) /* 0.386085518 */, 17 }, - /* 3375 */ { MAD_F(0x062e0800) /* 0.386238098 */, 17 }, - - /* 3376 */ { MAD_F(0x062ea802) /* 0.386390694 */, 17 }, - /* 3377 */ { MAD_F(0x062f4808) /* 0.386543304 */, 17 }, - /* 3378 */ { MAD_F(0x062fe812) /* 0.386695930 */, 17 }, - /* 3379 */ { MAD_F(0x06308820) /* 0.386848570 */, 17 }, - /* 3380 */ { MAD_F(0x06312832) /* 0.387001226 */, 17 }, - /* 3381 */ { MAD_F(0x0631c849) /* 0.387153897 */, 17 }, - /* 3382 */ { MAD_F(0x06326863) /* 0.387306582 */, 17 }, - /* 3383 */ { MAD_F(0x06330881) /* 0.387459283 */, 17 }, - /* 3384 */ { MAD_F(0x0633a8a3) /* 0.387611999 */, 17 }, - /* 3385 */ { MAD_F(0x063448ca) /* 0.387764730 */, 17 }, - /* 3386 */ { MAD_F(0x0634e8f4) /* 0.387917476 */, 17 }, - /* 3387 */ { MAD_F(0x06358923) /* 0.388070237 */, 17 }, - /* 3388 */ { MAD_F(0x06362955) /* 0.388223013 */, 17 }, - /* 3389 */ { MAD_F(0x0636c98c) /* 0.388375804 */, 17 }, - /* 3390 */ { MAD_F(0x063769c6) /* 0.388528610 */, 17 }, - /* 3391 */ { MAD_F(0x06380a05) /* 0.388681431 */, 17 }, - - /* 3392 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 17 }, - /* 3393 */ { MAD_F(0x06394a8e) /* 0.388987119 */, 17 }, - /* 3394 */ { MAD_F(0x0639ead9) /* 0.389139985 */, 17 }, - /* 3395 */ { MAD_F(0x063a8b28) /* 0.389292866 */, 17 }, - /* 3396 */ { MAD_F(0x063b2b7b) /* 0.389445762 */, 17 }, - /* 3397 */ { MAD_F(0x063bcbd1) /* 0.389598674 */, 17 }, - /* 3398 */ { MAD_F(0x063c6c2c) /* 0.389751600 */, 17 }, - /* 3399 */ { MAD_F(0x063d0c8b) /* 0.389904541 */, 17 }, - /* 3400 */ { MAD_F(0x063dacee) /* 0.390057497 */, 17 }, - /* 3401 */ { MAD_F(0x063e4d55) /* 0.390210468 */, 17 }, - /* 3402 */ { MAD_F(0x063eedc0) /* 0.390363455 */, 17 }, - /* 3403 */ { MAD_F(0x063f8e2f) /* 0.390516456 */, 17 }, - /* 3404 */ { MAD_F(0x06402ea2) /* 0.390669472 */, 17 }, - /* 3405 */ { MAD_F(0x0640cf19) /* 0.390822503 */, 17 }, - /* 3406 */ { MAD_F(0x06416f94) /* 0.390975549 */, 17 }, - /* 3407 */ { MAD_F(0x06421013) /* 0.391128611 */, 17 }, - - /* 3408 */ { MAD_F(0x0642b096) /* 0.391281687 */, 17 }, - /* 3409 */ { MAD_F(0x0643511d) /* 0.391434778 */, 17 }, - /* 3410 */ { MAD_F(0x0643f1a8) /* 0.391587884 */, 17 }, - /* 3411 */ { MAD_F(0x06449237) /* 0.391741005 */, 17 }, - /* 3412 */ { MAD_F(0x064532ca) /* 0.391894141 */, 17 }, - /* 3413 */ { MAD_F(0x0645d361) /* 0.392047292 */, 17 }, - /* 3414 */ { MAD_F(0x064673fc) /* 0.392200458 */, 17 }, - /* 3415 */ { MAD_F(0x0647149c) /* 0.392353638 */, 17 }, - /* 3416 */ { MAD_F(0x0647b53f) /* 0.392506834 */, 17 }, - /* 3417 */ { MAD_F(0x064855e6) /* 0.392660045 */, 17 }, - /* 3418 */ { MAD_F(0x0648f691) /* 0.392813271 */, 17 }, - /* 3419 */ { MAD_F(0x06499740) /* 0.392966511 */, 17 }, - /* 3420 */ { MAD_F(0x064a37f4) /* 0.393119767 */, 17 }, - /* 3421 */ { MAD_F(0x064ad8ab) /* 0.393273038 */, 17 }, - /* 3422 */ { MAD_F(0x064b7966) /* 0.393426323 */, 17 }, - /* 3423 */ { MAD_F(0x064c1a25) /* 0.393579623 */, 17 }, - - /* 3424 */ { MAD_F(0x064cbae9) /* 0.393732939 */, 17 }, - /* 3425 */ { MAD_F(0x064d5bb0) /* 0.393886269 */, 17 }, - /* 3426 */ { MAD_F(0x064dfc7b) /* 0.394039614 */, 17 }, - /* 3427 */ { MAD_F(0x064e9d4b) /* 0.394192974 */, 17 }, - /* 3428 */ { MAD_F(0x064f3e1e) /* 0.394346349 */, 17 }, - /* 3429 */ { MAD_F(0x064fdef5) /* 0.394499739 */, 17 }, - /* 3430 */ { MAD_F(0x06507fd0) /* 0.394653144 */, 17 }, - /* 3431 */ { MAD_F(0x065120b0) /* 0.394806564 */, 17 }, - /* 3432 */ { MAD_F(0x0651c193) /* 0.394959999 */, 17 }, - /* 3433 */ { MAD_F(0x0652627a) /* 0.395113448 */, 17 }, - /* 3434 */ { MAD_F(0x06530366) /* 0.395266913 */, 17 }, - /* 3435 */ { MAD_F(0x0653a455) /* 0.395420392 */, 17 }, - /* 3436 */ { MAD_F(0x06544548) /* 0.395573886 */, 17 }, - /* 3437 */ { MAD_F(0x0654e640) /* 0.395727395 */, 17 }, - /* 3438 */ { MAD_F(0x0655873b) /* 0.395880919 */, 17 }, - /* 3439 */ { MAD_F(0x0656283a) /* 0.396034458 */, 17 }, - - /* 3440 */ { MAD_F(0x0656c93d) /* 0.396188012 */, 17 }, - /* 3441 */ { MAD_F(0x06576a45) /* 0.396341581 */, 17 }, - /* 3442 */ { MAD_F(0x06580b50) /* 0.396495164 */, 17 }, - /* 3443 */ { MAD_F(0x0658ac5f) /* 0.396648763 */, 17 }, - /* 3444 */ { MAD_F(0x06594d73) /* 0.396802376 */, 17 }, - /* 3445 */ { MAD_F(0x0659ee8a) /* 0.396956004 */, 17 }, - /* 3446 */ { MAD_F(0x065a8fa5) /* 0.397109647 */, 17 }, - /* 3447 */ { MAD_F(0x065b30c4) /* 0.397263305 */, 17 }, - /* 3448 */ { MAD_F(0x065bd1e7) /* 0.397416978 */, 17 }, - /* 3449 */ { MAD_F(0x065c730f) /* 0.397570666 */, 17 }, - /* 3450 */ { MAD_F(0x065d143a) /* 0.397724368 */, 17 }, - /* 3451 */ { MAD_F(0x065db569) /* 0.397878085 */, 17 }, - /* 3452 */ { MAD_F(0x065e569c) /* 0.398031818 */, 17 }, - /* 3453 */ { MAD_F(0x065ef7d3) /* 0.398185565 */, 17 }, - /* 3454 */ { MAD_F(0x065f990e) /* 0.398339326 */, 17 }, - /* 3455 */ { MAD_F(0x06603a4e) /* 0.398493103 */, 17 }, - - /* 3456 */ { MAD_F(0x0660db91) /* 0.398646895 */, 17 }, - /* 3457 */ { MAD_F(0x06617cd8) /* 0.398800701 */, 17 }, - /* 3458 */ { MAD_F(0x06621e23) /* 0.398954522 */, 17 }, - /* 3459 */ { MAD_F(0x0662bf72) /* 0.399108358 */, 17 }, - /* 3460 */ { MAD_F(0x066360c5) /* 0.399262209 */, 17 }, - /* 3461 */ { MAD_F(0x0664021c) /* 0.399416075 */, 17 }, - /* 3462 */ { MAD_F(0x0664a377) /* 0.399569955 */, 17 }, - /* 3463 */ { MAD_F(0x066544d6) /* 0.399723851 */, 17 }, - /* 3464 */ { MAD_F(0x0665e639) /* 0.399877761 */, 17 }, - /* 3465 */ { MAD_F(0x066687a0) /* 0.400031686 */, 17 }, - /* 3466 */ { MAD_F(0x0667290b) /* 0.400185625 */, 17 }, - /* 3467 */ { MAD_F(0x0667ca79) /* 0.400339580 */, 17 }, - /* 3468 */ { MAD_F(0x06686bec) /* 0.400493549 */, 17 }, - /* 3469 */ { MAD_F(0x06690d63) /* 0.400647534 */, 17 }, - /* 3470 */ { MAD_F(0x0669aede) /* 0.400801533 */, 17 }, - /* 3471 */ { MAD_F(0x066a505d) /* 0.400955546 */, 17 }, - - /* 3472 */ { MAD_F(0x066af1df) /* 0.401109575 */, 17 }, - /* 3473 */ { MAD_F(0x066b9366) /* 0.401263618 */, 17 }, - /* 3474 */ { MAD_F(0x066c34f1) /* 0.401417676 */, 17 }, - /* 3475 */ { MAD_F(0x066cd67f) /* 0.401571749 */, 17 }, - /* 3476 */ { MAD_F(0x066d7812) /* 0.401725837 */, 17 }, - /* 3477 */ { MAD_F(0x066e19a9) /* 0.401879939 */, 17 }, - /* 3478 */ { MAD_F(0x066ebb43) /* 0.402034056 */, 17 }, - /* 3479 */ { MAD_F(0x066f5ce2) /* 0.402188188 */, 17 }, - /* 3480 */ { MAD_F(0x066ffe84) /* 0.402342335 */, 17 }, - /* 3481 */ { MAD_F(0x0670a02a) /* 0.402496497 */, 17 }, - /* 3482 */ { MAD_F(0x067141d5) /* 0.402650673 */, 17 }, - /* 3483 */ { MAD_F(0x0671e383) /* 0.402804864 */, 17 }, - /* 3484 */ { MAD_F(0x06728535) /* 0.402959070 */, 17 }, - /* 3485 */ { MAD_F(0x067326ec) /* 0.403113291 */, 17 }, - /* 3486 */ { MAD_F(0x0673c8a6) /* 0.403267526 */, 17 }, - /* 3487 */ { MAD_F(0x06746a64) /* 0.403421776 */, 17 }, - - /* 3488 */ { MAD_F(0x06750c26) /* 0.403576041 */, 17 }, - /* 3489 */ { MAD_F(0x0675adec) /* 0.403730320 */, 17 }, - /* 3490 */ { MAD_F(0x06764fb6) /* 0.403884615 */, 17 }, - /* 3491 */ { MAD_F(0x0676f184) /* 0.404038924 */, 17 }, - /* 3492 */ { MAD_F(0x06779356) /* 0.404193247 */, 17 }, - /* 3493 */ { MAD_F(0x0678352c) /* 0.404347586 */, 17 }, - /* 3494 */ { MAD_F(0x0678d706) /* 0.404501939 */, 17 }, - /* 3495 */ { MAD_F(0x067978e4) /* 0.404656307 */, 17 }, - /* 3496 */ { MAD_F(0x067a1ac6) /* 0.404810690 */, 17 }, - /* 3497 */ { MAD_F(0x067abcac) /* 0.404965087 */, 17 }, - /* 3498 */ { MAD_F(0x067b5e95) /* 0.405119499 */, 17 }, - /* 3499 */ { MAD_F(0x067c0083) /* 0.405273926 */, 17 }, - /* 3500 */ { MAD_F(0x067ca275) /* 0.405428368 */, 17 }, - /* 3501 */ { MAD_F(0x067d446a) /* 0.405582824 */, 17 }, - /* 3502 */ { MAD_F(0x067de664) /* 0.405737295 */, 17 }, - /* 3503 */ { MAD_F(0x067e8861) /* 0.405891781 */, 17 }, - - /* 3504 */ { MAD_F(0x067f2a62) /* 0.406046281 */, 17 }, - /* 3505 */ { MAD_F(0x067fcc68) /* 0.406200796 */, 17 }, - /* 3506 */ { MAD_F(0x06806e71) /* 0.406355326 */, 17 }, - /* 3507 */ { MAD_F(0x0681107e) /* 0.406509870 */, 17 }, - /* 3508 */ { MAD_F(0x0681b28f) /* 0.406664429 */, 17 }, - /* 3509 */ { MAD_F(0x068254a4) /* 0.406819003 */, 17 }, - /* 3510 */ { MAD_F(0x0682f6bd) /* 0.406973592 */, 17 }, - /* 3511 */ { MAD_F(0x068398da) /* 0.407128195 */, 17 }, - /* 3512 */ { MAD_F(0x06843afb) /* 0.407282813 */, 17 }, - /* 3513 */ { MAD_F(0x0684dd20) /* 0.407437445 */, 17 }, - /* 3514 */ { MAD_F(0x06857f49) /* 0.407592093 */, 17 }, - /* 3515 */ { MAD_F(0x06862176) /* 0.407746754 */, 17 }, - /* 3516 */ { MAD_F(0x0686c3a6) /* 0.407901431 */, 17 }, - /* 3517 */ { MAD_F(0x068765db) /* 0.408056122 */, 17 }, - /* 3518 */ { MAD_F(0x06880814) /* 0.408210828 */, 17 }, - /* 3519 */ { MAD_F(0x0688aa50) /* 0.408365549 */, 17 }, - - /* 3520 */ { MAD_F(0x06894c90) /* 0.408520284 */, 17 }, - /* 3521 */ { MAD_F(0x0689eed5) /* 0.408675034 */, 17 }, - /* 3522 */ { MAD_F(0x068a911d) /* 0.408829798 */, 17 }, - /* 3523 */ { MAD_F(0x068b3369) /* 0.408984577 */, 17 }, - /* 3524 */ { MAD_F(0x068bd5b9) /* 0.409139371 */, 17 }, - /* 3525 */ { MAD_F(0x068c780e) /* 0.409294180 */, 17 }, - /* 3526 */ { MAD_F(0x068d1a66) /* 0.409449003 */, 17 }, - /* 3527 */ { MAD_F(0x068dbcc1) /* 0.409603840 */, 17 }, - /* 3528 */ { MAD_F(0x068e5f21) /* 0.409758693 */, 17 }, - /* 3529 */ { MAD_F(0x068f0185) /* 0.409913560 */, 17 }, - /* 3530 */ { MAD_F(0x068fa3ed) /* 0.410068441 */, 17 }, - /* 3531 */ { MAD_F(0x06904658) /* 0.410223338 */, 17 }, - /* 3532 */ { MAD_F(0x0690e8c8) /* 0.410378249 */, 17 }, - /* 3533 */ { MAD_F(0x06918b3c) /* 0.410533174 */, 17 }, - /* 3534 */ { MAD_F(0x06922db3) /* 0.410688114 */, 17 }, - /* 3535 */ { MAD_F(0x0692d02e) /* 0.410843069 */, 17 }, - - /* 3536 */ { MAD_F(0x069372ae) /* 0.410998038 */, 17 }, - /* 3537 */ { MAD_F(0x06941531) /* 0.411153022 */, 17 }, - /* 3538 */ { MAD_F(0x0694b7b8) /* 0.411308021 */, 17 }, - /* 3539 */ { MAD_F(0x06955a43) /* 0.411463034 */, 17 }, - /* 3540 */ { MAD_F(0x0695fcd2) /* 0.411618062 */, 17 }, - /* 3541 */ { MAD_F(0x06969f65) /* 0.411773104 */, 17 }, - /* 3542 */ { MAD_F(0x069741fb) /* 0.411928161 */, 17 }, - /* 3543 */ { MAD_F(0x0697e496) /* 0.412083232 */, 17 }, - /* 3544 */ { MAD_F(0x06988735) /* 0.412238319 */, 17 }, - /* 3545 */ { MAD_F(0x069929d7) /* 0.412393419 */, 17 }, - /* 3546 */ { MAD_F(0x0699cc7e) /* 0.412548535 */, 17 }, - /* 3547 */ { MAD_F(0x069a6f28) /* 0.412703664 */, 17 }, - /* 3548 */ { MAD_F(0x069b11d6) /* 0.412858809 */, 17 }, - /* 3549 */ { MAD_F(0x069bb489) /* 0.413013968 */, 17 }, - /* 3550 */ { MAD_F(0x069c573f) /* 0.413169142 */, 17 }, - /* 3551 */ { MAD_F(0x069cf9f9) /* 0.413324330 */, 17 }, - - /* 3552 */ { MAD_F(0x069d9cb7) /* 0.413479532 */, 17 }, - /* 3553 */ { MAD_F(0x069e3f78) /* 0.413634750 */, 17 }, - /* 3554 */ { MAD_F(0x069ee23e) /* 0.413789982 */, 17 }, - /* 3555 */ { MAD_F(0x069f8508) /* 0.413945228 */, 17 }, - /* 3556 */ { MAD_F(0x06a027d5) /* 0.414100489 */, 17 }, - /* 3557 */ { MAD_F(0x06a0caa7) /* 0.414255765 */, 17 }, - /* 3558 */ { MAD_F(0x06a16d7c) /* 0.414411055 */, 17 }, - /* 3559 */ { MAD_F(0x06a21055) /* 0.414566359 */, 17 }, - /* 3560 */ { MAD_F(0x06a2b333) /* 0.414721679 */, 17 }, - /* 3561 */ { MAD_F(0x06a35614) /* 0.414877012 */, 17 }, - /* 3562 */ { MAD_F(0x06a3f8f9) /* 0.415032361 */, 17 }, - /* 3563 */ { MAD_F(0x06a49be2) /* 0.415187723 */, 17 }, - /* 3564 */ { MAD_F(0x06a53ece) /* 0.415343101 */, 17 }, - /* 3565 */ { MAD_F(0x06a5e1bf) /* 0.415498493 */, 17 }, - /* 3566 */ { MAD_F(0x06a684b4) /* 0.415653899 */, 17 }, - /* 3567 */ { MAD_F(0x06a727ac) /* 0.415809320 */, 17 }, - - /* 3568 */ { MAD_F(0x06a7caa9) /* 0.415964756 */, 17 }, - /* 3569 */ { MAD_F(0x06a86da9) /* 0.416120206 */, 17 }, - /* 3570 */ { MAD_F(0x06a910ad) /* 0.416275670 */, 17 }, - /* 3571 */ { MAD_F(0x06a9b3b5) /* 0.416431149 */, 17 }, - /* 3572 */ { MAD_F(0x06aa56c1) /* 0.416586643 */, 17 }, - /* 3573 */ { MAD_F(0x06aaf9d1) /* 0.416742151 */, 17 }, - /* 3574 */ { MAD_F(0x06ab9ce5) /* 0.416897673 */, 17 }, - /* 3575 */ { MAD_F(0x06ac3ffc) /* 0.417053210 */, 17 }, - /* 3576 */ { MAD_F(0x06ace318) /* 0.417208762 */, 17 }, - /* 3577 */ { MAD_F(0x06ad8637) /* 0.417364328 */, 17 }, - /* 3578 */ { MAD_F(0x06ae295b) /* 0.417519909 */, 17 }, - /* 3579 */ { MAD_F(0x06aecc82) /* 0.417675504 */, 17 }, - /* 3580 */ { MAD_F(0x06af6fad) /* 0.417831113 */, 17 }, - /* 3581 */ { MAD_F(0x06b012dc) /* 0.417986737 */, 17 }, - /* 3582 */ { MAD_F(0x06b0b60f) /* 0.418142376 */, 17 }, - /* 3583 */ { MAD_F(0x06b15946) /* 0.418298029 */, 17 }, - - /* 3584 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 17 }, - /* 3585 */ { MAD_F(0x06b29fbf) /* 0.418609378 */, 17 }, - /* 3586 */ { MAD_F(0x06b34302) /* 0.418765075 */, 17 }, - /* 3587 */ { MAD_F(0x06b3e648) /* 0.418920786 */, 17 }, - /* 3588 */ { MAD_F(0x06b48992) /* 0.419076511 */, 17 }, - /* 3589 */ { MAD_F(0x06b52ce0) /* 0.419232251 */, 17 }, - /* 3590 */ { MAD_F(0x06b5d032) /* 0.419388005 */, 17 }, - /* 3591 */ { MAD_F(0x06b67388) /* 0.419543774 */, 17 }, - /* 3592 */ { MAD_F(0x06b716e2) /* 0.419699557 */, 17 }, - /* 3593 */ { MAD_F(0x06b7ba3f) /* 0.419855355 */, 17 }, - /* 3594 */ { MAD_F(0x06b85da1) /* 0.420011167 */, 17 }, - /* 3595 */ { MAD_F(0x06b90106) /* 0.420166994 */, 17 }, - /* 3596 */ { MAD_F(0x06b9a470) /* 0.420322835 */, 17 }, - /* 3597 */ { MAD_F(0x06ba47dd) /* 0.420478690 */, 17 }, - /* 3598 */ { MAD_F(0x06baeb4e) /* 0.420634560 */, 17 }, - /* 3599 */ { MAD_F(0x06bb8ec3) /* 0.420790445 */, 17 }, - - /* 3600 */ { MAD_F(0x06bc323b) /* 0.420946343 */, 17 }, - /* 3601 */ { MAD_F(0x06bcd5b8) /* 0.421102257 */, 17 }, - /* 3602 */ { MAD_F(0x06bd7939) /* 0.421258184 */, 17 }, - /* 3603 */ { MAD_F(0x06be1cbd) /* 0.421414127 */, 17 }, - /* 3604 */ { MAD_F(0x06bec045) /* 0.421570083 */, 17 }, - /* 3605 */ { MAD_F(0x06bf63d1) /* 0.421726054 */, 17 }, - /* 3606 */ { MAD_F(0x06c00761) /* 0.421882040 */, 17 }, - /* 3607 */ { MAD_F(0x06c0aaf5) /* 0.422038039 */, 17 }, - /* 3608 */ { MAD_F(0x06c14e8d) /* 0.422194054 */, 17 }, - /* 3609 */ { MAD_F(0x06c1f229) /* 0.422350082 */, 17 }, - /* 3610 */ { MAD_F(0x06c295c8) /* 0.422506125 */, 17 }, - /* 3611 */ { MAD_F(0x06c3396c) /* 0.422662183 */, 17 }, - /* 3612 */ { MAD_F(0x06c3dd13) /* 0.422818255 */, 17 }, - /* 3613 */ { MAD_F(0x06c480be) /* 0.422974341 */, 17 }, - /* 3614 */ { MAD_F(0x06c5246d) /* 0.423130442 */, 17 }, - /* 3615 */ { MAD_F(0x06c5c820) /* 0.423286557 */, 17 }, - - /* 3616 */ { MAD_F(0x06c66bd6) /* 0.423442686 */, 17 }, - /* 3617 */ { MAD_F(0x06c70f91) /* 0.423598830 */, 17 }, - /* 3618 */ { MAD_F(0x06c7b34f) /* 0.423754988 */, 17 }, - /* 3619 */ { MAD_F(0x06c85712) /* 0.423911161 */, 17 }, - /* 3620 */ { MAD_F(0x06c8fad8) /* 0.424067348 */, 17 }, - /* 3621 */ { MAD_F(0x06c99ea2) /* 0.424223550 */, 17 }, - /* 3622 */ { MAD_F(0x06ca4270) /* 0.424379765 */, 17 }, - /* 3623 */ { MAD_F(0x06cae641) /* 0.424535996 */, 17 }, - /* 3624 */ { MAD_F(0x06cb8a17) /* 0.424692240 */, 17 }, - /* 3625 */ { MAD_F(0x06cc2df0) /* 0.424848499 */, 17 }, - /* 3626 */ { MAD_F(0x06ccd1ce) /* 0.425004772 */, 17 }, - /* 3627 */ { MAD_F(0x06cd75af) /* 0.425161060 */, 17 }, - /* 3628 */ { MAD_F(0x06ce1994) /* 0.425317362 */, 17 }, - /* 3629 */ { MAD_F(0x06cebd7d) /* 0.425473678 */, 17 }, - /* 3630 */ { MAD_F(0x06cf6169) /* 0.425630009 */, 17 }, - /* 3631 */ { MAD_F(0x06d0055a) /* 0.425786354 */, 17 }, - - /* 3632 */ { MAD_F(0x06d0a94e) /* 0.425942714 */, 17 }, - /* 3633 */ { MAD_F(0x06d14d47) /* 0.426099088 */, 17 }, - /* 3634 */ { MAD_F(0x06d1f143) /* 0.426255476 */, 17 }, - /* 3635 */ { MAD_F(0x06d29543) /* 0.426411878 */, 17 }, - /* 3636 */ { MAD_F(0x06d33947) /* 0.426568295 */, 17 }, - /* 3637 */ { MAD_F(0x06d3dd4e) /* 0.426724726 */, 17 }, - /* 3638 */ { MAD_F(0x06d4815a) /* 0.426881172 */, 17 }, - /* 3639 */ { MAD_F(0x06d52569) /* 0.427037632 */, 17 }, - /* 3640 */ { MAD_F(0x06d5c97c) /* 0.427194106 */, 17 }, - /* 3641 */ { MAD_F(0x06d66d93) /* 0.427350594 */, 17 }, - /* 3642 */ { MAD_F(0x06d711ae) /* 0.427507097 */, 17 }, - /* 3643 */ { MAD_F(0x06d7b5cd) /* 0.427663614 */, 17 }, - /* 3644 */ { MAD_F(0x06d859f0) /* 0.427820146 */, 17 }, - /* 3645 */ { MAD_F(0x06d8fe16) /* 0.427976692 */, 17 }, - /* 3646 */ { MAD_F(0x06d9a240) /* 0.428133252 */, 17 }, - /* 3647 */ { MAD_F(0x06da466f) /* 0.428289826 */, 17 }, - - /* 3648 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 17 }, - /* 3649 */ { MAD_F(0x06db8ed6) /* 0.428603018 */, 17 }, - /* 3650 */ { MAD_F(0x06dc3310) /* 0.428759635 */, 17 }, - /* 3651 */ { MAD_F(0x06dcd74d) /* 0.428916267 */, 17 }, - /* 3652 */ { MAD_F(0x06dd7b8f) /* 0.429072913 */, 17 }, - /* 3653 */ { MAD_F(0x06de1fd4) /* 0.429229573 */, 17 }, - /* 3654 */ { MAD_F(0x06dec41d) /* 0.429386248 */, 17 }, - /* 3655 */ { MAD_F(0x06df686a) /* 0.429542937 */, 17 }, - /* 3656 */ { MAD_F(0x06e00cbb) /* 0.429699640 */, 17 }, - /* 3657 */ { MAD_F(0x06e0b10f) /* 0.429856357 */, 17 }, - /* 3658 */ { MAD_F(0x06e15567) /* 0.430013089 */, 17 }, - /* 3659 */ { MAD_F(0x06e1f9c4) /* 0.430169835 */, 17 }, - /* 3660 */ { MAD_F(0x06e29e24) /* 0.430326595 */, 17 }, - /* 3661 */ { MAD_F(0x06e34287) /* 0.430483370 */, 17 }, - /* 3662 */ { MAD_F(0x06e3e6ef) /* 0.430640159 */, 17 }, - /* 3663 */ { MAD_F(0x06e48b5b) /* 0.430796962 */, 17 }, - - /* 3664 */ { MAD_F(0x06e52fca) /* 0.430953779 */, 17 }, - /* 3665 */ { MAD_F(0x06e5d43d) /* 0.431110611 */, 17 }, - /* 3666 */ { MAD_F(0x06e678b4) /* 0.431267457 */, 17 }, - /* 3667 */ { MAD_F(0x06e71d2f) /* 0.431424317 */, 17 }, - /* 3668 */ { MAD_F(0x06e7c1ae) /* 0.431581192 */, 17 }, - /* 3669 */ { MAD_F(0x06e86630) /* 0.431738080 */, 17 }, - /* 3670 */ { MAD_F(0x06e90ab7) /* 0.431894983 */, 17 }, - /* 3671 */ { MAD_F(0x06e9af41) /* 0.432051900 */, 17 }, - /* 3672 */ { MAD_F(0x06ea53cf) /* 0.432208832 */, 17 }, - /* 3673 */ { MAD_F(0x06eaf860) /* 0.432365778 */, 17 }, - /* 3674 */ { MAD_F(0x06eb9cf6) /* 0.432522737 */, 17 }, - /* 3675 */ { MAD_F(0x06ec418f) /* 0.432679712 */, 17 }, - /* 3676 */ { MAD_F(0x06ece62d) /* 0.432836700 */, 17 }, - /* 3677 */ { MAD_F(0x06ed8ace) /* 0.432993703 */, 17 }, - /* 3678 */ { MAD_F(0x06ee2f73) /* 0.433150720 */, 17 }, - /* 3679 */ { MAD_F(0x06eed41b) /* 0.433307751 */, 17 }, - - /* 3680 */ { MAD_F(0x06ef78c8) /* 0.433464796 */, 17 }, - /* 3681 */ { MAD_F(0x06f01d78) /* 0.433621856 */, 17 }, - /* 3682 */ { MAD_F(0x06f0c22c) /* 0.433778929 */, 17 }, - /* 3683 */ { MAD_F(0x06f166e4) /* 0.433936017 */, 17 }, - /* 3684 */ { MAD_F(0x06f20ba0) /* 0.434093120 */, 17 }, - /* 3685 */ { MAD_F(0x06f2b060) /* 0.434250236 */, 17 }, - /* 3686 */ { MAD_F(0x06f35523) /* 0.434407367 */, 17 }, - /* 3687 */ { MAD_F(0x06f3f9eb) /* 0.434564512 */, 17 }, - /* 3688 */ { MAD_F(0x06f49eb6) /* 0.434721671 */, 17 }, - /* 3689 */ { MAD_F(0x06f54385) /* 0.434878844 */, 17 }, - /* 3690 */ { MAD_F(0x06f5e857) /* 0.435036032 */, 17 }, - /* 3691 */ { MAD_F(0x06f68d2e) /* 0.435193233 */, 17 }, - /* 3692 */ { MAD_F(0x06f73208) /* 0.435350449 */, 17 }, - /* 3693 */ { MAD_F(0x06f7d6e6) /* 0.435507679 */, 17 }, - /* 3694 */ { MAD_F(0x06f87bc8) /* 0.435664924 */, 17 }, - /* 3695 */ { MAD_F(0x06f920ae) /* 0.435822182 */, 17 }, - - /* 3696 */ { MAD_F(0x06f9c597) /* 0.435979455 */, 17 }, - /* 3697 */ { MAD_F(0x06fa6a85) /* 0.436136741 */, 17 }, - /* 3698 */ { MAD_F(0x06fb0f76) /* 0.436294042 */, 17 }, - /* 3699 */ { MAD_F(0x06fbb46b) /* 0.436451358 */, 17 }, - /* 3700 */ { MAD_F(0x06fc5964) /* 0.436608687 */, 17 }, - /* 3701 */ { MAD_F(0x06fcfe60) /* 0.436766031 */, 17 }, - /* 3702 */ { MAD_F(0x06fda361) /* 0.436923388 */, 17 }, - /* 3703 */ { MAD_F(0x06fe4865) /* 0.437080760 */, 17 }, - /* 3704 */ { MAD_F(0x06feed6d) /* 0.437238146 */, 17 }, - /* 3705 */ { MAD_F(0x06ff9279) /* 0.437395547 */, 17 }, - /* 3706 */ { MAD_F(0x07003788) /* 0.437552961 */, 17 }, - /* 3707 */ { MAD_F(0x0700dc9c) /* 0.437710389 */, 17 }, - /* 3708 */ { MAD_F(0x070181b3) /* 0.437867832 */, 17 }, - /* 3709 */ { MAD_F(0x070226ce) /* 0.438025289 */, 17 }, - /* 3710 */ { MAD_F(0x0702cbed) /* 0.438182760 */, 17 }, - /* 3711 */ { MAD_F(0x0703710f) /* 0.438340245 */, 17 }, - - /* 3712 */ { MAD_F(0x07041636) /* 0.438497744 */, 17 }, - /* 3713 */ { MAD_F(0x0704bb60) /* 0.438655258 */, 17 }, - /* 3714 */ { MAD_F(0x0705608e) /* 0.438812785 */, 17 }, - /* 3715 */ { MAD_F(0x070605c0) /* 0.438970327 */, 17 }, - /* 3716 */ { MAD_F(0x0706aaf5) /* 0.439127883 */, 17 }, - /* 3717 */ { MAD_F(0x0707502f) /* 0.439285453 */, 17 }, - /* 3718 */ { MAD_F(0x0707f56c) /* 0.439443037 */, 17 }, - /* 3719 */ { MAD_F(0x07089aad) /* 0.439600635 */, 17 }, - /* 3720 */ { MAD_F(0x07093ff2) /* 0.439758248 */, 17 }, - /* 3721 */ { MAD_F(0x0709e53a) /* 0.439915874 */, 17 }, - /* 3722 */ { MAD_F(0x070a8a86) /* 0.440073515 */, 17 }, - /* 3723 */ { MAD_F(0x070b2fd7) /* 0.440231170 */, 17 }, - /* 3724 */ { MAD_F(0x070bd52a) /* 0.440388839 */, 17 }, - /* 3725 */ { MAD_F(0x070c7a82) /* 0.440546522 */, 17 }, - /* 3726 */ { MAD_F(0x070d1fde) /* 0.440704219 */, 17 }, - /* 3727 */ { MAD_F(0x070dc53d) /* 0.440861930 */, 17 }, - - /* 3728 */ { MAD_F(0x070e6aa0) /* 0.441019655 */, 17 }, - /* 3729 */ { MAD_F(0x070f1007) /* 0.441177395 */, 17 }, - /* 3730 */ { MAD_F(0x070fb571) /* 0.441335148 */, 17 }, - /* 3731 */ { MAD_F(0x07105ae0) /* 0.441492916 */, 17 }, - /* 3732 */ { MAD_F(0x07110052) /* 0.441650697 */, 17 }, - /* 3733 */ { MAD_F(0x0711a5c8) /* 0.441808493 */, 17 }, - /* 3734 */ { MAD_F(0x07124b42) /* 0.441966303 */, 17 }, - /* 3735 */ { MAD_F(0x0712f0bf) /* 0.442124127 */, 17 }, - /* 3736 */ { MAD_F(0x07139641) /* 0.442281965 */, 17 }, - /* 3737 */ { MAD_F(0x07143bc6) /* 0.442439817 */, 17 }, - /* 3738 */ { MAD_F(0x0714e14f) /* 0.442597683 */, 17 }, - /* 3739 */ { MAD_F(0x071586db) /* 0.442755564 */, 17 }, - /* 3740 */ { MAD_F(0x07162c6c) /* 0.442913458 */, 17 }, - /* 3741 */ { MAD_F(0x0716d200) /* 0.443071366 */, 17 }, - /* 3742 */ { MAD_F(0x07177798) /* 0.443229289 */, 17 }, - /* 3743 */ { MAD_F(0x07181d34) /* 0.443387226 */, 17 }, - - /* 3744 */ { MAD_F(0x0718c2d3) /* 0.443545176 */, 17 }, - /* 3745 */ { MAD_F(0x07196877) /* 0.443703141 */, 17 }, - /* 3746 */ { MAD_F(0x071a0e1e) /* 0.443861120 */, 17 }, - /* 3747 */ { MAD_F(0x071ab3c9) /* 0.444019113 */, 17 }, - /* 3748 */ { MAD_F(0x071b5977) /* 0.444177119 */, 17 }, - /* 3749 */ { MAD_F(0x071bff2a) /* 0.444335140 */, 17 }, - /* 3750 */ { MAD_F(0x071ca4e0) /* 0.444493175 */, 17 }, - /* 3751 */ { MAD_F(0x071d4a9a) /* 0.444651224 */, 17 }, - /* 3752 */ { MAD_F(0x071df058) /* 0.444809288 */, 17 }, - /* 3753 */ { MAD_F(0x071e9619) /* 0.444967365 */, 17 }, - /* 3754 */ { MAD_F(0x071f3bde) /* 0.445125456 */, 17 }, - /* 3755 */ { MAD_F(0x071fe1a8) /* 0.445283561 */, 17 }, - /* 3756 */ { MAD_F(0x07208774) /* 0.445441680 */, 17 }, - /* 3757 */ { MAD_F(0x07212d45) /* 0.445599814 */, 17 }, - /* 3758 */ { MAD_F(0x0721d319) /* 0.445757961 */, 17 }, - /* 3759 */ { MAD_F(0x072278f1) /* 0.445916122 */, 17 }, - - /* 3760 */ { MAD_F(0x07231ecd) /* 0.446074298 */, 17 }, - /* 3761 */ { MAD_F(0x0723c4ad) /* 0.446232487 */, 17 }, - /* 3762 */ { MAD_F(0x07246a90) /* 0.446390690 */, 17 }, - /* 3763 */ { MAD_F(0x07251077) /* 0.446548908 */, 17 }, - /* 3764 */ { MAD_F(0x0725b662) /* 0.446707139 */, 17 }, - /* 3765 */ { MAD_F(0x07265c51) /* 0.446865385 */, 17 }, - /* 3766 */ { MAD_F(0x07270244) /* 0.447023644 */, 17 }, - /* 3767 */ { MAD_F(0x0727a83a) /* 0.447181918 */, 17 }, - /* 3768 */ { MAD_F(0x07284e34) /* 0.447340205 */, 17 }, - /* 3769 */ { MAD_F(0x0728f431) /* 0.447498507 */, 17 }, - /* 3770 */ { MAD_F(0x07299a33) /* 0.447656822 */, 17 }, - /* 3771 */ { MAD_F(0x072a4038) /* 0.447815152 */, 17 }, - /* 3772 */ { MAD_F(0x072ae641) /* 0.447973495 */, 17 }, - /* 3773 */ { MAD_F(0x072b8c4e) /* 0.448131853 */, 17 }, - /* 3774 */ { MAD_F(0x072c325e) /* 0.448290224 */, 17 }, - /* 3775 */ { MAD_F(0x072cd873) /* 0.448448609 */, 17 }, - - /* 3776 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 17 }, - /* 3777 */ { MAD_F(0x072e24a7) /* 0.448765422 */, 17 }, - /* 3778 */ { MAD_F(0x072ecac6) /* 0.448923850 */, 17 }, - /* 3779 */ { MAD_F(0x072f70e9) /* 0.449082291 */, 17 }, - /* 3780 */ { MAD_F(0x07301710) /* 0.449240746 */, 17 }, - /* 3781 */ { MAD_F(0x0730bd3b) /* 0.449399216 */, 17 }, - /* 3782 */ { MAD_F(0x0731636a) /* 0.449557699 */, 17 }, - /* 3783 */ { MAD_F(0x0732099c) /* 0.449716196 */, 17 }, - /* 3784 */ { MAD_F(0x0732afd2) /* 0.449874708 */, 17 }, - /* 3785 */ { MAD_F(0x0733560c) /* 0.450033233 */, 17 }, - /* 3786 */ { MAD_F(0x0733fc49) /* 0.450191772 */, 17 }, - /* 3787 */ { MAD_F(0x0734a28b) /* 0.450350325 */, 17 }, - /* 3788 */ { MAD_F(0x073548d0) /* 0.450508892 */, 17 }, - /* 3789 */ { MAD_F(0x0735ef18) /* 0.450667473 */, 17 }, - /* 3790 */ { MAD_F(0x07369565) /* 0.450826068 */, 17 }, - /* 3791 */ { MAD_F(0x07373bb5) /* 0.450984677 */, 17 }, - - /* 3792 */ { MAD_F(0x0737e209) /* 0.451143300 */, 17 }, - /* 3793 */ { MAD_F(0x07388861) /* 0.451301937 */, 17 }, - /* 3794 */ { MAD_F(0x07392ebc) /* 0.451460588 */, 17 }, - /* 3795 */ { MAD_F(0x0739d51c) /* 0.451619252 */, 17 }, - /* 3796 */ { MAD_F(0x073a7b7f) /* 0.451777931 */, 17 }, - /* 3797 */ { MAD_F(0x073b21e5) /* 0.451936623 */, 17 }, - /* 3798 */ { MAD_F(0x073bc850) /* 0.452095330 */, 17 }, - /* 3799 */ { MAD_F(0x073c6ebe) /* 0.452254050 */, 17 }, - /* 3800 */ { MAD_F(0x073d1530) /* 0.452412785 */, 17 }, - /* 3801 */ { MAD_F(0x073dbba6) /* 0.452571533 */, 17 }, - /* 3802 */ { MAD_F(0x073e621f) /* 0.452730295 */, 17 }, - /* 3803 */ { MAD_F(0x073f089c) /* 0.452889071 */, 17 }, - /* 3804 */ { MAD_F(0x073faf1d) /* 0.453047861 */, 17 }, - /* 3805 */ { MAD_F(0x074055a2) /* 0.453206665 */, 17 }, - /* 3806 */ { MAD_F(0x0740fc2a) /* 0.453365483 */, 17 }, - /* 3807 */ { MAD_F(0x0741a2b6) /* 0.453524315 */, 17 }, - - /* 3808 */ { MAD_F(0x07424946) /* 0.453683161 */, 17 }, - /* 3809 */ { MAD_F(0x0742efd9) /* 0.453842020 */, 17 }, - /* 3810 */ { MAD_F(0x07439671) /* 0.454000894 */, 17 }, - /* 3811 */ { MAD_F(0x07443d0c) /* 0.454159781 */, 17 }, - /* 3812 */ { MAD_F(0x0744e3aa) /* 0.454318683 */, 17 }, - /* 3813 */ { MAD_F(0x07458a4d) /* 0.454477598 */, 17 }, - /* 3814 */ { MAD_F(0x074630f3) /* 0.454636527 */, 17 }, - /* 3815 */ { MAD_F(0x0746d79d) /* 0.454795470 */, 17 }, - /* 3816 */ { MAD_F(0x07477e4b) /* 0.454954427 */, 17 }, - /* 3817 */ { MAD_F(0x074824fc) /* 0.455113397 */, 17 }, - /* 3818 */ { MAD_F(0x0748cbb1) /* 0.455272382 */, 17 }, - /* 3819 */ { MAD_F(0x0749726a) /* 0.455431381 */, 17 }, - /* 3820 */ { MAD_F(0x074a1927) /* 0.455590393 */, 17 }, - /* 3821 */ { MAD_F(0x074abfe7) /* 0.455749419 */, 17 }, - /* 3822 */ { MAD_F(0x074b66ab) /* 0.455908459 */, 17 }, - /* 3823 */ { MAD_F(0x074c0d73) /* 0.456067513 */, 17 }, - - /* 3824 */ { MAD_F(0x074cb43e) /* 0.456226581 */, 17 }, - /* 3825 */ { MAD_F(0x074d5b0d) /* 0.456385663 */, 17 }, - /* 3826 */ { MAD_F(0x074e01e0) /* 0.456544759 */, 17 }, - /* 3827 */ { MAD_F(0x074ea8b7) /* 0.456703868 */, 17 }, - /* 3828 */ { MAD_F(0x074f4f91) /* 0.456862992 */, 17 }, - /* 3829 */ { MAD_F(0x074ff66f) /* 0.457022129 */, 17 }, - /* 3830 */ { MAD_F(0x07509d51) /* 0.457181280 */, 17 }, - /* 3831 */ { MAD_F(0x07514437) /* 0.457340445 */, 17 }, - /* 3832 */ { MAD_F(0x0751eb20) /* 0.457499623 */, 17 }, - /* 3833 */ { MAD_F(0x0752920d) /* 0.457658816 */, 17 }, - /* 3834 */ { MAD_F(0x075338fd) /* 0.457818022 */, 17 }, - /* 3835 */ { MAD_F(0x0753dff2) /* 0.457977243 */, 17 }, - /* 3836 */ { MAD_F(0x075486ea) /* 0.458136477 */, 17 }, - /* 3837 */ { MAD_F(0x07552de6) /* 0.458295725 */, 17 }, - /* 3838 */ { MAD_F(0x0755d4e5) /* 0.458454987 */, 17 }, - /* 3839 */ { MAD_F(0x07567be8) /* 0.458614262 */, 17 }, - - /* 3840 */ { MAD_F(0x075722ef) /* 0.458773552 */, 17 }, - /* 3841 */ { MAD_F(0x0757c9fa) /* 0.458932855 */, 17 }, - /* 3842 */ { MAD_F(0x07587108) /* 0.459092172 */, 17 }, - /* 3843 */ { MAD_F(0x0759181a) /* 0.459251503 */, 17 }, - /* 3844 */ { MAD_F(0x0759bf30) /* 0.459410848 */, 17 }, - /* 3845 */ { MAD_F(0x075a664a) /* 0.459570206 */, 17 }, - /* 3846 */ { MAD_F(0x075b0d67) /* 0.459729579 */, 17 }, - /* 3847 */ { MAD_F(0x075bb488) /* 0.459888965 */, 17 }, - /* 3848 */ { MAD_F(0x075c5bac) /* 0.460048365 */, 17 }, - /* 3849 */ { MAD_F(0x075d02d5) /* 0.460207779 */, 17 }, - /* 3850 */ { MAD_F(0x075daa01) /* 0.460367206 */, 17 }, - /* 3851 */ { MAD_F(0x075e5130) /* 0.460526648 */, 17 }, - /* 3852 */ { MAD_F(0x075ef864) /* 0.460686103 */, 17 }, - /* 3853 */ { MAD_F(0x075f9f9b) /* 0.460845572 */, 17 }, - /* 3854 */ { MAD_F(0x076046d6) /* 0.461005055 */, 17 }, - /* 3855 */ { MAD_F(0x0760ee14) /* 0.461164552 */, 17 }, - - /* 3856 */ { MAD_F(0x07619557) /* 0.461324062 */, 17 }, - /* 3857 */ { MAD_F(0x07623c9d) /* 0.461483586 */, 17 }, - /* 3858 */ { MAD_F(0x0762e3e6) /* 0.461643124 */, 17 }, - /* 3859 */ { MAD_F(0x07638b34) /* 0.461802676 */, 17 }, - /* 3860 */ { MAD_F(0x07643285) /* 0.461962242 */, 17 }, - /* 3861 */ { MAD_F(0x0764d9d9) /* 0.462121821 */, 17 }, - /* 3862 */ { MAD_F(0x07658132) /* 0.462281414 */, 17 }, - /* 3863 */ { MAD_F(0x0766288e) /* 0.462441021 */, 17 }, - /* 3864 */ { MAD_F(0x0766cfee) /* 0.462600642 */, 17 }, - /* 3865 */ { MAD_F(0x07677751) /* 0.462760276 */, 17 }, - /* 3866 */ { MAD_F(0x07681eb9) /* 0.462919924 */, 17 }, - /* 3867 */ { MAD_F(0x0768c624) /* 0.463079586 */, 17 }, - /* 3868 */ { MAD_F(0x07696d92) /* 0.463239262 */, 17 }, - /* 3869 */ { MAD_F(0x076a1505) /* 0.463398951 */, 17 }, - /* 3870 */ { MAD_F(0x076abc7b) /* 0.463558655 */, 17 }, - /* 3871 */ { MAD_F(0x076b63f4) /* 0.463718372 */, 17 }, - - /* 3872 */ { MAD_F(0x076c0b72) /* 0.463878102 */, 17 }, - /* 3873 */ { MAD_F(0x076cb2f3) /* 0.464037847 */, 17 }, - /* 3874 */ { MAD_F(0x076d5a78) /* 0.464197605 */, 17 }, - /* 3875 */ { MAD_F(0x076e0200) /* 0.464357377 */, 17 }, - /* 3876 */ { MAD_F(0x076ea98c) /* 0.464517163 */, 17 }, - /* 3877 */ { MAD_F(0x076f511c) /* 0.464676962 */, 17 }, - /* 3878 */ { MAD_F(0x076ff8b0) /* 0.464836776 */, 17 }, - /* 3879 */ { MAD_F(0x0770a047) /* 0.464996603 */, 17 }, - /* 3880 */ { MAD_F(0x077147e2) /* 0.465156443 */, 17 }, - /* 3881 */ { MAD_F(0x0771ef80) /* 0.465316298 */, 17 }, - /* 3882 */ { MAD_F(0x07729723) /* 0.465476166 */, 17 }, - /* 3883 */ { MAD_F(0x07733ec9) /* 0.465636048 */, 17 }, - /* 3884 */ { MAD_F(0x0773e672) /* 0.465795943 */, 17 }, - /* 3885 */ { MAD_F(0x07748e20) /* 0.465955853 */, 17 }, - /* 3886 */ { MAD_F(0x077535d1) /* 0.466115776 */, 17 }, - /* 3887 */ { MAD_F(0x0775dd85) /* 0.466275713 */, 17 }, - - /* 3888 */ { MAD_F(0x0776853e) /* 0.466435663 */, 17 }, - /* 3889 */ { MAD_F(0x07772cfa) /* 0.466595627 */, 17 }, - /* 3890 */ { MAD_F(0x0777d4ba) /* 0.466755605 */, 17 }, - /* 3891 */ { MAD_F(0x07787c7d) /* 0.466915597 */, 17 }, - /* 3892 */ { MAD_F(0x07792444) /* 0.467075602 */, 17 }, - /* 3893 */ { MAD_F(0x0779cc0f) /* 0.467235621 */, 17 }, - /* 3894 */ { MAD_F(0x077a73dd) /* 0.467395654 */, 17 }, - /* 3895 */ { MAD_F(0x077b1baf) /* 0.467555701 */, 17 }, - /* 3896 */ { MAD_F(0x077bc385) /* 0.467715761 */, 17 }, - /* 3897 */ { MAD_F(0x077c6b5f) /* 0.467875835 */, 17 }, - /* 3898 */ { MAD_F(0x077d133c) /* 0.468035922 */, 17 }, - /* 3899 */ { MAD_F(0x077dbb1d) /* 0.468196023 */, 17 }, - /* 3900 */ { MAD_F(0x077e6301) /* 0.468356138 */, 17 }, - /* 3901 */ { MAD_F(0x077f0ae9) /* 0.468516267 */, 17 }, - /* 3902 */ { MAD_F(0x077fb2d5) /* 0.468676409 */, 17 }, - /* 3903 */ { MAD_F(0x07805ac5) /* 0.468836565 */, 17 }, - - /* 3904 */ { MAD_F(0x078102b8) /* 0.468996735 */, 17 }, - /* 3905 */ { MAD_F(0x0781aaaf) /* 0.469156918 */, 17 }, - /* 3906 */ { MAD_F(0x078252aa) /* 0.469317115 */, 17 }, - /* 3907 */ { MAD_F(0x0782faa8) /* 0.469477326 */, 17 }, - /* 3908 */ { MAD_F(0x0783a2aa) /* 0.469637550 */, 17 }, - /* 3909 */ { MAD_F(0x07844aaf) /* 0.469797788 */, 17 }, - /* 3910 */ { MAD_F(0x0784f2b8) /* 0.469958040 */, 17 }, - /* 3911 */ { MAD_F(0x07859ac5) /* 0.470118305 */, 17 }, - /* 3912 */ { MAD_F(0x078642d6) /* 0.470278584 */, 17 }, - /* 3913 */ { MAD_F(0x0786eaea) /* 0.470438877 */, 17 }, - /* 3914 */ { MAD_F(0x07879302) /* 0.470599183 */, 17 }, - /* 3915 */ { MAD_F(0x07883b1e) /* 0.470759503 */, 17 }, - /* 3916 */ { MAD_F(0x0788e33d) /* 0.470919836 */, 17 }, - /* 3917 */ { MAD_F(0x07898b60) /* 0.471080184 */, 17 }, - /* 3918 */ { MAD_F(0x078a3386) /* 0.471240545 */, 17 }, - /* 3919 */ { MAD_F(0x078adbb0) /* 0.471400919 */, 17 }, - - /* 3920 */ { MAD_F(0x078b83de) /* 0.471561307 */, 17 }, - /* 3921 */ { MAD_F(0x078c2c10) /* 0.471721709 */, 17 }, - /* 3922 */ { MAD_F(0x078cd445) /* 0.471882125 */, 17 }, - /* 3923 */ { MAD_F(0x078d7c7e) /* 0.472042554 */, 17 }, - /* 3924 */ { MAD_F(0x078e24ba) /* 0.472202996 */, 17 }, - /* 3925 */ { MAD_F(0x078eccfb) /* 0.472363453 */, 17 }, - /* 3926 */ { MAD_F(0x078f753e) /* 0.472523923 */, 17 }, - /* 3927 */ { MAD_F(0x07901d86) /* 0.472684406 */, 17 }, - /* 3928 */ { MAD_F(0x0790c5d1) /* 0.472844904 */, 17 }, - /* 3929 */ { MAD_F(0x07916e20) /* 0.473005414 */, 17 }, - /* 3930 */ { MAD_F(0x07921672) /* 0.473165939 */, 17 }, - /* 3931 */ { MAD_F(0x0792bec8) /* 0.473326477 */, 17 }, - /* 3932 */ { MAD_F(0x07936722) /* 0.473487029 */, 17 }, - /* 3933 */ { MAD_F(0x07940f80) /* 0.473647594 */, 17 }, - /* 3934 */ { MAD_F(0x0794b7e1) /* 0.473808173 */, 17 }, - /* 3935 */ { MAD_F(0x07956045) /* 0.473968765 */, 17 }, - - /* 3936 */ { MAD_F(0x079608ae) /* 0.474129372 */, 17 }, - /* 3937 */ { MAD_F(0x0796b11a) /* 0.474289991 */, 17 }, - /* 3938 */ { MAD_F(0x0797598a) /* 0.474450625 */, 17 }, - /* 3939 */ { MAD_F(0x079801fd) /* 0.474611272 */, 17 }, - /* 3940 */ { MAD_F(0x0798aa74) /* 0.474771932 */, 17 }, - /* 3941 */ { MAD_F(0x079952ee) /* 0.474932606 */, 17 }, - /* 3942 */ { MAD_F(0x0799fb6d) /* 0.475093294 */, 17 }, - /* 3943 */ { MAD_F(0x079aa3ef) /* 0.475253995 */, 17 }, - /* 3944 */ { MAD_F(0x079b4c74) /* 0.475414710 */, 17 }, - /* 3945 */ { MAD_F(0x079bf4fd) /* 0.475575439 */, 17 }, - /* 3946 */ { MAD_F(0x079c9d8a) /* 0.475736181 */, 17 }, - /* 3947 */ { MAD_F(0x079d461b) /* 0.475896936 */, 17 }, - /* 3948 */ { MAD_F(0x079deeaf) /* 0.476057705 */, 17 }, - /* 3949 */ { MAD_F(0x079e9747) /* 0.476218488 */, 17 }, - /* 3950 */ { MAD_F(0x079f3fe2) /* 0.476379285 */, 17 }, - /* 3951 */ { MAD_F(0x079fe881) /* 0.476540095 */, 17 }, - - /* 3952 */ { MAD_F(0x07a09124) /* 0.476700918 */, 17 }, - /* 3953 */ { MAD_F(0x07a139ca) /* 0.476861755 */, 17 }, - /* 3954 */ { MAD_F(0x07a1e274) /* 0.477022606 */, 17 }, - /* 3955 */ { MAD_F(0x07a28b22) /* 0.477183470 */, 17 }, - /* 3956 */ { MAD_F(0x07a333d3) /* 0.477344348 */, 17 }, - /* 3957 */ { MAD_F(0x07a3dc88) /* 0.477505239 */, 17 }, - /* 3958 */ { MAD_F(0x07a48541) /* 0.477666144 */, 17 }, - /* 3959 */ { MAD_F(0x07a52dfd) /* 0.477827062 */, 17 }, - /* 3960 */ { MAD_F(0x07a5d6bd) /* 0.477987994 */, 17 }, - /* 3961 */ { MAD_F(0x07a67f80) /* 0.478148940 */, 17 }, - /* 3962 */ { MAD_F(0x07a72847) /* 0.478309899 */, 17 }, - /* 3963 */ { MAD_F(0x07a7d112) /* 0.478470871 */, 17 }, - /* 3964 */ { MAD_F(0x07a879e1) /* 0.478631857 */, 17 }, - /* 3965 */ { MAD_F(0x07a922b3) /* 0.478792857 */, 17 }, - /* 3966 */ { MAD_F(0x07a9cb88) /* 0.478953870 */, 17 }, - /* 3967 */ { MAD_F(0x07aa7462) /* 0.479114897 */, 17 }, - - /* 3968 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 17 }, - /* 3969 */ { MAD_F(0x07abc61f) /* 0.479436991 */, 17 }, - /* 3970 */ { MAD_F(0x07ac6f03) /* 0.479598058 */, 17 }, - /* 3971 */ { MAD_F(0x07ad17eb) /* 0.479759139 */, 17 }, - /* 3972 */ { MAD_F(0x07adc0d6) /* 0.479920233 */, 17 }, - /* 3973 */ { MAD_F(0x07ae69c6) /* 0.480081341 */, 17 }, - /* 3974 */ { MAD_F(0x07af12b8) /* 0.480242463 */, 17 }, - /* 3975 */ { MAD_F(0x07afbbaf) /* 0.480403598 */, 17 }, - /* 3976 */ { MAD_F(0x07b064a8) /* 0.480564746 */, 17 }, - /* 3977 */ { MAD_F(0x07b10da6) /* 0.480725908 */, 17 }, - /* 3978 */ { MAD_F(0x07b1b6a7) /* 0.480887083 */, 17 }, - /* 3979 */ { MAD_F(0x07b25fac) /* 0.481048272 */, 17 }, - /* 3980 */ { MAD_F(0x07b308b5) /* 0.481209475 */, 17 }, - /* 3981 */ { MAD_F(0x07b3b1c1) /* 0.481370691 */, 17 }, - /* 3982 */ { MAD_F(0x07b45ad0) /* 0.481531920 */, 17 }, - /* 3983 */ { MAD_F(0x07b503e4) /* 0.481693163 */, 17 }, - - /* 3984 */ { MAD_F(0x07b5acfb) /* 0.481854420 */, 17 }, - /* 3985 */ { MAD_F(0x07b65615) /* 0.482015690 */, 17 }, - /* 3986 */ { MAD_F(0x07b6ff33) /* 0.482176973 */, 17 }, - /* 3987 */ { MAD_F(0x07b7a855) /* 0.482338270 */, 17 }, - /* 3988 */ { MAD_F(0x07b8517b) /* 0.482499580 */, 17 }, - /* 3989 */ { MAD_F(0x07b8faa4) /* 0.482660904 */, 17 }, - /* 3990 */ { MAD_F(0x07b9a3d0) /* 0.482822242 */, 17 }, - /* 3991 */ { MAD_F(0x07ba4d01) /* 0.482983592 */, 17 }, - /* 3992 */ { MAD_F(0x07baf635) /* 0.483144957 */, 17 }, - /* 3993 */ { MAD_F(0x07bb9f6c) /* 0.483306335 */, 17 }, - /* 3994 */ { MAD_F(0x07bc48a7) /* 0.483467726 */, 17 }, - /* 3995 */ { MAD_F(0x07bcf1e6) /* 0.483629131 */, 17 }, - /* 3996 */ { MAD_F(0x07bd9b28) /* 0.483790549 */, 17 }, - /* 3997 */ { MAD_F(0x07be446e) /* 0.483951980 */, 17 }, - /* 3998 */ { MAD_F(0x07beedb8) /* 0.484113426 */, 17 }, - /* 3999 */ { MAD_F(0x07bf9705) /* 0.484274884 */, 17 }, - - /* 4000 */ { MAD_F(0x07c04056) /* 0.484436356 */, 17 }, - /* 4001 */ { MAD_F(0x07c0e9aa) /* 0.484597842 */, 17 }, - /* 4002 */ { MAD_F(0x07c19302) /* 0.484759341 */, 17 }, - /* 4003 */ { MAD_F(0x07c23c5e) /* 0.484920853 */, 17 }, - /* 4004 */ { MAD_F(0x07c2e5bd) /* 0.485082379 */, 17 }, - /* 4005 */ { MAD_F(0x07c38f20) /* 0.485243918 */, 17 }, - /* 4006 */ { MAD_F(0x07c43887) /* 0.485405471 */, 17 }, - /* 4007 */ { MAD_F(0x07c4e1f1) /* 0.485567037 */, 17 }, - /* 4008 */ { MAD_F(0x07c58b5f) /* 0.485728617 */, 17 }, - /* 4009 */ { MAD_F(0x07c634d0) /* 0.485890210 */, 17 }, - /* 4010 */ { MAD_F(0x07c6de45) /* 0.486051817 */, 17 }, - /* 4011 */ { MAD_F(0x07c787bd) /* 0.486213436 */, 17 }, - /* 4012 */ { MAD_F(0x07c83139) /* 0.486375070 */, 17 }, - /* 4013 */ { MAD_F(0x07c8dab9) /* 0.486536717 */, 17 }, - /* 4014 */ { MAD_F(0x07c9843c) /* 0.486698377 */, 17 }, - /* 4015 */ { MAD_F(0x07ca2dc3) /* 0.486860051 */, 17 }, - - /* 4016 */ { MAD_F(0x07cad74e) /* 0.487021738 */, 17 }, - /* 4017 */ { MAD_F(0x07cb80dc) /* 0.487183438 */, 17 }, - /* 4018 */ { MAD_F(0x07cc2a6e) /* 0.487345152 */, 17 }, - /* 4019 */ { MAD_F(0x07ccd403) /* 0.487506879 */, 17 }, - /* 4020 */ { MAD_F(0x07cd7d9c) /* 0.487668620 */, 17 }, - /* 4021 */ { MAD_F(0x07ce2739) /* 0.487830374 */, 17 }, - /* 4022 */ { MAD_F(0x07ced0d9) /* 0.487992142 */, 17 }, - /* 4023 */ { MAD_F(0x07cf7a7d) /* 0.488153923 */, 17 }, - /* 4024 */ { MAD_F(0x07d02424) /* 0.488315717 */, 17 }, - /* 4025 */ { MAD_F(0x07d0cdcf) /* 0.488477525 */, 17 }, - /* 4026 */ { MAD_F(0x07d1777e) /* 0.488639346 */, 17 }, - /* 4027 */ { MAD_F(0x07d22130) /* 0.488801181 */, 17 }, - /* 4028 */ { MAD_F(0x07d2cae5) /* 0.488963029 */, 17 }, - /* 4029 */ { MAD_F(0x07d3749f) /* 0.489124890 */, 17 }, - /* 4030 */ { MAD_F(0x07d41e5c) /* 0.489286765 */, 17 }, - /* 4031 */ { MAD_F(0x07d4c81c) /* 0.489448653 */, 17 }, - - /* 4032 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 17 }, - /* 4033 */ { MAD_F(0x07d61ba8) /* 0.489772470 */, 17 }, - /* 4034 */ { MAD_F(0x07d6c573) /* 0.489934398 */, 17 }, - /* 4035 */ { MAD_F(0x07d76f42) /* 0.490096340 */, 17 }, - /* 4036 */ { MAD_F(0x07d81915) /* 0.490258295 */, 17 }, - /* 4037 */ { MAD_F(0x07d8c2eb) /* 0.490420263 */, 17 }, - /* 4038 */ { MAD_F(0x07d96cc4) /* 0.490582245 */, 17 }, - /* 4039 */ { MAD_F(0x07da16a2) /* 0.490744240 */, 17 }, - /* 4040 */ { MAD_F(0x07dac083) /* 0.490906249 */, 17 }, - /* 4041 */ { MAD_F(0x07db6a67) /* 0.491068271 */, 17 }, - /* 4042 */ { MAD_F(0x07dc144f) /* 0.491230306 */, 17 }, - /* 4043 */ { MAD_F(0x07dcbe3b) /* 0.491392355 */, 17 }, - /* 4044 */ { MAD_F(0x07dd682a) /* 0.491554417 */, 17 }, - /* 4045 */ { MAD_F(0x07de121d) /* 0.491716492 */, 17 }, - /* 4046 */ { MAD_F(0x07debc13) /* 0.491878581 */, 17 }, - /* 4047 */ { MAD_F(0x07df660d) /* 0.492040683 */, 17 }, - - /* 4048 */ { MAD_F(0x07e0100a) /* 0.492202799 */, 17 }, - /* 4049 */ { MAD_F(0x07e0ba0c) /* 0.492364928 */, 17 }, - /* 4050 */ { MAD_F(0x07e16410) /* 0.492527070 */, 17 }, - /* 4051 */ { MAD_F(0x07e20e19) /* 0.492689225 */, 17 }, - /* 4052 */ { MAD_F(0x07e2b824) /* 0.492851394 */, 17 }, - /* 4053 */ { MAD_F(0x07e36234) /* 0.493013576 */, 17 }, - /* 4054 */ { MAD_F(0x07e40c47) /* 0.493175772 */, 17 }, - /* 4055 */ { MAD_F(0x07e4b65e) /* 0.493337981 */, 17 }, - /* 4056 */ { MAD_F(0x07e56078) /* 0.493500203 */, 17 }, - /* 4057 */ { MAD_F(0x07e60a95) /* 0.493662438 */, 17 }, - /* 4058 */ { MAD_F(0x07e6b4b7) /* 0.493824687 */, 17 }, - /* 4059 */ { MAD_F(0x07e75edc) /* 0.493986949 */, 17 }, - /* 4060 */ { MAD_F(0x07e80904) /* 0.494149225 */, 17 }, - /* 4061 */ { MAD_F(0x07e8b330) /* 0.494311514 */, 17 }, - /* 4062 */ { MAD_F(0x07e95d60) /* 0.494473816 */, 17 }, - /* 4063 */ { MAD_F(0x07ea0793) /* 0.494636131 */, 17 }, - - /* 4064 */ { MAD_F(0x07eab1ca) /* 0.494798460 */, 17 }, - /* 4065 */ { MAD_F(0x07eb5c04) /* 0.494960802 */, 17 }, - /* 4066 */ { MAD_F(0x07ec0642) /* 0.495123158 */, 17 }, - /* 4067 */ { MAD_F(0x07ecb084) /* 0.495285526 */, 17 }, - /* 4068 */ { MAD_F(0x07ed5ac9) /* 0.495447908 */, 17 }, - /* 4069 */ { MAD_F(0x07ee0512) /* 0.495610304 */, 17 }, - /* 4070 */ { MAD_F(0x07eeaf5e) /* 0.495772712 */, 17 }, - /* 4071 */ { MAD_F(0x07ef59ae) /* 0.495935134 */, 17 }, - /* 4072 */ { MAD_F(0x07f00401) /* 0.496097570 */, 17 }, - /* 4073 */ { MAD_F(0x07f0ae58) /* 0.496260018 */, 17 }, - /* 4074 */ { MAD_F(0x07f158b3) /* 0.496422480 */, 17 }, - /* 4075 */ { MAD_F(0x07f20311) /* 0.496584955 */, 17 }, - /* 4076 */ { MAD_F(0x07f2ad72) /* 0.496747444 */, 17 }, - /* 4077 */ { MAD_F(0x07f357d8) /* 0.496909945 */, 17 }, - /* 4078 */ { MAD_F(0x07f40240) /* 0.497072460 */, 17 }, - /* 4079 */ { MAD_F(0x07f4acad) /* 0.497234989 */, 17 }, - - /* 4080 */ { MAD_F(0x07f5571d) /* 0.497397530 */, 17 }, - /* 4081 */ { MAD_F(0x07f60190) /* 0.497560085 */, 17 }, - /* 4082 */ { MAD_F(0x07f6ac07) /* 0.497722653 */, 17 }, - /* 4083 */ { MAD_F(0x07f75682) /* 0.497885235 */, 17 }, - /* 4084 */ { MAD_F(0x07f80100) /* 0.498047829 */, 17 }, - /* 4085 */ { MAD_F(0x07f8ab82) /* 0.498210437 */, 17 }, - /* 4086 */ { MAD_F(0x07f95607) /* 0.498373058 */, 17 }, - /* 4087 */ { MAD_F(0x07fa0090) /* 0.498535693 */, 17 }, - /* 4088 */ { MAD_F(0x07faab1c) /* 0.498698341 */, 17 }, - /* 4089 */ { MAD_F(0x07fb55ac) /* 0.498861002 */, 17 }, - /* 4090 */ { MAD_F(0x07fc0040) /* 0.499023676 */, 17 }, - /* 4091 */ { MAD_F(0x07fcaad7) /* 0.499186364 */, 17 }, - /* 4092 */ { MAD_F(0x07fd5572) /* 0.499349064 */, 17 }, - /* 4093 */ { MAD_F(0x07fe0010) /* 0.499511778 */, 17 }, - /* 4094 */ { MAD_F(0x07feaab2) /* 0.499674506 */, 17 }, - /* 4095 */ { MAD_F(0x07ff5557) /* 0.499837246 */, 17 }, - - /* 4096 */ { MAD_F(0x04000000) /* 0.250000000 */, 18 }, - /* 4097 */ { MAD_F(0x04005556) /* 0.250081384 */, 18 }, - /* 4098 */ { MAD_F(0x0400aaae) /* 0.250162774 */, 18 }, - /* 4099 */ { MAD_F(0x04010008) /* 0.250244170 */, 18 }, - /* 4100 */ { MAD_F(0x04015563) /* 0.250325574 */, 18 }, - /* 4101 */ { MAD_F(0x0401aac1) /* 0.250406984 */, 18 }, - /* 4102 */ { MAD_F(0x04020020) /* 0.250488400 */, 18 }, - /* 4103 */ { MAD_F(0x04025581) /* 0.250569824 */, 18 }, - /* 4104 */ { MAD_F(0x0402aae3) /* 0.250651254 */, 18 }, - /* 4105 */ { MAD_F(0x04030048) /* 0.250732690 */, 18 }, - /* 4106 */ { MAD_F(0x040355ae) /* 0.250814133 */, 18 }, - /* 4107 */ { MAD_F(0x0403ab16) /* 0.250895583 */, 18 }, - /* 4108 */ { MAD_F(0x04040080) /* 0.250977039 */, 18 }, - /* 4109 */ { MAD_F(0x040455eb) /* 0.251058502 */, 18 }, - /* 4110 */ { MAD_F(0x0404ab59) /* 0.251139971 */, 18 }, - /* 4111 */ { MAD_F(0x040500c8) /* 0.251221448 */, 18 }, - - /* 4112 */ { MAD_F(0x04055638) /* 0.251302930 */, 18 }, - /* 4113 */ { MAD_F(0x0405abab) /* 0.251384420 */, 18 }, - /* 4114 */ { MAD_F(0x0406011f) /* 0.251465916 */, 18 }, - /* 4115 */ { MAD_F(0x04065696) /* 0.251547418 */, 18 }, - /* 4116 */ { MAD_F(0x0406ac0e) /* 0.251628927 */, 18 }, - /* 4117 */ { MAD_F(0x04070187) /* 0.251710443 */, 18 }, - /* 4118 */ { MAD_F(0x04075703) /* 0.251791965 */, 18 }, - /* 4119 */ { MAD_F(0x0407ac80) /* 0.251873494 */, 18 }, - /* 4120 */ { MAD_F(0x040801ff) /* 0.251955030 */, 18 }, - /* 4121 */ { MAD_F(0x04085780) /* 0.252036572 */, 18 }, - /* 4122 */ { MAD_F(0x0408ad02) /* 0.252118121 */, 18 }, - /* 4123 */ { MAD_F(0x04090287) /* 0.252199676 */, 18 }, - /* 4124 */ { MAD_F(0x0409580d) /* 0.252281238 */, 18 }, - /* 4125 */ { MAD_F(0x0409ad95) /* 0.252362807 */, 18 }, - /* 4126 */ { MAD_F(0x040a031e) /* 0.252444382 */, 18 }, - /* 4127 */ { MAD_F(0x040a58aa) /* 0.252525963 */, 18 }, - - /* 4128 */ { MAD_F(0x040aae37) /* 0.252607552 */, 18 }, - /* 4129 */ { MAD_F(0x040b03c6) /* 0.252689147 */, 18 }, - /* 4130 */ { MAD_F(0x040b5957) /* 0.252770748 */, 18 }, - /* 4131 */ { MAD_F(0x040baee9) /* 0.252852356 */, 18 }, - /* 4132 */ { MAD_F(0x040c047e) /* 0.252933971 */, 18 }, - /* 4133 */ { MAD_F(0x040c5a14) /* 0.253015592 */, 18 }, - /* 4134 */ { MAD_F(0x040cafab) /* 0.253097220 */, 18 }, - /* 4135 */ { MAD_F(0x040d0545) /* 0.253178854 */, 18 }, - /* 4136 */ { MAD_F(0x040d5ae0) /* 0.253260495 */, 18 }, - /* 4137 */ { MAD_F(0x040db07d) /* 0.253342143 */, 18 }, - /* 4138 */ { MAD_F(0x040e061c) /* 0.253423797 */, 18 }, - /* 4139 */ { MAD_F(0x040e5bbd) /* 0.253505457 */, 18 }, - /* 4140 */ { MAD_F(0x040eb15f) /* 0.253587125 */, 18 }, - /* 4141 */ { MAD_F(0x040f0703) /* 0.253668799 */, 18 }, - /* 4142 */ { MAD_F(0x040f5ca9) /* 0.253750479 */, 18 }, - /* 4143 */ { MAD_F(0x040fb251) /* 0.253832166 */, 18 }, - - /* 4144 */ { MAD_F(0x041007fa) /* 0.253913860 */, 18 }, - /* 4145 */ { MAD_F(0x04105da6) /* 0.253995560 */, 18 }, - /* 4146 */ { MAD_F(0x0410b353) /* 0.254077266 */, 18 }, - /* 4147 */ { MAD_F(0x04110901) /* 0.254158980 */, 18 }, - /* 4148 */ { MAD_F(0x04115eb2) /* 0.254240700 */, 18 }, - /* 4149 */ { MAD_F(0x0411b464) /* 0.254322426 */, 18 }, - /* 4150 */ { MAD_F(0x04120a18) /* 0.254404159 */, 18 }, - /* 4151 */ { MAD_F(0x04125fce) /* 0.254485899 */, 18 }, - /* 4152 */ { MAD_F(0x0412b586) /* 0.254567645 */, 18 }, - /* 4153 */ { MAD_F(0x04130b3f) /* 0.254649397 */, 18 }, - /* 4154 */ { MAD_F(0x041360fa) /* 0.254731157 */, 18 }, - /* 4155 */ { MAD_F(0x0413b6b7) /* 0.254812922 */, 18 }, - /* 4156 */ { MAD_F(0x04140c75) /* 0.254894695 */, 18 }, - /* 4157 */ { MAD_F(0x04146236) /* 0.254976474 */, 18 }, - /* 4158 */ { MAD_F(0x0414b7f8) /* 0.255058259 */, 18 }, - /* 4159 */ { MAD_F(0x04150dbc) /* 0.255140051 */, 18 }, - - /* 4160 */ { MAD_F(0x04156381) /* 0.255221850 */, 18 }, - /* 4161 */ { MAD_F(0x0415b949) /* 0.255303655 */, 18 }, - /* 4162 */ { MAD_F(0x04160f12) /* 0.255385467 */, 18 }, - /* 4163 */ { MAD_F(0x041664dd) /* 0.255467285 */, 18 }, - /* 4164 */ { MAD_F(0x0416baaa) /* 0.255549110 */, 18 }, - /* 4165 */ { MAD_F(0x04171078) /* 0.255630941 */, 18 }, - /* 4166 */ { MAD_F(0x04176648) /* 0.255712779 */, 18 }, - /* 4167 */ { MAD_F(0x0417bc1a) /* 0.255794624 */, 18 }, - /* 4168 */ { MAD_F(0x041811ee) /* 0.255876475 */, 18 }, - /* 4169 */ { MAD_F(0x041867c3) /* 0.255958332 */, 18 }, - /* 4170 */ { MAD_F(0x0418bd9b) /* 0.256040196 */, 18 }, - /* 4171 */ { MAD_F(0x04191374) /* 0.256122067 */, 18 }, - /* 4172 */ { MAD_F(0x0419694e) /* 0.256203944 */, 18 }, - /* 4173 */ { MAD_F(0x0419bf2b) /* 0.256285828 */, 18 }, - /* 4174 */ { MAD_F(0x041a1509) /* 0.256367718 */, 18 }, - /* 4175 */ { MAD_F(0x041a6ae9) /* 0.256449615 */, 18 }, - - /* 4176 */ { MAD_F(0x041ac0cb) /* 0.256531518 */, 18 }, - /* 4177 */ { MAD_F(0x041b16ae) /* 0.256613428 */, 18 }, - /* 4178 */ { MAD_F(0x041b6c94) /* 0.256695344 */, 18 }, - /* 4179 */ { MAD_F(0x041bc27b) /* 0.256777267 */, 18 }, - /* 4180 */ { MAD_F(0x041c1863) /* 0.256859197 */, 18 }, - /* 4181 */ { MAD_F(0x041c6e4e) /* 0.256941133 */, 18 }, - /* 4182 */ { MAD_F(0x041cc43a) /* 0.257023076 */, 18 }, - /* 4183 */ { MAD_F(0x041d1a28) /* 0.257105025 */, 18 }, - /* 4184 */ { MAD_F(0x041d7018) /* 0.257186980 */, 18 }, - /* 4185 */ { MAD_F(0x041dc60a) /* 0.257268942 */, 18 }, - /* 4186 */ { MAD_F(0x041e1bfd) /* 0.257350911 */, 18 }, - /* 4187 */ { MAD_F(0x041e71f2) /* 0.257432886 */, 18 }, - /* 4188 */ { MAD_F(0x041ec7e9) /* 0.257514868 */, 18 }, - /* 4189 */ { MAD_F(0x041f1de1) /* 0.257596856 */, 18 }, - /* 4190 */ { MAD_F(0x041f73dc) /* 0.257678851 */, 18 }, - /* 4191 */ { MAD_F(0x041fc9d8) /* 0.257760852 */, 18 }, - - /* 4192 */ { MAD_F(0x04201fd5) /* 0.257842860 */, 18 }, - /* 4193 */ { MAD_F(0x042075d5) /* 0.257924875 */, 18 }, - /* 4194 */ { MAD_F(0x0420cbd6) /* 0.258006895 */, 18 }, - /* 4195 */ { MAD_F(0x042121d9) /* 0.258088923 */, 18 }, - /* 4196 */ { MAD_F(0x042177de) /* 0.258170957 */, 18 }, - /* 4197 */ { MAD_F(0x0421cde5) /* 0.258252997 */, 18 }, - /* 4198 */ { MAD_F(0x042223ed) /* 0.258335044 */, 18 }, - /* 4199 */ { MAD_F(0x042279f7) /* 0.258417097 */, 18 }, - /* 4200 */ { MAD_F(0x0422d003) /* 0.258499157 */, 18 }, - /* 4201 */ { MAD_F(0x04232611) /* 0.258581224 */, 18 }, - /* 4202 */ { MAD_F(0x04237c20) /* 0.258663297 */, 18 }, - /* 4203 */ { MAD_F(0x0423d231) /* 0.258745376 */, 18 }, - /* 4204 */ { MAD_F(0x04242844) /* 0.258827462 */, 18 }, - /* 4205 */ { MAD_F(0x04247e58) /* 0.258909555 */, 18 }, - /* 4206 */ { MAD_F(0x0424d46e) /* 0.258991654 */, 18 }, - /* 4207 */ { MAD_F(0x04252a87) /* 0.259073760 */, 18 }, - - /* 4208 */ { MAD_F(0x042580a0) /* 0.259155872 */, 18 }, - /* 4209 */ { MAD_F(0x0425d6bc) /* 0.259237990 */, 18 }, - /* 4210 */ { MAD_F(0x04262cd9) /* 0.259320115 */, 18 }, - /* 4211 */ { MAD_F(0x042682f8) /* 0.259402247 */, 18 }, - /* 4212 */ { MAD_F(0x0426d919) /* 0.259484385 */, 18 }, - /* 4213 */ { MAD_F(0x04272f3b) /* 0.259566529 */, 18 }, - /* 4214 */ { MAD_F(0x04278560) /* 0.259648680 */, 18 }, - /* 4215 */ { MAD_F(0x0427db86) /* 0.259730838 */, 18 }, - /* 4216 */ { MAD_F(0x042831ad) /* 0.259813002 */, 18 }, - /* 4217 */ { MAD_F(0x042887d7) /* 0.259895173 */, 18 }, - /* 4218 */ { MAD_F(0x0428de02) /* 0.259977350 */, 18 }, - /* 4219 */ { MAD_F(0x0429342f) /* 0.260059533 */, 18 }, - /* 4220 */ { MAD_F(0x04298a5e) /* 0.260141723 */, 18 }, - /* 4221 */ { MAD_F(0x0429e08e) /* 0.260223920 */, 18 }, - /* 4222 */ { MAD_F(0x042a36c0) /* 0.260306123 */, 18 }, - /* 4223 */ { MAD_F(0x042a8cf4) /* 0.260388332 */, 18 }, - - /* 4224 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 18 }, - /* 4225 */ { MAD_F(0x042b3962) /* 0.260552771 */, 18 }, - /* 4226 */ { MAD_F(0x042b8f9b) /* 0.260635000 */, 18 }, - /* 4227 */ { MAD_F(0x042be5d6) /* 0.260717235 */, 18 }, - /* 4228 */ { MAD_F(0x042c3c12) /* 0.260799477 */, 18 }, - /* 4229 */ { MAD_F(0x042c9251) /* 0.260881725 */, 18 }, - /* 4230 */ { MAD_F(0x042ce891) /* 0.260963980 */, 18 }, - /* 4231 */ { MAD_F(0x042d3ed3) /* 0.261046242 */, 18 }, - /* 4232 */ { MAD_F(0x042d9516) /* 0.261128510 */, 18 }, - /* 4233 */ { MAD_F(0x042deb5c) /* 0.261210784 */, 18 }, - /* 4234 */ { MAD_F(0x042e41a3) /* 0.261293065 */, 18 }, - /* 4235 */ { MAD_F(0x042e97ec) /* 0.261375352 */, 18 }, - /* 4236 */ { MAD_F(0x042eee36) /* 0.261457646 */, 18 }, - /* 4237 */ { MAD_F(0x042f4482) /* 0.261539946 */, 18 }, - /* 4238 */ { MAD_F(0x042f9ad1) /* 0.261622253 */, 18 }, - /* 4239 */ { MAD_F(0x042ff120) /* 0.261704566 */, 18 }, - - /* 4240 */ { MAD_F(0x04304772) /* 0.261786886 */, 18 }, - /* 4241 */ { MAD_F(0x04309dc5) /* 0.261869212 */, 18 }, - /* 4242 */ { MAD_F(0x0430f41a) /* 0.261951545 */, 18 }, - /* 4243 */ { MAD_F(0x04314a71) /* 0.262033884 */, 18 }, - /* 4244 */ { MAD_F(0x0431a0c9) /* 0.262116229 */, 18 }, - /* 4245 */ { MAD_F(0x0431f723) /* 0.262198581 */, 18 }, - /* 4246 */ { MAD_F(0x04324d7f) /* 0.262280940 */, 18 }, - /* 4247 */ { MAD_F(0x0432a3dd) /* 0.262363305 */, 18 }, - /* 4248 */ { MAD_F(0x0432fa3d) /* 0.262445676 */, 18 }, - /* 4249 */ { MAD_F(0x0433509e) /* 0.262528054 */, 18 }, - /* 4250 */ { MAD_F(0x0433a701) /* 0.262610438 */, 18 }, - /* 4251 */ { MAD_F(0x0433fd65) /* 0.262692829 */, 18 }, - /* 4252 */ { MAD_F(0x043453cc) /* 0.262775227 */, 18 }, - /* 4253 */ { MAD_F(0x0434aa34) /* 0.262857630 */, 18 }, - /* 4254 */ { MAD_F(0x0435009d) /* 0.262940040 */, 18 }, - /* 4255 */ { MAD_F(0x04355709) /* 0.263022457 */, 18 }, - - /* 4256 */ { MAD_F(0x0435ad76) /* 0.263104880 */, 18 }, - /* 4257 */ { MAD_F(0x043603e5) /* 0.263187310 */, 18 }, - /* 4258 */ { MAD_F(0x04365a56) /* 0.263269746 */, 18 }, - /* 4259 */ { MAD_F(0x0436b0c9) /* 0.263352188 */, 18 }, - /* 4260 */ { MAD_F(0x0437073d) /* 0.263434637 */, 18 }, - /* 4261 */ { MAD_F(0x04375db3) /* 0.263517093 */, 18 }, - /* 4262 */ { MAD_F(0x0437b42a) /* 0.263599554 */, 18 }, - /* 4263 */ { MAD_F(0x04380aa4) /* 0.263682023 */, 18 }, - /* 4264 */ { MAD_F(0x0438611f) /* 0.263764497 */, 18 }, - /* 4265 */ { MAD_F(0x0438b79c) /* 0.263846979 */, 18 }, - /* 4266 */ { MAD_F(0x04390e1a) /* 0.263929466 */, 18 }, - /* 4267 */ { MAD_F(0x0439649b) /* 0.264011960 */, 18 }, - /* 4268 */ { MAD_F(0x0439bb1d) /* 0.264094461 */, 18 }, - /* 4269 */ { MAD_F(0x043a11a1) /* 0.264176968 */, 18 }, - /* 4270 */ { MAD_F(0x043a6826) /* 0.264259481 */, 18 }, - /* 4271 */ { MAD_F(0x043abead) /* 0.264342001 */, 18 }, - - /* 4272 */ { MAD_F(0x043b1536) /* 0.264424527 */, 18 }, - /* 4273 */ { MAD_F(0x043b6bc1) /* 0.264507060 */, 18 }, - /* 4274 */ { MAD_F(0x043bc24d) /* 0.264589599 */, 18 }, - /* 4275 */ { MAD_F(0x043c18dc) /* 0.264672145 */, 18 }, - /* 4276 */ { MAD_F(0x043c6f6c) /* 0.264754697 */, 18 }, - /* 4277 */ { MAD_F(0x043cc5fd) /* 0.264837255 */, 18 }, - /* 4278 */ { MAD_F(0x043d1c91) /* 0.264919820 */, 18 }, - /* 4279 */ { MAD_F(0x043d7326) /* 0.265002392 */, 18 }, - /* 4280 */ { MAD_F(0x043dc9bc) /* 0.265084969 */, 18 }, - /* 4281 */ { MAD_F(0x043e2055) /* 0.265167554 */, 18 }, - /* 4282 */ { MAD_F(0x043e76ef) /* 0.265250144 */, 18 }, - /* 4283 */ { MAD_F(0x043ecd8b) /* 0.265332741 */, 18 }, - /* 4284 */ { MAD_F(0x043f2429) /* 0.265415345 */, 18 }, - /* 4285 */ { MAD_F(0x043f7ac8) /* 0.265497955 */, 18 }, - /* 4286 */ { MAD_F(0x043fd169) /* 0.265580571 */, 18 }, - /* 4287 */ { MAD_F(0x0440280c) /* 0.265663194 */, 18 }, - - /* 4288 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 18 }, - /* 4289 */ { MAD_F(0x0440d557) /* 0.265828459 */, 18 }, - /* 4290 */ { MAD_F(0x04412bff) /* 0.265911101 */, 18 }, - /* 4291 */ { MAD_F(0x044182a9) /* 0.265993749 */, 18 }, - /* 4292 */ { MAD_F(0x0441d955) /* 0.266076404 */, 18 }, - /* 4293 */ { MAD_F(0x04423002) /* 0.266159065 */, 18 }, - /* 4294 */ { MAD_F(0x044286b1) /* 0.266241733 */, 18 }, - /* 4295 */ { MAD_F(0x0442dd61) /* 0.266324407 */, 18 }, - /* 4296 */ { MAD_F(0x04433414) /* 0.266407088 */, 18 }, - /* 4297 */ { MAD_F(0x04438ac8) /* 0.266489775 */, 18 }, - /* 4298 */ { MAD_F(0x0443e17e) /* 0.266572468 */, 18 }, - /* 4299 */ { MAD_F(0x04443835) /* 0.266655168 */, 18 }, - /* 4300 */ { MAD_F(0x04448eef) /* 0.266737874 */, 18 }, - /* 4301 */ { MAD_F(0x0444e5aa) /* 0.266820587 */, 18 }, - /* 4302 */ { MAD_F(0x04453c66) /* 0.266903306 */, 18 }, - /* 4303 */ { MAD_F(0x04459325) /* 0.266986031 */, 18 }, - - /* 4304 */ { MAD_F(0x0445e9e5) /* 0.267068763 */, 18 }, - /* 4305 */ { MAD_F(0x044640a7) /* 0.267151501 */, 18 }, - /* 4306 */ { MAD_F(0x0446976a) /* 0.267234246 */, 18 }, - /* 4307 */ { MAD_F(0x0446ee30) /* 0.267316997 */, 18 }, - /* 4308 */ { MAD_F(0x044744f7) /* 0.267399755 */, 18 }, - /* 4309 */ { MAD_F(0x04479bc0) /* 0.267482518 */, 18 }, - /* 4310 */ { MAD_F(0x0447f28a) /* 0.267565289 */, 18 }, - /* 4311 */ { MAD_F(0x04484956) /* 0.267648065 */, 18 }, - /* 4312 */ { MAD_F(0x0448a024) /* 0.267730848 */, 18 }, - /* 4313 */ { MAD_F(0x0448f6f4) /* 0.267813638 */, 18 }, - /* 4314 */ { MAD_F(0x04494dc5) /* 0.267896434 */, 18 }, - /* 4315 */ { MAD_F(0x0449a498) /* 0.267979236 */, 18 }, - /* 4316 */ { MAD_F(0x0449fb6d) /* 0.268062045 */, 18 }, - /* 4317 */ { MAD_F(0x044a5243) /* 0.268144860 */, 18 }, - /* 4318 */ { MAD_F(0x044aa91c) /* 0.268227681 */, 18 }, - /* 4319 */ { MAD_F(0x044afff6) /* 0.268310509 */, 18 }, - - /* 4320 */ { MAD_F(0x044b56d1) /* 0.268393343 */, 18 }, - /* 4321 */ { MAD_F(0x044badaf) /* 0.268476184 */, 18 }, - /* 4322 */ { MAD_F(0x044c048e) /* 0.268559031 */, 18 }, - /* 4323 */ { MAD_F(0x044c5b6f) /* 0.268641885 */, 18 }, - /* 4324 */ { MAD_F(0x044cb251) /* 0.268724744 */, 18 }, - /* 4325 */ { MAD_F(0x044d0935) /* 0.268807611 */, 18 }, - /* 4326 */ { MAD_F(0x044d601b) /* 0.268890483 */, 18 }, - /* 4327 */ { MAD_F(0x044db703) /* 0.268973362 */, 18 }, - /* 4328 */ { MAD_F(0x044e0dec) /* 0.269056248 */, 18 }, - /* 4329 */ { MAD_F(0x044e64d7) /* 0.269139139 */, 18 }, - /* 4330 */ { MAD_F(0x044ebbc4) /* 0.269222037 */, 18 }, - /* 4331 */ { MAD_F(0x044f12b3) /* 0.269304942 */, 18 }, - /* 4332 */ { MAD_F(0x044f69a3) /* 0.269387853 */, 18 }, - /* 4333 */ { MAD_F(0x044fc095) /* 0.269470770 */, 18 }, - /* 4334 */ { MAD_F(0x04501788) /* 0.269553694 */, 18 }, - /* 4335 */ { MAD_F(0x04506e7e) /* 0.269636624 */, 18 }, - - /* 4336 */ { MAD_F(0x0450c575) /* 0.269719560 */, 18 }, - /* 4337 */ { MAD_F(0x04511c6e) /* 0.269802503 */, 18 }, - /* 4338 */ { MAD_F(0x04517368) /* 0.269885452 */, 18 }, - /* 4339 */ { MAD_F(0x0451ca64) /* 0.269968408 */, 18 }, - /* 4340 */ { MAD_F(0x04522162) /* 0.270051370 */, 18 }, - /* 4341 */ { MAD_F(0x04527862) /* 0.270134338 */, 18 }, - /* 4342 */ { MAD_F(0x0452cf63) /* 0.270217312 */, 18 }, - /* 4343 */ { MAD_F(0x04532666) /* 0.270300293 */, 18 }, - /* 4344 */ { MAD_F(0x04537d6b) /* 0.270383281 */, 18 }, - /* 4345 */ { MAD_F(0x0453d472) /* 0.270466275 */, 18 }, - /* 4346 */ { MAD_F(0x04542b7a) /* 0.270549275 */, 18 }, - /* 4347 */ { MAD_F(0x04548284) /* 0.270632281 */, 18 }, - /* 4348 */ { MAD_F(0x0454d98f) /* 0.270715294 */, 18 }, - /* 4349 */ { MAD_F(0x0455309c) /* 0.270798313 */, 18 }, - /* 4350 */ { MAD_F(0x045587ab) /* 0.270881339 */, 18 }, - /* 4351 */ { MAD_F(0x0455debc) /* 0.270964371 */, 18 }, - - /* 4352 */ { MAD_F(0x045635cf) /* 0.271047409 */, 18 }, - /* 4353 */ { MAD_F(0x04568ce3) /* 0.271130454 */, 18 }, - /* 4354 */ { MAD_F(0x0456e3f9) /* 0.271213505 */, 18 }, - /* 4355 */ { MAD_F(0x04573b10) /* 0.271296562 */, 18 }, - /* 4356 */ { MAD_F(0x04579229) /* 0.271379626 */, 18 }, - /* 4357 */ { MAD_F(0x0457e944) /* 0.271462696 */, 18 }, - /* 4358 */ { MAD_F(0x04584061) /* 0.271545772 */, 18 }, - /* 4359 */ { MAD_F(0x0458977f) /* 0.271628855 */, 18 }, - /* 4360 */ { MAD_F(0x0458ee9f) /* 0.271711944 */, 18 }, - /* 4361 */ { MAD_F(0x045945c1) /* 0.271795040 */, 18 }, - /* 4362 */ { MAD_F(0x04599ce5) /* 0.271878142 */, 18 }, - /* 4363 */ { MAD_F(0x0459f40a) /* 0.271961250 */, 18 }, - /* 4364 */ { MAD_F(0x045a4b31) /* 0.272044365 */, 18 }, - /* 4365 */ { MAD_F(0x045aa259) /* 0.272127486 */, 18 }, - /* 4366 */ { MAD_F(0x045af984) /* 0.272210613 */, 18 }, - /* 4367 */ { MAD_F(0x045b50b0) /* 0.272293746 */, 18 }, - - /* 4368 */ { MAD_F(0x045ba7dd) /* 0.272376886 */, 18 }, - /* 4369 */ { MAD_F(0x045bff0d) /* 0.272460033 */, 18 }, - /* 4370 */ { MAD_F(0x045c563e) /* 0.272543185 */, 18 }, - /* 4371 */ { MAD_F(0x045cad71) /* 0.272626344 */, 18 }, - /* 4372 */ { MAD_F(0x045d04a5) /* 0.272709510 */, 18 }, - /* 4373 */ { MAD_F(0x045d5bdc) /* 0.272792681 */, 18 }, - /* 4374 */ { MAD_F(0x045db313) /* 0.272875859 */, 18 }, - /* 4375 */ { MAD_F(0x045e0a4d) /* 0.272959044 */, 18 }, - /* 4376 */ { MAD_F(0x045e6188) /* 0.273042234 */, 18 }, - /* 4377 */ { MAD_F(0x045eb8c5) /* 0.273125431 */, 18 }, - /* 4378 */ { MAD_F(0x045f1004) /* 0.273208635 */, 18 }, - /* 4379 */ { MAD_F(0x045f6745) /* 0.273291844 */, 18 }, - /* 4380 */ { MAD_F(0x045fbe87) /* 0.273375060 */, 18 }, - /* 4381 */ { MAD_F(0x046015cb) /* 0.273458283 */, 18 }, - /* 4382 */ { MAD_F(0x04606d10) /* 0.273541511 */, 18 }, - /* 4383 */ { MAD_F(0x0460c457) /* 0.273624747 */, 18 }, - - /* 4384 */ { MAD_F(0x04611ba0) /* 0.273707988 */, 18 }, - /* 4385 */ { MAD_F(0x046172eb) /* 0.273791236 */, 18 }, - /* 4386 */ { MAD_F(0x0461ca37) /* 0.273874490 */, 18 }, - /* 4387 */ { MAD_F(0x04622185) /* 0.273957750 */, 18 }, - /* 4388 */ { MAD_F(0x046278d5) /* 0.274041017 */, 18 }, - /* 4389 */ { MAD_F(0x0462d026) /* 0.274124290 */, 18 }, - /* 4390 */ { MAD_F(0x0463277a) /* 0.274207569 */, 18 }, - /* 4391 */ { MAD_F(0x04637ece) /* 0.274290855 */, 18 }, - /* 4392 */ { MAD_F(0x0463d625) /* 0.274374147 */, 18 }, - /* 4393 */ { MAD_F(0x04642d7d) /* 0.274457445 */, 18 }, - /* 4394 */ { MAD_F(0x046484d7) /* 0.274540749 */, 18 }, - /* 4395 */ { MAD_F(0x0464dc33) /* 0.274624060 */, 18 }, - /* 4396 */ { MAD_F(0x04653390) /* 0.274707378 */, 18 }, - /* 4397 */ { MAD_F(0x04658aef) /* 0.274790701 */, 18 }, - /* 4398 */ { MAD_F(0x0465e250) /* 0.274874031 */, 18 }, - /* 4399 */ { MAD_F(0x046639b2) /* 0.274957367 */, 18 }, - - /* 4400 */ { MAD_F(0x04669116) /* 0.275040710 */, 18 }, - /* 4401 */ { MAD_F(0x0466e87c) /* 0.275124059 */, 18 }, - /* 4402 */ { MAD_F(0x04673fe3) /* 0.275207414 */, 18 }, - /* 4403 */ { MAD_F(0x0467974d) /* 0.275290775 */, 18 }, - /* 4404 */ { MAD_F(0x0467eeb7) /* 0.275374143 */, 18 }, - /* 4405 */ { MAD_F(0x04684624) /* 0.275457517 */, 18 }, - /* 4406 */ { MAD_F(0x04689d92) /* 0.275540897 */, 18 }, - /* 4407 */ { MAD_F(0x0468f502) /* 0.275624284 */, 18 }, - /* 4408 */ { MAD_F(0x04694c74) /* 0.275707677 */, 18 }, - /* 4409 */ { MAD_F(0x0469a3e7) /* 0.275791076 */, 18 }, - /* 4410 */ { MAD_F(0x0469fb5c) /* 0.275874482 */, 18 }, - /* 4411 */ { MAD_F(0x046a52d3) /* 0.275957894 */, 18 }, - /* 4412 */ { MAD_F(0x046aaa4b) /* 0.276041312 */, 18 }, - /* 4413 */ { MAD_F(0x046b01c5) /* 0.276124737 */, 18 }, - /* 4414 */ { MAD_F(0x046b5941) /* 0.276208167 */, 18 }, - /* 4415 */ { MAD_F(0x046bb0bf) /* 0.276291605 */, 18 }, - - /* 4416 */ { MAD_F(0x046c083e) /* 0.276375048 */, 18 }, - /* 4417 */ { MAD_F(0x046c5fbf) /* 0.276458498 */, 18 }, - /* 4418 */ { MAD_F(0x046cb741) /* 0.276541954 */, 18 }, - /* 4419 */ { MAD_F(0x046d0ec5) /* 0.276625416 */, 18 }, - /* 4420 */ { MAD_F(0x046d664b) /* 0.276708885 */, 18 }, - /* 4421 */ { MAD_F(0x046dbdd3) /* 0.276792360 */, 18 }, - /* 4422 */ { MAD_F(0x046e155c) /* 0.276875841 */, 18 }, - /* 4423 */ { MAD_F(0x046e6ce7) /* 0.276959328 */, 18 }, - /* 4424 */ { MAD_F(0x046ec474) /* 0.277042822 */, 18 }, - /* 4425 */ { MAD_F(0x046f1c02) /* 0.277126322 */, 18 }, - /* 4426 */ { MAD_F(0x046f7392) /* 0.277209829 */, 18 }, - /* 4427 */ { MAD_F(0x046fcb24) /* 0.277293341 */, 18 }, - /* 4428 */ { MAD_F(0x047022b8) /* 0.277376860 */, 18 }, - /* 4429 */ { MAD_F(0x04707a4d) /* 0.277460385 */, 18 }, - /* 4430 */ { MAD_F(0x0470d1e4) /* 0.277543917 */, 18 }, - /* 4431 */ { MAD_F(0x0471297c) /* 0.277627455 */, 18 }, - - /* 4432 */ { MAD_F(0x04718116) /* 0.277710999 */, 18 }, - /* 4433 */ { MAD_F(0x0471d8b2) /* 0.277794549 */, 18 }, - /* 4434 */ { MAD_F(0x04723050) /* 0.277878106 */, 18 }, - /* 4435 */ { MAD_F(0x047287ef) /* 0.277961669 */, 18 }, - /* 4436 */ { MAD_F(0x0472df90) /* 0.278045238 */, 18 }, - /* 4437 */ { MAD_F(0x04733733) /* 0.278128813 */, 18 }, - /* 4438 */ { MAD_F(0x04738ed7) /* 0.278212395 */, 18 }, - /* 4439 */ { MAD_F(0x0473e67d) /* 0.278295983 */, 18 }, - /* 4440 */ { MAD_F(0x04743e25) /* 0.278379578 */, 18 }, - /* 4441 */ { MAD_F(0x047495ce) /* 0.278463178 */, 18 }, - /* 4442 */ { MAD_F(0x0474ed79) /* 0.278546785 */, 18 }, - /* 4443 */ { MAD_F(0x04754526) /* 0.278630398 */, 18 }, - /* 4444 */ { MAD_F(0x04759cd4) /* 0.278714018 */, 18 }, - /* 4445 */ { MAD_F(0x0475f484) /* 0.278797643 */, 18 }, - /* 4446 */ { MAD_F(0x04764c36) /* 0.278881275 */, 18 }, - /* 4447 */ { MAD_F(0x0476a3ea) /* 0.278964914 */, 18 }, - - /* 4448 */ { MAD_F(0x0476fb9f) /* 0.279048558 */, 18 }, - /* 4449 */ { MAD_F(0x04775356) /* 0.279132209 */, 18 }, - /* 4450 */ { MAD_F(0x0477ab0e) /* 0.279215866 */, 18 }, - /* 4451 */ { MAD_F(0x047802c8) /* 0.279299529 */, 18 }, - /* 4452 */ { MAD_F(0x04785a84) /* 0.279383199 */, 18 }, - /* 4453 */ { MAD_F(0x0478b242) /* 0.279466875 */, 18 }, - /* 4454 */ { MAD_F(0x04790a01) /* 0.279550557 */, 18 }, - /* 4455 */ { MAD_F(0x047961c2) /* 0.279634245 */, 18 }, - /* 4456 */ { MAD_F(0x0479b984) /* 0.279717940 */, 18 }, - /* 4457 */ { MAD_F(0x047a1149) /* 0.279801641 */, 18 }, - /* 4458 */ { MAD_F(0x047a690f) /* 0.279885348 */, 18 }, - /* 4459 */ { MAD_F(0x047ac0d6) /* 0.279969061 */, 18 }, - /* 4460 */ { MAD_F(0x047b18a0) /* 0.280052781 */, 18 }, - /* 4461 */ { MAD_F(0x047b706b) /* 0.280136507 */, 18 }, - /* 4462 */ { MAD_F(0x047bc837) /* 0.280220239 */, 18 }, - /* 4463 */ { MAD_F(0x047c2006) /* 0.280303978 */, 18 }, - - /* 4464 */ { MAD_F(0x047c77d6) /* 0.280387722 */, 18 }, - /* 4465 */ { MAD_F(0x047ccfa8) /* 0.280471473 */, 18 }, - /* 4466 */ { MAD_F(0x047d277b) /* 0.280555230 */, 18 }, - /* 4467 */ { MAD_F(0x047d7f50) /* 0.280638994 */, 18 }, - /* 4468 */ { MAD_F(0x047dd727) /* 0.280722764 */, 18 }, - /* 4469 */ { MAD_F(0x047e2eff) /* 0.280806540 */, 18 }, - /* 4470 */ { MAD_F(0x047e86d9) /* 0.280890322 */, 18 }, - /* 4471 */ { MAD_F(0x047edeb5) /* 0.280974110 */, 18 }, - /* 4472 */ { MAD_F(0x047f3693) /* 0.281057905 */, 18 }, - /* 4473 */ { MAD_F(0x047f8e72) /* 0.281141706 */, 18 }, - /* 4474 */ { MAD_F(0x047fe653) /* 0.281225513 */, 18 }, - /* 4475 */ { MAD_F(0x04803e35) /* 0.281309326 */, 18 }, - /* 4476 */ { MAD_F(0x04809619) /* 0.281393146 */, 18 }, - /* 4477 */ { MAD_F(0x0480edff) /* 0.281476972 */, 18 }, - /* 4478 */ { MAD_F(0x048145e7) /* 0.281560804 */, 18 }, - /* 4479 */ { MAD_F(0x04819dd0) /* 0.281644643 */, 18 }, - - /* 4480 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 18 }, - /* 4481 */ { MAD_F(0x04824da7) /* 0.281812338 */, 18 }, - /* 4482 */ { MAD_F(0x0482a595) /* 0.281896195 */, 18 }, - /* 4483 */ { MAD_F(0x0482fd85) /* 0.281980059 */, 18 }, - /* 4484 */ { MAD_F(0x04835577) /* 0.282063928 */, 18 }, - /* 4485 */ { MAD_F(0x0483ad6a) /* 0.282147804 */, 18 }, - /* 4486 */ { MAD_F(0x0484055f) /* 0.282231686 */, 18 }, - /* 4487 */ { MAD_F(0x04845d56) /* 0.282315574 */, 18 }, - /* 4488 */ { MAD_F(0x0484b54e) /* 0.282399469 */, 18 }, - /* 4489 */ { MAD_F(0x04850d48) /* 0.282483370 */, 18 }, - /* 4490 */ { MAD_F(0x04856544) /* 0.282567277 */, 18 }, - /* 4491 */ { MAD_F(0x0485bd41) /* 0.282651190 */, 18 }, - /* 4492 */ { MAD_F(0x04861540) /* 0.282735109 */, 18 }, - /* 4493 */ { MAD_F(0x04866d40) /* 0.282819035 */, 18 }, - /* 4494 */ { MAD_F(0x0486c543) /* 0.282902967 */, 18 }, - /* 4495 */ { MAD_F(0x04871d47) /* 0.282986905 */, 18 }, - - /* 4496 */ { MAD_F(0x0487754c) /* 0.283070849 */, 18 }, - /* 4497 */ { MAD_F(0x0487cd54) /* 0.283154800 */, 18 }, - /* 4498 */ { MAD_F(0x0488255d) /* 0.283238757 */, 18 }, - /* 4499 */ { MAD_F(0x04887d67) /* 0.283322720 */, 18 }, - /* 4500 */ { MAD_F(0x0488d574) /* 0.283406689 */, 18 }, - /* 4501 */ { MAD_F(0x04892d82) /* 0.283490665 */, 18 }, - /* 4502 */ { MAD_F(0x04898591) /* 0.283574646 */, 18 }, - /* 4503 */ { MAD_F(0x0489dda3) /* 0.283658634 */, 18 }, - /* 4504 */ { MAD_F(0x048a35b6) /* 0.283742628 */, 18 }, - /* 4505 */ { MAD_F(0x048a8dca) /* 0.283826629 */, 18 }, - /* 4506 */ { MAD_F(0x048ae5e1) /* 0.283910635 */, 18 }, - /* 4507 */ { MAD_F(0x048b3df9) /* 0.283994648 */, 18 }, - /* 4508 */ { MAD_F(0x048b9612) /* 0.284078667 */, 18 }, - /* 4509 */ { MAD_F(0x048bee2e) /* 0.284162692 */, 18 }, - /* 4510 */ { MAD_F(0x048c464b) /* 0.284246723 */, 18 }, - /* 4511 */ { MAD_F(0x048c9e69) /* 0.284330761 */, 18 }, - - /* 4512 */ { MAD_F(0x048cf68a) /* 0.284414805 */, 18 }, - /* 4513 */ { MAD_F(0x048d4eac) /* 0.284498855 */, 18 }, - /* 4514 */ { MAD_F(0x048da6cf) /* 0.284582911 */, 18 }, - /* 4515 */ { MAD_F(0x048dfef5) /* 0.284666974 */, 18 }, - /* 4516 */ { MAD_F(0x048e571c) /* 0.284751042 */, 18 }, - /* 4517 */ { MAD_F(0x048eaf44) /* 0.284835117 */, 18 }, - /* 4518 */ { MAD_F(0x048f076f) /* 0.284919198 */, 18 }, - /* 4519 */ { MAD_F(0x048f5f9b) /* 0.285003285 */, 18 }, - /* 4520 */ { MAD_F(0x048fb7c8) /* 0.285087379 */, 18 }, - /* 4521 */ { MAD_F(0x04900ff8) /* 0.285171479 */, 18 }, - /* 4522 */ { MAD_F(0x04906829) /* 0.285255584 */, 18 }, - /* 4523 */ { MAD_F(0x0490c05b) /* 0.285339697 */, 18 }, - /* 4524 */ { MAD_F(0x04911890) /* 0.285423815 */, 18 }, - /* 4525 */ { MAD_F(0x049170c6) /* 0.285507939 */, 18 }, - /* 4526 */ { MAD_F(0x0491c8fd) /* 0.285592070 */, 18 }, - /* 4527 */ { MAD_F(0x04922137) /* 0.285676207 */, 18 }, - - /* 4528 */ { MAD_F(0x04927972) /* 0.285760350 */, 18 }, - /* 4529 */ { MAD_F(0x0492d1ae) /* 0.285844499 */, 18 }, - /* 4530 */ { MAD_F(0x049329ed) /* 0.285928655 */, 18 }, - /* 4531 */ { MAD_F(0x0493822c) /* 0.286012816 */, 18 }, - /* 4532 */ { MAD_F(0x0493da6e) /* 0.286096984 */, 18 }, - /* 4533 */ { MAD_F(0x049432b1) /* 0.286181158 */, 18 }, - /* 4534 */ { MAD_F(0x04948af6) /* 0.286265338 */, 18 }, - /* 4535 */ { MAD_F(0x0494e33d) /* 0.286349525 */, 18 }, - /* 4536 */ { MAD_F(0x04953b85) /* 0.286433717 */, 18 }, - /* 4537 */ { MAD_F(0x049593cf) /* 0.286517916 */, 18 }, - /* 4538 */ { MAD_F(0x0495ec1b) /* 0.286602121 */, 18 }, - /* 4539 */ { MAD_F(0x04964468) /* 0.286686332 */, 18 }, - /* 4540 */ { MAD_F(0x04969cb7) /* 0.286770550 */, 18 }, - /* 4541 */ { MAD_F(0x0496f508) /* 0.286854773 */, 18 }, - /* 4542 */ { MAD_F(0x04974d5a) /* 0.286939003 */, 18 }, - /* 4543 */ { MAD_F(0x0497a5ae) /* 0.287023239 */, 18 }, - - /* 4544 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 18 }, - /* 4545 */ { MAD_F(0x0498565a) /* 0.287191729 */, 18 }, - /* 4546 */ { MAD_F(0x0498aeb3) /* 0.287275983 */, 18 }, - /* 4547 */ { MAD_F(0x0499070e) /* 0.287360244 */, 18 }, - /* 4548 */ { MAD_F(0x04995f6a) /* 0.287444511 */, 18 }, - /* 4549 */ { MAD_F(0x0499b7c8) /* 0.287528784 */, 18 }, - /* 4550 */ { MAD_F(0x049a1027) /* 0.287613063 */, 18 }, - /* 4551 */ { MAD_F(0x049a6889) /* 0.287697348 */, 18 }, - /* 4552 */ { MAD_F(0x049ac0eb) /* 0.287781640 */, 18 }, - /* 4553 */ { MAD_F(0x049b1950) /* 0.287865937 */, 18 }, - /* 4554 */ { MAD_F(0x049b71b6) /* 0.287950241 */, 18 }, - /* 4555 */ { MAD_F(0x049bca1e) /* 0.288034551 */, 18 }, - /* 4556 */ { MAD_F(0x049c2287) /* 0.288118867 */, 18 }, - /* 4557 */ { MAD_F(0x049c7af2) /* 0.288203190 */, 18 }, - /* 4558 */ { MAD_F(0x049cd35f) /* 0.288287518 */, 18 }, - /* 4559 */ { MAD_F(0x049d2bce) /* 0.288371853 */, 18 }, - - /* 4560 */ { MAD_F(0x049d843e) /* 0.288456194 */, 18 }, - /* 4561 */ { MAD_F(0x049ddcaf) /* 0.288540541 */, 18 }, - /* 4562 */ { MAD_F(0x049e3523) /* 0.288624894 */, 18 }, - /* 4563 */ { MAD_F(0x049e8d98) /* 0.288709253 */, 18 }, - /* 4564 */ { MAD_F(0x049ee60e) /* 0.288793619 */, 18 }, - /* 4565 */ { MAD_F(0x049f3e87) /* 0.288877990 */, 18 }, - /* 4566 */ { MAD_F(0x049f9701) /* 0.288962368 */, 18 }, - /* 4567 */ { MAD_F(0x049fef7c) /* 0.289046752 */, 18 }, - /* 4568 */ { MAD_F(0x04a047fa) /* 0.289131142 */, 18 }, - /* 4569 */ { MAD_F(0x04a0a079) /* 0.289215538 */, 18 }, - /* 4570 */ { MAD_F(0x04a0f8f9) /* 0.289299941 */, 18 }, - /* 4571 */ { MAD_F(0x04a1517c) /* 0.289384349 */, 18 }, - /* 4572 */ { MAD_F(0x04a1a9ff) /* 0.289468764 */, 18 }, - /* 4573 */ { MAD_F(0x04a20285) /* 0.289553185 */, 18 }, - /* 4574 */ { MAD_F(0x04a25b0c) /* 0.289637612 */, 18 }, - /* 4575 */ { MAD_F(0x04a2b395) /* 0.289722045 */, 18 }, - - /* 4576 */ { MAD_F(0x04a30c20) /* 0.289806485 */, 18 }, - /* 4577 */ { MAD_F(0x04a364ac) /* 0.289890930 */, 18 }, - /* 4578 */ { MAD_F(0x04a3bd3a) /* 0.289975382 */, 18 }, - /* 4579 */ { MAD_F(0x04a415c9) /* 0.290059840 */, 18 }, - /* 4580 */ { MAD_F(0x04a46e5a) /* 0.290144304 */, 18 }, - /* 4581 */ { MAD_F(0x04a4c6ed) /* 0.290228774 */, 18 }, - /* 4582 */ { MAD_F(0x04a51f81) /* 0.290313250 */, 18 }, - /* 4583 */ { MAD_F(0x04a57818) /* 0.290397733 */, 18 }, - /* 4584 */ { MAD_F(0x04a5d0af) /* 0.290482221 */, 18 }, - /* 4585 */ { MAD_F(0x04a62949) /* 0.290566716 */, 18 }, - /* 4586 */ { MAD_F(0x04a681e4) /* 0.290651217 */, 18 }, - /* 4587 */ { MAD_F(0x04a6da80) /* 0.290735724 */, 18 }, - /* 4588 */ { MAD_F(0x04a7331f) /* 0.290820237 */, 18 }, - /* 4589 */ { MAD_F(0x04a78bbf) /* 0.290904756 */, 18 }, - /* 4590 */ { MAD_F(0x04a7e460) /* 0.290989281 */, 18 }, - /* 4591 */ { MAD_F(0x04a83d03) /* 0.291073813 */, 18 }, - - /* 4592 */ { MAD_F(0x04a895a8) /* 0.291158351 */, 18 }, - /* 4593 */ { MAD_F(0x04a8ee4f) /* 0.291242894 */, 18 }, - /* 4594 */ { MAD_F(0x04a946f7) /* 0.291327444 */, 18 }, - /* 4595 */ { MAD_F(0x04a99fa1) /* 0.291412001 */, 18 }, - /* 4596 */ { MAD_F(0x04a9f84c) /* 0.291496563 */, 18 }, - /* 4597 */ { MAD_F(0x04aa50fa) /* 0.291581131 */, 18 }, - /* 4598 */ { MAD_F(0x04aaa9a8) /* 0.291665706 */, 18 }, - /* 4599 */ { MAD_F(0x04ab0259) /* 0.291750286 */, 18 }, - /* 4600 */ { MAD_F(0x04ab5b0b) /* 0.291834873 */, 18 }, - /* 4601 */ { MAD_F(0x04abb3bf) /* 0.291919466 */, 18 }, - /* 4602 */ { MAD_F(0x04ac0c74) /* 0.292004065 */, 18 }, - /* 4603 */ { MAD_F(0x04ac652b) /* 0.292088670 */, 18 }, - /* 4604 */ { MAD_F(0x04acbde4) /* 0.292173281 */, 18 }, - /* 4605 */ { MAD_F(0x04ad169e) /* 0.292257899 */, 18 }, - /* 4606 */ { MAD_F(0x04ad6f5a) /* 0.292342522 */, 18 }, - /* 4607 */ { MAD_F(0x04adc818) /* 0.292427152 */, 18 }, - - /* 4608 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 18 }, - /* 4609 */ { MAD_F(0x04ae7998) /* 0.292596430 */, 18 }, - /* 4610 */ { MAD_F(0x04aed25a) /* 0.292681078 */, 18 }, - /* 4611 */ { MAD_F(0x04af2b1e) /* 0.292765732 */, 18 }, - /* 4612 */ { MAD_F(0x04af83e4) /* 0.292850392 */, 18 }, - /* 4613 */ { MAD_F(0x04afdcac) /* 0.292935058 */, 18 }, - /* 4614 */ { MAD_F(0x04b03575) /* 0.293019731 */, 18 }, - /* 4615 */ { MAD_F(0x04b08e40) /* 0.293104409 */, 18 }, - /* 4616 */ { MAD_F(0x04b0e70c) /* 0.293189094 */, 18 }, - /* 4617 */ { MAD_F(0x04b13fda) /* 0.293273785 */, 18 }, - /* 4618 */ { MAD_F(0x04b198aa) /* 0.293358482 */, 18 }, - /* 4619 */ { MAD_F(0x04b1f17b) /* 0.293443185 */, 18 }, - /* 4620 */ { MAD_F(0x04b24a4e) /* 0.293527894 */, 18 }, - /* 4621 */ { MAD_F(0x04b2a322) /* 0.293612609 */, 18 }, - /* 4622 */ { MAD_F(0x04b2fbf9) /* 0.293697331 */, 18 }, - /* 4623 */ { MAD_F(0x04b354d1) /* 0.293782058 */, 18 }, - - /* 4624 */ { MAD_F(0x04b3adaa) /* 0.293866792 */, 18 }, - /* 4625 */ { MAD_F(0x04b40685) /* 0.293951532 */, 18 }, - /* 4626 */ { MAD_F(0x04b45f62) /* 0.294036278 */, 18 }, - /* 4627 */ { MAD_F(0x04b4b840) /* 0.294121029 */, 18 }, - /* 4628 */ { MAD_F(0x04b51120) /* 0.294205788 */, 18 }, - /* 4629 */ { MAD_F(0x04b56a02) /* 0.294290552 */, 18 }, - /* 4630 */ { MAD_F(0x04b5c2e6) /* 0.294375322 */, 18 }, - /* 4631 */ { MAD_F(0x04b61bcb) /* 0.294460098 */, 18 }, - /* 4632 */ { MAD_F(0x04b674b1) /* 0.294544881 */, 18 }, - /* 4633 */ { MAD_F(0x04b6cd99) /* 0.294629669 */, 18 }, - /* 4634 */ { MAD_F(0x04b72683) /* 0.294714464 */, 18 }, - /* 4635 */ { MAD_F(0x04b77f6f) /* 0.294799265 */, 18 }, - /* 4636 */ { MAD_F(0x04b7d85c) /* 0.294884072 */, 18 }, - /* 4637 */ { MAD_F(0x04b8314b) /* 0.294968885 */, 18 }, - /* 4638 */ { MAD_F(0x04b88a3b) /* 0.295053704 */, 18 }, - /* 4639 */ { MAD_F(0x04b8e32d) /* 0.295138529 */, 18 }, - - /* 4640 */ { MAD_F(0x04b93c21) /* 0.295223360 */, 18 }, - /* 4641 */ { MAD_F(0x04b99516) /* 0.295308197 */, 18 }, - /* 4642 */ { MAD_F(0x04b9ee0d) /* 0.295393041 */, 18 }, - /* 4643 */ { MAD_F(0x04ba4706) /* 0.295477890 */, 18 }, - /* 4644 */ { MAD_F(0x04baa000) /* 0.295562746 */, 18 }, - /* 4645 */ { MAD_F(0x04baf8fc) /* 0.295647608 */, 18 }, - /* 4646 */ { MAD_F(0x04bb51fa) /* 0.295732476 */, 18 }, - /* 4647 */ { MAD_F(0x04bbaaf9) /* 0.295817349 */, 18 }, - /* 4648 */ { MAD_F(0x04bc03fa) /* 0.295902229 */, 18 }, - /* 4649 */ { MAD_F(0x04bc5cfc) /* 0.295987115 */, 18 }, - /* 4650 */ { MAD_F(0x04bcb600) /* 0.296072008 */, 18 }, - /* 4651 */ { MAD_F(0x04bd0f06) /* 0.296156906 */, 18 }, - /* 4652 */ { MAD_F(0x04bd680d) /* 0.296241810 */, 18 }, - /* 4653 */ { MAD_F(0x04bdc116) /* 0.296326721 */, 18 }, - /* 4654 */ { MAD_F(0x04be1a21) /* 0.296411637 */, 18 }, - /* 4655 */ { MAD_F(0x04be732d) /* 0.296496560 */, 18 }, - - /* 4656 */ { MAD_F(0x04becc3b) /* 0.296581488 */, 18 }, - /* 4657 */ { MAD_F(0x04bf254a) /* 0.296666423 */, 18 }, - /* 4658 */ { MAD_F(0x04bf7e5b) /* 0.296751364 */, 18 }, - /* 4659 */ { MAD_F(0x04bfd76e) /* 0.296836311 */, 18 }, - /* 4660 */ { MAD_F(0x04c03083) /* 0.296921264 */, 18 }, - /* 4661 */ { MAD_F(0x04c08999) /* 0.297006223 */, 18 }, - /* 4662 */ { MAD_F(0x04c0e2b0) /* 0.297091188 */, 18 }, - /* 4663 */ { MAD_F(0x04c13bca) /* 0.297176159 */, 18 }, - /* 4664 */ { MAD_F(0x04c194e4) /* 0.297261136 */, 18 }, - /* 4665 */ { MAD_F(0x04c1ee01) /* 0.297346120 */, 18 }, - /* 4666 */ { MAD_F(0x04c2471f) /* 0.297431109 */, 18 }, - /* 4667 */ { MAD_F(0x04c2a03f) /* 0.297516105 */, 18 }, - /* 4668 */ { MAD_F(0x04c2f960) /* 0.297601106 */, 18 }, - /* 4669 */ { MAD_F(0x04c35283) /* 0.297686114 */, 18 }, - /* 4670 */ { MAD_F(0x04c3aba8) /* 0.297771128 */, 18 }, - /* 4671 */ { MAD_F(0x04c404ce) /* 0.297856147 */, 18 }, - - /* 4672 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 18 }, - /* 4673 */ { MAD_F(0x04c4b720) /* 0.298026205 */, 18 }, - /* 4674 */ { MAD_F(0x04c5104b) /* 0.298111243 */, 18 }, - /* 4675 */ { MAD_F(0x04c56978) /* 0.298196287 */, 18 }, - /* 4676 */ { MAD_F(0x04c5c2a7) /* 0.298281337 */, 18 }, - /* 4677 */ { MAD_F(0x04c61bd7) /* 0.298366393 */, 18 }, - /* 4678 */ { MAD_F(0x04c67508) /* 0.298451456 */, 18 }, - /* 4679 */ { MAD_F(0x04c6ce3c) /* 0.298536524 */, 18 }, - /* 4680 */ { MAD_F(0x04c72771) /* 0.298621598 */, 18 }, - /* 4681 */ { MAD_F(0x04c780a7) /* 0.298706679 */, 18 }, - /* 4682 */ { MAD_F(0x04c7d9df) /* 0.298791765 */, 18 }, - /* 4683 */ { MAD_F(0x04c83319) /* 0.298876858 */, 18 }, - /* 4684 */ { MAD_F(0x04c88c55) /* 0.298961956 */, 18 }, - /* 4685 */ { MAD_F(0x04c8e592) /* 0.299047061 */, 18 }, - /* 4686 */ { MAD_F(0x04c93ed1) /* 0.299132172 */, 18 }, - /* 4687 */ { MAD_F(0x04c99811) /* 0.299217288 */, 18 }, - - /* 4688 */ { MAD_F(0x04c9f153) /* 0.299302411 */, 18 }, - /* 4689 */ { MAD_F(0x04ca4a97) /* 0.299387540 */, 18 }, - /* 4690 */ { MAD_F(0x04caa3dc) /* 0.299472675 */, 18 }, - /* 4691 */ { MAD_F(0x04cafd23) /* 0.299557816 */, 18 }, - /* 4692 */ { MAD_F(0x04cb566b) /* 0.299642963 */, 18 }, - /* 4693 */ { MAD_F(0x04cbafb5) /* 0.299728116 */, 18 }, - /* 4694 */ { MAD_F(0x04cc0901) /* 0.299813275 */, 18 }, - /* 4695 */ { MAD_F(0x04cc624e) /* 0.299898440 */, 18 }, - /* 4696 */ { MAD_F(0x04ccbb9d) /* 0.299983611 */, 18 }, - /* 4697 */ { MAD_F(0x04cd14ee) /* 0.300068789 */, 18 }, - /* 4698 */ { MAD_F(0x04cd6e40) /* 0.300153972 */, 18 }, - /* 4699 */ { MAD_F(0x04cdc794) /* 0.300239161 */, 18 }, - /* 4700 */ { MAD_F(0x04ce20e9) /* 0.300324357 */, 18 }, - /* 4701 */ { MAD_F(0x04ce7a40) /* 0.300409558 */, 18 }, - /* 4702 */ { MAD_F(0x04ced399) /* 0.300494765 */, 18 }, - /* 4703 */ { MAD_F(0x04cf2cf3) /* 0.300579979 */, 18 }, - - /* 4704 */ { MAD_F(0x04cf864f) /* 0.300665198 */, 18 }, - /* 4705 */ { MAD_F(0x04cfdfad) /* 0.300750424 */, 18 }, - /* 4706 */ { MAD_F(0x04d0390c) /* 0.300835656 */, 18 }, - /* 4707 */ { MAD_F(0x04d0926d) /* 0.300920893 */, 18 }, - /* 4708 */ { MAD_F(0x04d0ebcf) /* 0.301006137 */, 18 }, - /* 4709 */ { MAD_F(0x04d14533) /* 0.301091387 */, 18 }, - /* 4710 */ { MAD_F(0x04d19e99) /* 0.301176643 */, 18 }, - /* 4711 */ { MAD_F(0x04d1f800) /* 0.301261904 */, 18 }, - /* 4712 */ { MAD_F(0x04d25169) /* 0.301347172 */, 18 }, - /* 4713 */ { MAD_F(0x04d2aad4) /* 0.301432446 */, 18 }, - /* 4714 */ { MAD_F(0x04d30440) /* 0.301517726 */, 18 }, - /* 4715 */ { MAD_F(0x04d35dae) /* 0.301603012 */, 18 }, - /* 4716 */ { MAD_F(0x04d3b71d) /* 0.301688304 */, 18 }, - /* 4717 */ { MAD_F(0x04d4108e) /* 0.301773602 */, 18 }, - /* 4718 */ { MAD_F(0x04d46a01) /* 0.301858906 */, 18 }, - /* 4719 */ { MAD_F(0x04d4c375) /* 0.301944216 */, 18 }, - - /* 4720 */ { MAD_F(0x04d51ceb) /* 0.302029532 */, 18 }, - /* 4721 */ { MAD_F(0x04d57662) /* 0.302114854 */, 18 }, - /* 4722 */ { MAD_F(0x04d5cfdb) /* 0.302200182 */, 18 }, - /* 4723 */ { MAD_F(0x04d62956) /* 0.302285516 */, 18 }, - /* 4724 */ { MAD_F(0x04d682d2) /* 0.302370856 */, 18 }, - /* 4725 */ { MAD_F(0x04d6dc50) /* 0.302456203 */, 18 }, - /* 4726 */ { MAD_F(0x04d735d0) /* 0.302541555 */, 18 }, - /* 4727 */ { MAD_F(0x04d78f51) /* 0.302626913 */, 18 }, - /* 4728 */ { MAD_F(0x04d7e8d4) /* 0.302712277 */, 18 }, - /* 4729 */ { MAD_F(0x04d84258) /* 0.302797648 */, 18 }, - /* 4730 */ { MAD_F(0x04d89bde) /* 0.302883024 */, 18 }, - /* 4731 */ { MAD_F(0x04d8f566) /* 0.302968406 */, 18 }, - /* 4732 */ { MAD_F(0x04d94eef) /* 0.303053794 */, 18 }, - /* 4733 */ { MAD_F(0x04d9a87a) /* 0.303139189 */, 18 }, - /* 4734 */ { MAD_F(0x04da0207) /* 0.303224589 */, 18 }, - /* 4735 */ { MAD_F(0x04da5b95) /* 0.303309995 */, 18 }, - - /* 4736 */ { MAD_F(0x04dab524) /* 0.303395408 */, 18 }, - /* 4737 */ { MAD_F(0x04db0eb6) /* 0.303480826 */, 18 }, - /* 4738 */ { MAD_F(0x04db6849) /* 0.303566251 */, 18 }, - /* 4739 */ { MAD_F(0x04dbc1dd) /* 0.303651681 */, 18 }, - /* 4740 */ { MAD_F(0x04dc1b73) /* 0.303737117 */, 18 }, - /* 4741 */ { MAD_F(0x04dc750b) /* 0.303822560 */, 18 }, - /* 4742 */ { MAD_F(0x04dccea5) /* 0.303908008 */, 18 }, - /* 4743 */ { MAD_F(0x04dd2840) /* 0.303993463 */, 18 }, - /* 4744 */ { MAD_F(0x04dd81dc) /* 0.304078923 */, 18 }, - /* 4745 */ { MAD_F(0x04dddb7a) /* 0.304164390 */, 18 }, - /* 4746 */ { MAD_F(0x04de351a) /* 0.304249862 */, 18 }, - /* 4747 */ { MAD_F(0x04de8ebc) /* 0.304335340 */, 18 }, - /* 4748 */ { MAD_F(0x04dee85f) /* 0.304420825 */, 18 }, - /* 4749 */ { MAD_F(0x04df4203) /* 0.304506315 */, 18 }, - /* 4750 */ { MAD_F(0x04df9baa) /* 0.304591812 */, 18 }, - /* 4751 */ { MAD_F(0x04dff552) /* 0.304677314 */, 18 }, - - /* 4752 */ { MAD_F(0x04e04efb) /* 0.304762823 */, 18 }, - /* 4753 */ { MAD_F(0x04e0a8a6) /* 0.304848337 */, 18 }, - /* 4754 */ { MAD_F(0x04e10253) /* 0.304933858 */, 18 }, - /* 4755 */ { MAD_F(0x04e15c01) /* 0.305019384 */, 18 }, - /* 4756 */ { MAD_F(0x04e1b5b1) /* 0.305104917 */, 18 }, - /* 4757 */ { MAD_F(0x04e20f63) /* 0.305190455 */, 18 }, - /* 4758 */ { MAD_F(0x04e26916) /* 0.305275999 */, 18 }, - /* 4759 */ { MAD_F(0x04e2c2cb) /* 0.305361550 */, 18 }, - /* 4760 */ { MAD_F(0x04e31c81) /* 0.305447106 */, 18 }, - /* 4761 */ { MAD_F(0x04e37639) /* 0.305532669 */, 18 }, - /* 4762 */ { MAD_F(0x04e3cff3) /* 0.305618237 */, 18 }, - /* 4763 */ { MAD_F(0x04e429ae) /* 0.305703811 */, 18 }, - /* 4764 */ { MAD_F(0x04e4836b) /* 0.305789392 */, 18 }, - /* 4765 */ { MAD_F(0x04e4dd29) /* 0.305874978 */, 18 }, - /* 4766 */ { MAD_F(0x04e536e9) /* 0.305960571 */, 18 }, - /* 4767 */ { MAD_F(0x04e590ab) /* 0.306046169 */, 18 }, - - /* 4768 */ { MAD_F(0x04e5ea6e) /* 0.306131773 */, 18 }, - /* 4769 */ { MAD_F(0x04e64433) /* 0.306217383 */, 18 }, - /* 4770 */ { MAD_F(0x04e69df9) /* 0.306303000 */, 18 }, - /* 4771 */ { MAD_F(0x04e6f7c1) /* 0.306388622 */, 18 }, - /* 4772 */ { MAD_F(0x04e7518b) /* 0.306474250 */, 18 }, - /* 4773 */ { MAD_F(0x04e7ab56) /* 0.306559885 */, 18 }, - /* 4774 */ { MAD_F(0x04e80523) /* 0.306645525 */, 18 }, - /* 4775 */ { MAD_F(0x04e85ef2) /* 0.306731171 */, 18 }, - /* 4776 */ { MAD_F(0x04e8b8c2) /* 0.306816823 */, 18 }, - /* 4777 */ { MAD_F(0x04e91293) /* 0.306902481 */, 18 }, - /* 4778 */ { MAD_F(0x04e96c67) /* 0.306988145 */, 18 }, - /* 4779 */ { MAD_F(0x04e9c63b) /* 0.307073816 */, 18 }, - /* 4780 */ { MAD_F(0x04ea2012) /* 0.307159492 */, 18 }, - /* 4781 */ { MAD_F(0x04ea79ea) /* 0.307245174 */, 18 }, - /* 4782 */ { MAD_F(0x04ead3c4) /* 0.307330862 */, 18 }, - /* 4783 */ { MAD_F(0x04eb2d9f) /* 0.307416556 */, 18 }, - - /* 4784 */ { MAD_F(0x04eb877c) /* 0.307502256 */, 18 }, - /* 4785 */ { MAD_F(0x04ebe15b) /* 0.307587962 */, 18 }, - /* 4786 */ { MAD_F(0x04ec3b3b) /* 0.307673674 */, 18 }, - /* 4787 */ { MAD_F(0x04ec951c) /* 0.307759392 */, 18 }, - /* 4788 */ { MAD_F(0x04ecef00) /* 0.307845115 */, 18 }, - /* 4789 */ { MAD_F(0x04ed48e5) /* 0.307930845 */, 18 }, - /* 4790 */ { MAD_F(0x04eda2cb) /* 0.308016581 */, 18 }, - /* 4791 */ { MAD_F(0x04edfcb3) /* 0.308102323 */, 18 }, - /* 4792 */ { MAD_F(0x04ee569d) /* 0.308188071 */, 18 }, - /* 4793 */ { MAD_F(0x04eeb088) /* 0.308273824 */, 18 }, - /* 4794 */ { MAD_F(0x04ef0a75) /* 0.308359584 */, 18 }, - /* 4795 */ { MAD_F(0x04ef6464) /* 0.308445350 */, 18 }, - /* 4796 */ { MAD_F(0x04efbe54) /* 0.308531121 */, 18 }, - /* 4797 */ { MAD_F(0x04f01846) /* 0.308616899 */, 18 }, - /* 4798 */ { MAD_F(0x04f07239) /* 0.308702682 */, 18 }, - /* 4799 */ { MAD_F(0x04f0cc2e) /* 0.308788472 */, 18 }, - - /* 4800 */ { MAD_F(0x04f12624) /* 0.308874267 */, 18 }, - /* 4801 */ { MAD_F(0x04f1801d) /* 0.308960068 */, 18 }, - /* 4802 */ { MAD_F(0x04f1da16) /* 0.309045876 */, 18 }, - /* 4803 */ { MAD_F(0x04f23412) /* 0.309131689 */, 18 }, - /* 4804 */ { MAD_F(0x04f28e0f) /* 0.309217508 */, 18 }, - /* 4805 */ { MAD_F(0x04f2e80d) /* 0.309303334 */, 18 }, - /* 4806 */ { MAD_F(0x04f3420d) /* 0.309389165 */, 18 }, - /* 4807 */ { MAD_F(0x04f39c0f) /* 0.309475002 */, 18 }, - /* 4808 */ { MAD_F(0x04f3f612) /* 0.309560845 */, 18 }, - /* 4809 */ { MAD_F(0x04f45017) /* 0.309646694 */, 18 }, - /* 4810 */ { MAD_F(0x04f4aa1e) /* 0.309732549 */, 18 }, - /* 4811 */ { MAD_F(0x04f50426) /* 0.309818410 */, 18 }, - /* 4812 */ { MAD_F(0x04f55e30) /* 0.309904277 */, 18 }, - /* 4813 */ { MAD_F(0x04f5b83b) /* 0.309990150 */, 18 }, - /* 4814 */ { MAD_F(0x04f61248) /* 0.310076028 */, 18 }, - /* 4815 */ { MAD_F(0x04f66c56) /* 0.310161913 */, 18 }, - - /* 4816 */ { MAD_F(0x04f6c666) /* 0.310247804 */, 18 }, - /* 4817 */ { MAD_F(0x04f72078) /* 0.310333700 */, 18 }, - /* 4818 */ { MAD_F(0x04f77a8b) /* 0.310419603 */, 18 }, - /* 4819 */ { MAD_F(0x04f7d4a0) /* 0.310505511 */, 18 }, - /* 4820 */ { MAD_F(0x04f82eb7) /* 0.310591426 */, 18 }, - /* 4821 */ { MAD_F(0x04f888cf) /* 0.310677346 */, 18 }, - /* 4822 */ { MAD_F(0x04f8e2e9) /* 0.310763272 */, 18 }, - /* 4823 */ { MAD_F(0x04f93d04) /* 0.310849205 */, 18 }, - /* 4824 */ { MAD_F(0x04f99721) /* 0.310935143 */, 18 }, - /* 4825 */ { MAD_F(0x04f9f13f) /* 0.311021087 */, 18 }, - /* 4826 */ { MAD_F(0x04fa4b5f) /* 0.311107037 */, 18 }, - /* 4827 */ { MAD_F(0x04faa581) /* 0.311192993 */, 18 }, - /* 4828 */ { MAD_F(0x04faffa4) /* 0.311278955 */, 18 }, - /* 4829 */ { MAD_F(0x04fb59c9) /* 0.311364923 */, 18 }, - /* 4830 */ { MAD_F(0x04fbb3ef) /* 0.311450897 */, 18 }, - /* 4831 */ { MAD_F(0x04fc0e17) /* 0.311536877 */, 18 }, - - /* 4832 */ { MAD_F(0x04fc6841) /* 0.311622862 */, 18 }, - /* 4833 */ { MAD_F(0x04fcc26c) /* 0.311708854 */, 18 }, - /* 4834 */ { MAD_F(0x04fd1c99) /* 0.311794851 */, 18 }, - /* 4835 */ { MAD_F(0x04fd76c7) /* 0.311880855 */, 18 }, - /* 4836 */ { MAD_F(0x04fdd0f7) /* 0.311966864 */, 18 }, - /* 4837 */ { MAD_F(0x04fe2b29) /* 0.312052880 */, 18 }, - /* 4838 */ { MAD_F(0x04fe855c) /* 0.312138901 */, 18 }, - /* 4839 */ { MAD_F(0x04fedf91) /* 0.312224928 */, 18 }, - /* 4840 */ { MAD_F(0x04ff39c7) /* 0.312310961 */, 18 }, - /* 4841 */ { MAD_F(0x04ff93ff) /* 0.312397000 */, 18 }, - /* 4842 */ { MAD_F(0x04ffee38) /* 0.312483045 */, 18 }, - /* 4843 */ { MAD_F(0x05004874) /* 0.312569096 */, 18 }, - /* 4844 */ { MAD_F(0x0500a2b0) /* 0.312655153 */, 18 }, - /* 4845 */ { MAD_F(0x0500fcef) /* 0.312741216 */, 18 }, - /* 4846 */ { MAD_F(0x0501572e) /* 0.312827284 */, 18 }, - /* 4847 */ { MAD_F(0x0501b170) /* 0.312913359 */, 18 }, - - /* 4848 */ { MAD_F(0x05020bb3) /* 0.312999439 */, 18 }, - /* 4849 */ { MAD_F(0x050265f8) /* 0.313085526 */, 18 }, - /* 4850 */ { MAD_F(0x0502c03e) /* 0.313171618 */, 18 }, - /* 4851 */ { MAD_F(0x05031a86) /* 0.313257716 */, 18 }, - /* 4852 */ { MAD_F(0x050374cf) /* 0.313343820 */, 18 }, - /* 4853 */ { MAD_F(0x0503cf1a) /* 0.313429931 */, 18 }, - /* 4854 */ { MAD_F(0x05042967) /* 0.313516047 */, 18 }, - /* 4855 */ { MAD_F(0x050483b5) /* 0.313602168 */, 18 }, - /* 4856 */ { MAD_F(0x0504de05) /* 0.313688296 */, 18 }, - /* 4857 */ { MAD_F(0x05053856) /* 0.313774430 */, 18 }, - /* 4858 */ { MAD_F(0x050592a9) /* 0.313860570 */, 18 }, - /* 4859 */ { MAD_F(0x0505ecfd) /* 0.313946715 */, 18 }, - /* 4860 */ { MAD_F(0x05064754) /* 0.314032867 */, 18 }, - /* 4861 */ { MAD_F(0x0506a1ab) /* 0.314119024 */, 18 }, - /* 4862 */ { MAD_F(0x0506fc04) /* 0.314205187 */, 18 }, - /* 4863 */ { MAD_F(0x0507565f) /* 0.314291357 */, 18 }, - - /* 4864 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 18 }, - /* 4865 */ { MAD_F(0x05080b1a) /* 0.314463713 */, 18 }, - /* 4866 */ { MAD_F(0x05086579) /* 0.314549900 */, 18 }, - /* 4867 */ { MAD_F(0x0508bfdb) /* 0.314636092 */, 18 }, - /* 4868 */ { MAD_F(0x05091a3d) /* 0.314722291 */, 18 }, - /* 4869 */ { MAD_F(0x050974a2) /* 0.314808496 */, 18 }, - /* 4870 */ { MAD_F(0x0509cf08) /* 0.314894706 */, 18 }, - /* 4871 */ { MAD_F(0x050a296f) /* 0.314980923 */, 18 }, - /* 4872 */ { MAD_F(0x050a83d8) /* 0.315067145 */, 18 }, - /* 4873 */ { MAD_F(0x050ade43) /* 0.315153373 */, 18 }, - /* 4874 */ { MAD_F(0x050b38af) /* 0.315239607 */, 18 }, - /* 4875 */ { MAD_F(0x050b931d) /* 0.315325847 */, 18 }, - /* 4876 */ { MAD_F(0x050bed8d) /* 0.315412093 */, 18 }, - /* 4877 */ { MAD_F(0x050c47fe) /* 0.315498345 */, 18 }, - /* 4878 */ { MAD_F(0x050ca271) /* 0.315584603 */, 18 }, - /* 4879 */ { MAD_F(0x050cfce5) /* 0.315670866 */, 18 }, - - /* 4880 */ { MAD_F(0x050d575b) /* 0.315757136 */, 18 }, - /* 4881 */ { MAD_F(0x050db1d2) /* 0.315843411 */, 18 }, - /* 4882 */ { MAD_F(0x050e0c4b) /* 0.315929693 */, 18 }, - /* 4883 */ { MAD_F(0x050e66c5) /* 0.316015980 */, 18 }, - /* 4884 */ { MAD_F(0x050ec141) /* 0.316102273 */, 18 }, - /* 4885 */ { MAD_F(0x050f1bbf) /* 0.316188572 */, 18 }, - /* 4886 */ { MAD_F(0x050f763e) /* 0.316274877 */, 18 }, - /* 4887 */ { MAD_F(0x050fd0bf) /* 0.316361187 */, 18 }, - /* 4888 */ { MAD_F(0x05102b42) /* 0.316447504 */, 18 }, - /* 4889 */ { MAD_F(0x051085c6) /* 0.316533826 */, 18 }, - /* 4890 */ { MAD_F(0x0510e04b) /* 0.316620155 */, 18 }, - /* 4891 */ { MAD_F(0x05113ad3) /* 0.316706489 */, 18 }, - /* 4892 */ { MAD_F(0x0511955b) /* 0.316792829 */, 18 }, - /* 4893 */ { MAD_F(0x0511efe6) /* 0.316879175 */, 18 }, - /* 4894 */ { MAD_F(0x05124a72) /* 0.316965527 */, 18 }, - /* 4895 */ { MAD_F(0x0512a4ff) /* 0.317051885 */, 18 }, - - /* 4896 */ { MAD_F(0x0512ff8e) /* 0.317138249 */, 18 }, - /* 4897 */ { MAD_F(0x05135a1f) /* 0.317224618 */, 18 }, - /* 4898 */ { MAD_F(0x0513b4b1) /* 0.317310994 */, 18 }, - /* 4899 */ { MAD_F(0x05140f45) /* 0.317397375 */, 18 }, - /* 4900 */ { MAD_F(0x051469da) /* 0.317483762 */, 18 }, - /* 4901 */ { MAD_F(0x0514c471) /* 0.317570155 */, 18 }, - /* 4902 */ { MAD_F(0x05151f0a) /* 0.317656554 */, 18 }, - /* 4903 */ { MAD_F(0x051579a4) /* 0.317742959 */, 18 }, - /* 4904 */ { MAD_F(0x0515d440) /* 0.317829370 */, 18 }, - /* 4905 */ { MAD_F(0x05162edd) /* 0.317915786 */, 18 }, - /* 4906 */ { MAD_F(0x0516897c) /* 0.318002209 */, 18 }, - /* 4907 */ { MAD_F(0x0516e41c) /* 0.318088637 */, 18 }, - /* 4908 */ { MAD_F(0x05173ebe) /* 0.318175071 */, 18 }, - /* 4909 */ { MAD_F(0x05179962) /* 0.318261511 */, 18 }, - /* 4910 */ { MAD_F(0x0517f407) /* 0.318347957 */, 18 }, - /* 4911 */ { MAD_F(0x05184eae) /* 0.318434409 */, 18 }, - - /* 4912 */ { MAD_F(0x0518a956) /* 0.318520867 */, 18 }, - /* 4913 */ { MAD_F(0x05190400) /* 0.318607330 */, 18 }, - /* 4914 */ { MAD_F(0x05195eab) /* 0.318693800 */, 18 }, - /* 4915 */ { MAD_F(0x0519b958) /* 0.318780275 */, 18 }, - /* 4916 */ { MAD_F(0x051a1407) /* 0.318866756 */, 18 }, - /* 4917 */ { MAD_F(0x051a6eb7) /* 0.318953243 */, 18 }, - /* 4918 */ { MAD_F(0x051ac969) /* 0.319039736 */, 18 }, - /* 4919 */ { MAD_F(0x051b241c) /* 0.319126235 */, 18 }, - /* 4920 */ { MAD_F(0x051b7ed1) /* 0.319212739 */, 18 }, - /* 4921 */ { MAD_F(0x051bd987) /* 0.319299250 */, 18 }, - /* 4922 */ { MAD_F(0x051c3440) /* 0.319385766 */, 18 }, - /* 4923 */ { MAD_F(0x051c8ef9) /* 0.319472288 */, 18 }, - /* 4924 */ { MAD_F(0x051ce9b4) /* 0.319558816 */, 18 }, - /* 4925 */ { MAD_F(0x051d4471) /* 0.319645350 */, 18 }, - /* 4926 */ { MAD_F(0x051d9f2f) /* 0.319731890 */, 18 }, - /* 4927 */ { MAD_F(0x051df9ef) /* 0.319818435 */, 18 }, - - /* 4928 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 18 }, - /* 4929 */ { MAD_F(0x051eaf74) /* 0.319991544 */, 18 }, - /* 4930 */ { MAD_F(0x051f0a38) /* 0.320078107 */, 18 }, - /* 4931 */ { MAD_F(0x051f64ff) /* 0.320164676 */, 18 }, - /* 4932 */ { MAD_F(0x051fbfc6) /* 0.320251251 */, 18 }, - /* 4933 */ { MAD_F(0x05201a90) /* 0.320337832 */, 18 }, - /* 4934 */ { MAD_F(0x0520755b) /* 0.320424419 */, 18 }, - /* 4935 */ { MAD_F(0x0520d027) /* 0.320511011 */, 18 }, - /* 4936 */ { MAD_F(0x05212af5) /* 0.320597609 */, 18 }, - /* 4937 */ { MAD_F(0x052185c5) /* 0.320684213 */, 18 }, - /* 4938 */ { MAD_F(0x0521e096) /* 0.320770823 */, 18 }, - /* 4939 */ { MAD_F(0x05223b69) /* 0.320857439 */, 18 }, - /* 4940 */ { MAD_F(0x0522963d) /* 0.320944061 */, 18 }, - /* 4941 */ { MAD_F(0x0522f113) /* 0.321030688 */, 18 }, - /* 4942 */ { MAD_F(0x05234bea) /* 0.321117322 */, 18 }, - /* 4943 */ { MAD_F(0x0523a6c3) /* 0.321203961 */, 18 }, - - /* 4944 */ { MAD_F(0x0524019e) /* 0.321290606 */, 18 }, - /* 4945 */ { MAD_F(0x05245c7a) /* 0.321377257 */, 18 }, - /* 4946 */ { MAD_F(0x0524b758) /* 0.321463913 */, 18 }, - /* 4947 */ { MAD_F(0x05251237) /* 0.321550576 */, 18 }, - /* 4948 */ { MAD_F(0x05256d18) /* 0.321637244 */, 18 }, - /* 4949 */ { MAD_F(0x0525c7fb) /* 0.321723919 */, 18 }, - /* 4950 */ { MAD_F(0x052622df) /* 0.321810599 */, 18 }, - /* 4951 */ { MAD_F(0x05267dc4) /* 0.321897285 */, 18 }, - /* 4952 */ { MAD_F(0x0526d8ab) /* 0.321983976 */, 18 }, - /* 4953 */ { MAD_F(0x05273394) /* 0.322070674 */, 18 }, - /* 4954 */ { MAD_F(0x05278e7e) /* 0.322157377 */, 18 }, - /* 4955 */ { MAD_F(0x0527e96a) /* 0.322244087 */, 18 }, - /* 4956 */ { MAD_F(0x05284457) /* 0.322330802 */, 18 }, - /* 4957 */ { MAD_F(0x05289f46) /* 0.322417523 */, 18 }, - /* 4958 */ { MAD_F(0x0528fa37) /* 0.322504249 */, 18 }, - /* 4959 */ { MAD_F(0x05295529) /* 0.322590982 */, 18 }, - - /* 4960 */ { MAD_F(0x0529b01d) /* 0.322677720 */, 18 }, - /* 4961 */ { MAD_F(0x052a0b12) /* 0.322764465 */, 18 }, - /* 4962 */ { MAD_F(0x052a6609) /* 0.322851215 */, 18 }, - /* 4963 */ { MAD_F(0x052ac101) /* 0.322937971 */, 18 }, - /* 4964 */ { MAD_F(0x052b1bfb) /* 0.323024732 */, 18 }, - /* 4965 */ { MAD_F(0x052b76f7) /* 0.323111500 */, 18 }, - /* 4966 */ { MAD_F(0x052bd1f4) /* 0.323198273 */, 18 }, - /* 4967 */ { MAD_F(0x052c2cf2) /* 0.323285052 */, 18 }, - /* 4968 */ { MAD_F(0x052c87f2) /* 0.323371837 */, 18 }, - /* 4969 */ { MAD_F(0x052ce2f4) /* 0.323458628 */, 18 }, - /* 4970 */ { MAD_F(0x052d3df7) /* 0.323545425 */, 18 }, - /* 4971 */ { MAD_F(0x052d98fc) /* 0.323632227 */, 18 }, - /* 4972 */ { MAD_F(0x052df403) /* 0.323719036 */, 18 }, - /* 4973 */ { MAD_F(0x052e4f0b) /* 0.323805850 */, 18 }, - /* 4974 */ { MAD_F(0x052eaa14) /* 0.323892670 */, 18 }, - /* 4975 */ { MAD_F(0x052f051f) /* 0.323979496 */, 18 }, - - /* 4976 */ { MAD_F(0x052f602c) /* 0.324066327 */, 18 }, - /* 4977 */ { MAD_F(0x052fbb3a) /* 0.324153165 */, 18 }, - /* 4978 */ { MAD_F(0x0530164a) /* 0.324240008 */, 18 }, - /* 4979 */ { MAD_F(0x0530715b) /* 0.324326857 */, 18 }, - /* 4980 */ { MAD_F(0x0530cc6e) /* 0.324413712 */, 18 }, - /* 4981 */ { MAD_F(0x05312783) /* 0.324500572 */, 18 }, - /* 4982 */ { MAD_F(0x05318299) /* 0.324587439 */, 18 }, - /* 4983 */ { MAD_F(0x0531ddb0) /* 0.324674311 */, 18 }, - /* 4984 */ { MAD_F(0x053238ca) /* 0.324761189 */, 18 }, - /* 4985 */ { MAD_F(0x053293e4) /* 0.324848073 */, 18 }, - /* 4986 */ { MAD_F(0x0532ef01) /* 0.324934963 */, 18 }, - /* 4987 */ { MAD_F(0x05334a1e) /* 0.325021858 */, 18 }, - /* 4988 */ { MAD_F(0x0533a53e) /* 0.325108760 */, 18 }, - /* 4989 */ { MAD_F(0x0534005f) /* 0.325195667 */, 18 }, - /* 4990 */ { MAD_F(0x05345b81) /* 0.325282580 */, 18 }, - /* 4991 */ { MAD_F(0x0534b6a5) /* 0.325369498 */, 18 }, - - /* 4992 */ { MAD_F(0x053511cb) /* 0.325456423 */, 18 }, - /* 4993 */ { MAD_F(0x05356cf2) /* 0.325543353 */, 18 }, - /* 4994 */ { MAD_F(0x0535c81b) /* 0.325630290 */, 18 }, - /* 4995 */ { MAD_F(0x05362345) /* 0.325717232 */, 18 }, - /* 4996 */ { MAD_F(0x05367e71) /* 0.325804179 */, 18 }, - /* 4997 */ { MAD_F(0x0536d99f) /* 0.325891133 */, 18 }, - /* 4998 */ { MAD_F(0x053734ce) /* 0.325978092 */, 18 }, - /* 4999 */ { MAD_F(0x05378ffe) /* 0.326065057 */, 18 }, - /* 5000 */ { MAD_F(0x0537eb30) /* 0.326152028 */, 18 }, - /* 5001 */ { MAD_F(0x05384664) /* 0.326239005 */, 18 }, - /* 5002 */ { MAD_F(0x0538a199) /* 0.326325988 */, 18 }, - /* 5003 */ { MAD_F(0x0538fcd0) /* 0.326412976 */, 18 }, - /* 5004 */ { MAD_F(0x05395808) /* 0.326499970 */, 18 }, - /* 5005 */ { MAD_F(0x0539b342) /* 0.326586970 */, 18 }, - /* 5006 */ { MAD_F(0x053a0e7d) /* 0.326673976 */, 18 }, - /* 5007 */ { MAD_F(0x053a69ba) /* 0.326760988 */, 18 }, - - /* 5008 */ { MAD_F(0x053ac4f9) /* 0.326848005 */, 18 }, - /* 5009 */ { MAD_F(0x053b2039) /* 0.326935028 */, 18 }, - /* 5010 */ { MAD_F(0x053b7b7b) /* 0.327022057 */, 18 }, - /* 5011 */ { MAD_F(0x053bd6be) /* 0.327109092 */, 18 }, - /* 5012 */ { MAD_F(0x053c3203) /* 0.327196132 */, 18 }, - /* 5013 */ { MAD_F(0x053c8d49) /* 0.327283178 */, 18 }, - /* 5014 */ { MAD_F(0x053ce891) /* 0.327370231 */, 18 }, - /* 5015 */ { MAD_F(0x053d43da) /* 0.327457288 */, 18 }, - /* 5016 */ { MAD_F(0x053d9f25) /* 0.327544352 */, 18 }, - /* 5017 */ { MAD_F(0x053dfa72) /* 0.327631421 */, 18 }, - /* 5018 */ { MAD_F(0x053e55c0) /* 0.327718497 */, 18 }, - /* 5019 */ { MAD_F(0x053eb10f) /* 0.327805578 */, 18 }, - /* 5020 */ { MAD_F(0x053f0c61) /* 0.327892665 */, 18 }, - /* 5021 */ { MAD_F(0x053f67b3) /* 0.327979757 */, 18 }, - /* 5022 */ { MAD_F(0x053fc308) /* 0.328066855 */, 18 }, - /* 5023 */ { MAD_F(0x05401e5e) /* 0.328153960 */, 18 }, - - /* 5024 */ { MAD_F(0x054079b5) /* 0.328241070 */, 18 }, - /* 5025 */ { MAD_F(0x0540d50e) /* 0.328328185 */, 18 }, - /* 5026 */ { MAD_F(0x05413068) /* 0.328415307 */, 18 }, - /* 5027 */ { MAD_F(0x05418bc4) /* 0.328502434 */, 18 }, - /* 5028 */ { MAD_F(0x0541e722) /* 0.328589567 */, 18 }, - /* 5029 */ { MAD_F(0x05424281) /* 0.328676706 */, 18 }, - /* 5030 */ { MAD_F(0x05429de2) /* 0.328763850 */, 18 }, - /* 5031 */ { MAD_F(0x0542f944) /* 0.328851001 */, 18 }, - /* 5032 */ { MAD_F(0x054354a8) /* 0.328938157 */, 18 }, - /* 5033 */ { MAD_F(0x0543b00d) /* 0.329025319 */, 18 }, - /* 5034 */ { MAD_F(0x05440b74) /* 0.329112486 */, 18 }, - /* 5035 */ { MAD_F(0x054466dd) /* 0.329199660 */, 18 }, - /* 5036 */ { MAD_F(0x0544c247) /* 0.329286839 */, 18 }, - /* 5037 */ { MAD_F(0x05451db2) /* 0.329374024 */, 18 }, - /* 5038 */ { MAD_F(0x0545791f) /* 0.329461215 */, 18 }, - /* 5039 */ { MAD_F(0x0545d48e) /* 0.329548411 */, 18 }, - - /* 5040 */ { MAD_F(0x05462ffe) /* 0.329635614 */, 18 }, - /* 5041 */ { MAD_F(0x05468b70) /* 0.329722822 */, 18 }, - /* 5042 */ { MAD_F(0x0546e6e3) /* 0.329810036 */, 18 }, - /* 5043 */ { MAD_F(0x05474258) /* 0.329897255 */, 18 }, - /* 5044 */ { MAD_F(0x05479dce) /* 0.329984481 */, 18 }, - /* 5045 */ { MAD_F(0x0547f946) /* 0.330071712 */, 18 }, - /* 5046 */ { MAD_F(0x054854c0) /* 0.330158949 */, 18 }, - /* 5047 */ { MAD_F(0x0548b03b) /* 0.330246191 */, 18 }, - /* 5048 */ { MAD_F(0x05490bb7) /* 0.330333440 */, 18 }, - /* 5049 */ { MAD_F(0x05496735) /* 0.330420694 */, 18 }, - /* 5050 */ { MAD_F(0x0549c2b5) /* 0.330507954 */, 18 }, - /* 5051 */ { MAD_F(0x054a1e36) /* 0.330595220 */, 18 }, - /* 5052 */ { MAD_F(0x054a79b9) /* 0.330682491 */, 18 }, - /* 5053 */ { MAD_F(0x054ad53d) /* 0.330769768 */, 18 }, - /* 5054 */ { MAD_F(0x054b30c3) /* 0.330857051 */, 18 }, - /* 5055 */ { MAD_F(0x054b8c4b) /* 0.330944340 */, 18 }, - - /* 5056 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 18 }, - /* 5057 */ { MAD_F(0x054c435e) /* 0.331118935 */, 18 }, - /* 5058 */ { MAD_F(0x054c9eea) /* 0.331206241 */, 18 }, - /* 5059 */ { MAD_F(0x054cfa78) /* 0.331293553 */, 18 }, - /* 5060 */ { MAD_F(0x054d5607) /* 0.331380870 */, 18 }, - /* 5061 */ { MAD_F(0x054db197) /* 0.331468193 */, 18 }, - /* 5062 */ { MAD_F(0x054e0d2a) /* 0.331555522 */, 18 }, - /* 5063 */ { MAD_F(0x054e68bd) /* 0.331642857 */, 18 }, - /* 5064 */ { MAD_F(0x054ec453) /* 0.331730198 */, 18 }, - /* 5065 */ { MAD_F(0x054f1fe9) /* 0.331817544 */, 18 }, - /* 5066 */ { MAD_F(0x054f7b82) /* 0.331904896 */, 18 }, - /* 5067 */ { MAD_F(0x054fd71c) /* 0.331992254 */, 18 }, - /* 5068 */ { MAD_F(0x055032b7) /* 0.332079617 */, 18 }, - /* 5069 */ { MAD_F(0x05508e54) /* 0.332166986 */, 18 }, - /* 5070 */ { MAD_F(0x0550e9f3) /* 0.332254361 */, 18 }, - /* 5071 */ { MAD_F(0x05514593) /* 0.332341742 */, 18 }, - - /* 5072 */ { MAD_F(0x0551a134) /* 0.332429129 */, 18 }, - /* 5073 */ { MAD_F(0x0551fcd8) /* 0.332516521 */, 18 }, - /* 5074 */ { MAD_F(0x0552587c) /* 0.332603919 */, 18 }, - /* 5075 */ { MAD_F(0x0552b423) /* 0.332691323 */, 18 }, - /* 5076 */ { MAD_F(0x05530fca) /* 0.332778732 */, 18 }, - /* 5077 */ { MAD_F(0x05536b74) /* 0.332866147 */, 18 }, - /* 5078 */ { MAD_F(0x0553c71f) /* 0.332953568 */, 18 }, - /* 5079 */ { MAD_F(0x055422cb) /* 0.333040995 */, 18 }, - /* 5080 */ { MAD_F(0x05547e79) /* 0.333128427 */, 18 }, - /* 5081 */ { MAD_F(0x0554da29) /* 0.333215865 */, 18 }, - /* 5082 */ { MAD_F(0x055535da) /* 0.333303309 */, 18 }, - /* 5083 */ { MAD_F(0x0555918c) /* 0.333390759 */, 18 }, - /* 5084 */ { MAD_F(0x0555ed40) /* 0.333478214 */, 18 }, - /* 5085 */ { MAD_F(0x055648f6) /* 0.333565675 */, 18 }, - /* 5086 */ { MAD_F(0x0556a4ad) /* 0.333653142 */, 18 }, - /* 5087 */ { MAD_F(0x05570066) /* 0.333740615 */, 18 }, - - /* 5088 */ { MAD_F(0x05575c20) /* 0.333828093 */, 18 }, - /* 5089 */ { MAD_F(0x0557b7dc) /* 0.333915577 */, 18 }, - /* 5090 */ { MAD_F(0x05581399) /* 0.334003067 */, 18 }, - /* 5091 */ { MAD_F(0x05586f58) /* 0.334090562 */, 18 }, - /* 5092 */ { MAD_F(0x0558cb19) /* 0.334178063 */, 18 }, - /* 5093 */ { MAD_F(0x055926db) /* 0.334265570 */, 18 }, - /* 5094 */ { MAD_F(0x0559829e) /* 0.334353083 */, 18 }, - /* 5095 */ { MAD_F(0x0559de63) /* 0.334440601 */, 18 }, - /* 5096 */ { MAD_F(0x055a3a2a) /* 0.334528126 */, 18 }, - /* 5097 */ { MAD_F(0x055a95f2) /* 0.334615655 */, 18 }, - /* 5098 */ { MAD_F(0x055af1bb) /* 0.334703191 */, 18 }, - /* 5099 */ { MAD_F(0x055b4d87) /* 0.334790732 */, 18 }, - /* 5100 */ { MAD_F(0x055ba953) /* 0.334878279 */, 18 }, - /* 5101 */ { MAD_F(0x055c0522) /* 0.334965832 */, 18 }, - /* 5102 */ { MAD_F(0x055c60f1) /* 0.335053391 */, 18 }, - /* 5103 */ { MAD_F(0x055cbcc3) /* 0.335140955 */, 18 }, - - /* 5104 */ { MAD_F(0x055d1896) /* 0.335228525 */, 18 }, - /* 5105 */ { MAD_F(0x055d746a) /* 0.335316100 */, 18 }, - /* 5106 */ { MAD_F(0x055dd040) /* 0.335403682 */, 18 }, - /* 5107 */ { MAD_F(0x055e2c17) /* 0.335491269 */, 18 }, - /* 5108 */ { MAD_F(0x055e87f0) /* 0.335578861 */, 18 }, - /* 5109 */ { MAD_F(0x055ee3cb) /* 0.335666460 */, 18 }, - /* 5110 */ { MAD_F(0x055f3fa7) /* 0.335754064 */, 18 }, - /* 5111 */ { MAD_F(0x055f9b85) /* 0.335841674 */, 18 }, - /* 5112 */ { MAD_F(0x055ff764) /* 0.335929290 */, 18 }, - /* 5113 */ { MAD_F(0x05605344) /* 0.336016911 */, 18 }, - /* 5114 */ { MAD_F(0x0560af27) /* 0.336104538 */, 18 }, - /* 5115 */ { MAD_F(0x05610b0a) /* 0.336192171 */, 18 }, - /* 5116 */ { MAD_F(0x056166f0) /* 0.336279809 */, 18 }, - /* 5117 */ { MAD_F(0x0561c2d7) /* 0.336367453 */, 18 }, - /* 5118 */ { MAD_F(0x05621ebf) /* 0.336455103 */, 18 }, - /* 5119 */ { MAD_F(0x05627aa9) /* 0.336542759 */, 18 }, - - /* 5120 */ { MAD_F(0x0562d694) /* 0.336630420 */, 18 }, - /* 5121 */ { MAD_F(0x05633281) /* 0.336718087 */, 18 }, - /* 5122 */ { MAD_F(0x05638e70) /* 0.336805760 */, 18 }, - /* 5123 */ { MAD_F(0x0563ea60) /* 0.336893439 */, 18 }, - /* 5124 */ { MAD_F(0x05644651) /* 0.336981123 */, 18 }, - /* 5125 */ { MAD_F(0x0564a244) /* 0.337068813 */, 18 }, - /* 5126 */ { MAD_F(0x0564fe39) /* 0.337156508 */, 18 }, - /* 5127 */ { MAD_F(0x05655a2f) /* 0.337244209 */, 18 }, - /* 5128 */ { MAD_F(0x0565b627) /* 0.337331916 */, 18 }, - /* 5129 */ { MAD_F(0x05661220) /* 0.337419629 */, 18 }, - /* 5130 */ { MAD_F(0x05666e1a) /* 0.337507347 */, 18 }, - /* 5131 */ { MAD_F(0x0566ca17) /* 0.337595071 */, 18 }, - /* 5132 */ { MAD_F(0x05672614) /* 0.337682801 */, 18 }, - /* 5133 */ { MAD_F(0x05678214) /* 0.337770537 */, 18 }, - /* 5134 */ { MAD_F(0x0567de15) /* 0.337858278 */, 18 }, - /* 5135 */ { MAD_F(0x05683a17) /* 0.337946025 */, 18 }, - - /* 5136 */ { MAD_F(0x0568961b) /* 0.338033777 */, 18 }, - /* 5137 */ { MAD_F(0x0568f220) /* 0.338121535 */, 18 }, - /* 5138 */ { MAD_F(0x05694e27) /* 0.338209299 */, 18 }, - /* 5139 */ { MAD_F(0x0569aa30) /* 0.338297069 */, 18 }, - /* 5140 */ { MAD_F(0x056a063a) /* 0.338384844 */, 18 }, - /* 5141 */ { MAD_F(0x056a6245) /* 0.338472625 */, 18 }, - /* 5142 */ { MAD_F(0x056abe52) /* 0.338560412 */, 18 }, - /* 5143 */ { MAD_F(0x056b1a61) /* 0.338648204 */, 18 }, - /* 5144 */ { MAD_F(0x056b7671) /* 0.338736002 */, 18 }, - /* 5145 */ { MAD_F(0x056bd283) /* 0.338823806 */, 18 }, - /* 5146 */ { MAD_F(0x056c2e96) /* 0.338911616 */, 18 }, - /* 5147 */ { MAD_F(0x056c8aab) /* 0.338999431 */, 18 }, - /* 5148 */ { MAD_F(0x056ce6c1) /* 0.339087252 */, 18 }, - /* 5149 */ { MAD_F(0x056d42d9) /* 0.339175078 */, 18 }, - /* 5150 */ { MAD_F(0x056d9ef2) /* 0.339262910 */, 18 }, - /* 5151 */ { MAD_F(0x056dfb0d) /* 0.339350748 */, 18 }, - - /* 5152 */ { MAD_F(0x056e5729) /* 0.339438592 */, 18 }, - /* 5153 */ { MAD_F(0x056eb347) /* 0.339526441 */, 18 }, - /* 5154 */ { MAD_F(0x056f0f66) /* 0.339614296 */, 18 }, - /* 5155 */ { MAD_F(0x056f6b87) /* 0.339702157 */, 18 }, - /* 5156 */ { MAD_F(0x056fc7aa) /* 0.339790023 */, 18 }, - /* 5157 */ { MAD_F(0x057023cd) /* 0.339877895 */, 18 }, - /* 5158 */ { MAD_F(0x05707ff3) /* 0.339965773 */, 18 }, - /* 5159 */ { MAD_F(0x0570dc1a) /* 0.340053656 */, 18 }, - /* 5160 */ { MAD_F(0x05713843) /* 0.340141545 */, 18 }, - /* 5161 */ { MAD_F(0x0571946d) /* 0.340229440 */, 18 }, - /* 5162 */ { MAD_F(0x0571f098) /* 0.340317340 */, 18 }, - /* 5163 */ { MAD_F(0x05724cc5) /* 0.340405246 */, 18 }, - /* 5164 */ { MAD_F(0x0572a8f4) /* 0.340493158 */, 18 }, - /* 5165 */ { MAD_F(0x05730524) /* 0.340581075 */, 18 }, - /* 5166 */ { MAD_F(0x05736156) /* 0.340668999 */, 18 }, - /* 5167 */ { MAD_F(0x0573bd89) /* 0.340756927 */, 18 }, - - /* 5168 */ { MAD_F(0x057419be) /* 0.340844862 */, 18 }, - /* 5169 */ { MAD_F(0x057475f4) /* 0.340932802 */, 18 }, - /* 5170 */ { MAD_F(0x0574d22c) /* 0.341020748 */, 18 }, - /* 5171 */ { MAD_F(0x05752e65) /* 0.341108699 */, 18 }, - /* 5172 */ { MAD_F(0x05758aa0) /* 0.341196656 */, 18 }, - /* 5173 */ { MAD_F(0x0575e6dc) /* 0.341284619 */, 18 }, - /* 5174 */ { MAD_F(0x0576431a) /* 0.341372587 */, 18 }, - /* 5175 */ { MAD_F(0x05769f59) /* 0.341460562 */, 18 }, - /* 5176 */ { MAD_F(0x0576fb9a) /* 0.341548541 */, 18 }, - /* 5177 */ { MAD_F(0x057757dd) /* 0.341636527 */, 18 }, - /* 5178 */ { MAD_F(0x0577b421) /* 0.341724518 */, 18 }, - /* 5179 */ { MAD_F(0x05781066) /* 0.341812515 */, 18 }, - /* 5180 */ { MAD_F(0x05786cad) /* 0.341900517 */, 18 }, - /* 5181 */ { MAD_F(0x0578c8f5) /* 0.341988525 */, 18 }, - /* 5182 */ { MAD_F(0x0579253f) /* 0.342076539 */, 18 }, - /* 5183 */ { MAD_F(0x0579818b) /* 0.342164558 */, 18 }, - - /* 5184 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 18 }, - /* 5185 */ { MAD_F(0x057a3a27) /* 0.342340614 */, 18 }, - /* 5186 */ { MAD_F(0x057a9677) /* 0.342428651 */, 18 }, - /* 5187 */ { MAD_F(0x057af2c8) /* 0.342516693 */, 18 }, - /* 5188 */ { MAD_F(0x057b4f1c) /* 0.342604741 */, 18 }, - /* 5189 */ { MAD_F(0x057bab70) /* 0.342692794 */, 18 }, - /* 5190 */ { MAD_F(0x057c07c6) /* 0.342780853 */, 18 }, - /* 5191 */ { MAD_F(0x057c641e) /* 0.342868918 */, 18 }, - /* 5192 */ { MAD_F(0x057cc077) /* 0.342956988 */, 18 }, - /* 5193 */ { MAD_F(0x057d1cd2) /* 0.343045064 */, 18 }, - /* 5194 */ { MAD_F(0x057d792e) /* 0.343133146 */, 18 }, - /* 5195 */ { MAD_F(0x057dd58c) /* 0.343221233 */, 18 }, - /* 5196 */ { MAD_F(0x057e31eb) /* 0.343309326 */, 18 }, - /* 5197 */ { MAD_F(0x057e8e4c) /* 0.343397425 */, 18 }, - /* 5198 */ { MAD_F(0x057eeaae) /* 0.343485529 */, 18 }, - /* 5199 */ { MAD_F(0x057f4712) /* 0.343573639 */, 18 }, - - /* 5200 */ { MAD_F(0x057fa378) /* 0.343661754 */, 18 }, - /* 5201 */ { MAD_F(0x057fffde) /* 0.343749876 */, 18 }, - /* 5202 */ { MAD_F(0x05805c47) /* 0.343838003 */, 18 }, - /* 5203 */ { MAD_F(0x0580b8b1) /* 0.343926135 */, 18 }, - /* 5204 */ { MAD_F(0x0581151c) /* 0.344014273 */, 18 }, - /* 5205 */ { MAD_F(0x05817189) /* 0.344102417 */, 18 }, - /* 5206 */ { MAD_F(0x0581cdf7) /* 0.344190566 */, 18 }, - /* 5207 */ { MAD_F(0x05822a67) /* 0.344278722 */, 18 }, - /* 5208 */ { MAD_F(0x058286d9) /* 0.344366882 */, 18 }, - /* 5209 */ { MAD_F(0x0582e34c) /* 0.344455049 */, 18 }, - /* 5210 */ { MAD_F(0x05833fc0) /* 0.344543221 */, 18 }, - /* 5211 */ { MAD_F(0x05839c36) /* 0.344631398 */, 18 }, - /* 5212 */ { MAD_F(0x0583f8ae) /* 0.344719582 */, 18 }, - /* 5213 */ { MAD_F(0x05845527) /* 0.344807771 */, 18 }, - /* 5214 */ { MAD_F(0x0584b1a1) /* 0.344895965 */, 18 }, - /* 5215 */ { MAD_F(0x05850e1e) /* 0.344984165 */, 18 }, - - /* 5216 */ { MAD_F(0x05856a9b) /* 0.345072371 */, 18 }, - /* 5217 */ { MAD_F(0x0585c71a) /* 0.345160583 */, 18 }, - /* 5218 */ { MAD_F(0x0586239b) /* 0.345248800 */, 18 }, - /* 5219 */ { MAD_F(0x0586801d) /* 0.345337023 */, 18 }, - /* 5220 */ { MAD_F(0x0586dca1) /* 0.345425251 */, 18 }, - /* 5221 */ { MAD_F(0x05873926) /* 0.345513485 */, 18 }, - /* 5222 */ { MAD_F(0x058795ac) /* 0.345601725 */, 18 }, - /* 5223 */ { MAD_F(0x0587f235) /* 0.345689970 */, 18 }, - /* 5224 */ { MAD_F(0x05884ebe) /* 0.345778221 */, 18 }, - /* 5225 */ { MAD_F(0x0588ab49) /* 0.345866478 */, 18 }, - /* 5226 */ { MAD_F(0x058907d6) /* 0.345954740 */, 18 }, - /* 5227 */ { MAD_F(0x05896464) /* 0.346043008 */, 18 }, - /* 5228 */ { MAD_F(0x0589c0f4) /* 0.346131281 */, 18 }, - /* 5229 */ { MAD_F(0x058a1d85) /* 0.346219560 */, 18 }, - /* 5230 */ { MAD_F(0x058a7a18) /* 0.346307845 */, 18 }, - /* 5231 */ { MAD_F(0x058ad6ac) /* 0.346396135 */, 18 }, - - /* 5232 */ { MAD_F(0x058b3342) /* 0.346484431 */, 18 }, - /* 5233 */ { MAD_F(0x058b8fd9) /* 0.346572733 */, 18 }, - /* 5234 */ { MAD_F(0x058bec72) /* 0.346661040 */, 18 }, - /* 5235 */ { MAD_F(0x058c490c) /* 0.346749353 */, 18 }, - /* 5236 */ { MAD_F(0x058ca5a8) /* 0.346837671 */, 18 }, - /* 5237 */ { MAD_F(0x058d0246) /* 0.346925996 */, 18 }, - /* 5238 */ { MAD_F(0x058d5ee4) /* 0.347014325 */, 18 }, - /* 5239 */ { MAD_F(0x058dbb85) /* 0.347102661 */, 18 }, - /* 5240 */ { MAD_F(0x058e1827) /* 0.347191002 */, 18 }, - /* 5241 */ { MAD_F(0x058e74ca) /* 0.347279348 */, 18 }, - /* 5242 */ { MAD_F(0x058ed16f) /* 0.347367700 */, 18 }, - /* 5243 */ { MAD_F(0x058f2e15) /* 0.347456058 */, 18 }, - /* 5244 */ { MAD_F(0x058f8abd) /* 0.347544422 */, 18 }, - /* 5245 */ { MAD_F(0x058fe766) /* 0.347632791 */, 18 }, - /* 5246 */ { MAD_F(0x05904411) /* 0.347721165 */, 18 }, - /* 5247 */ { MAD_F(0x0590a0be) /* 0.347809546 */, 18 }, - - /* 5248 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 18 }, - /* 5249 */ { MAD_F(0x05915a1b) /* 0.347986323 */, 18 }, - /* 5250 */ { MAD_F(0x0591b6cc) /* 0.348074720 */, 18 }, - /* 5251 */ { MAD_F(0x0592137e) /* 0.348163123 */, 18 }, - /* 5252 */ { MAD_F(0x05927032) /* 0.348251531 */, 18 }, - /* 5253 */ { MAD_F(0x0592cce8) /* 0.348339945 */, 18 }, - /* 5254 */ { MAD_F(0x0593299f) /* 0.348428365 */, 18 }, - /* 5255 */ { MAD_F(0x05938657) /* 0.348516790 */, 18 }, - /* 5256 */ { MAD_F(0x0593e311) /* 0.348605221 */, 18 }, - /* 5257 */ { MAD_F(0x05943fcd) /* 0.348693657 */, 18 }, - /* 5258 */ { MAD_F(0x05949c8a) /* 0.348782099 */, 18 }, - /* 5259 */ { MAD_F(0x0594f948) /* 0.348870547 */, 18 }, - /* 5260 */ { MAD_F(0x05955608) /* 0.348959000 */, 18 }, - /* 5261 */ { MAD_F(0x0595b2ca) /* 0.349047459 */, 18 }, - /* 5262 */ { MAD_F(0x05960f8c) /* 0.349135923 */, 18 }, - /* 5263 */ { MAD_F(0x05966c51) /* 0.349224393 */, 18 }, - - /* 5264 */ { MAD_F(0x0596c917) /* 0.349312869 */, 18 }, - /* 5265 */ { MAD_F(0x059725de) /* 0.349401350 */, 18 }, - /* 5266 */ { MAD_F(0x059782a7) /* 0.349489837 */, 18 }, - /* 5267 */ { MAD_F(0x0597df72) /* 0.349578329 */, 18 }, - /* 5268 */ { MAD_F(0x05983c3e) /* 0.349666827 */, 18 }, - /* 5269 */ { MAD_F(0x0598990c) /* 0.349755331 */, 18 }, - /* 5270 */ { MAD_F(0x0598f5db) /* 0.349843840 */, 18 }, - /* 5271 */ { MAD_F(0x059952ab) /* 0.349932355 */, 18 }, - /* 5272 */ { MAD_F(0x0599af7d) /* 0.350020876 */, 18 }, - /* 5273 */ { MAD_F(0x059a0c51) /* 0.350109402 */, 18 }, - /* 5274 */ { MAD_F(0x059a6926) /* 0.350197933 */, 18 }, - /* 5275 */ { MAD_F(0x059ac5fc) /* 0.350286470 */, 18 }, - /* 5276 */ { MAD_F(0x059b22d4) /* 0.350375013 */, 18 }, - /* 5277 */ { MAD_F(0x059b7fae) /* 0.350463562 */, 18 }, - /* 5278 */ { MAD_F(0x059bdc89) /* 0.350552116 */, 18 }, - /* 5279 */ { MAD_F(0x059c3965) /* 0.350640675 */, 18 }, - - /* 5280 */ { MAD_F(0x059c9643) /* 0.350729240 */, 18 }, - /* 5281 */ { MAD_F(0x059cf323) /* 0.350817811 */, 18 }, - /* 5282 */ { MAD_F(0x059d5004) /* 0.350906388 */, 18 }, - /* 5283 */ { MAD_F(0x059dace6) /* 0.350994970 */, 18 }, - /* 5284 */ { MAD_F(0x059e09cb) /* 0.351083557 */, 18 }, - /* 5285 */ { MAD_F(0x059e66b0) /* 0.351172150 */, 18 }, - /* 5286 */ { MAD_F(0x059ec397) /* 0.351260749 */, 18 }, - /* 5287 */ { MAD_F(0x059f2080) /* 0.351349353 */, 18 }, - /* 5288 */ { MAD_F(0x059f7d6a) /* 0.351437963 */, 18 }, - /* 5289 */ { MAD_F(0x059fda55) /* 0.351526579 */, 18 }, - /* 5290 */ { MAD_F(0x05a03742) /* 0.351615200 */, 18 }, - /* 5291 */ { MAD_F(0x05a09431) /* 0.351703827 */, 18 }, - /* 5292 */ { MAD_F(0x05a0f121) /* 0.351792459 */, 18 }, - /* 5293 */ { MAD_F(0x05a14e12) /* 0.351881097 */, 18 }, - /* 5294 */ { MAD_F(0x05a1ab05) /* 0.351969740 */, 18 }, - /* 5295 */ { MAD_F(0x05a207fa) /* 0.352058389 */, 18 }, - - /* 5296 */ { MAD_F(0x05a264f0) /* 0.352147044 */, 18 }, - /* 5297 */ { MAD_F(0x05a2c1e7) /* 0.352235704 */, 18 }, - /* 5298 */ { MAD_F(0x05a31ee1) /* 0.352324369 */, 18 }, - /* 5299 */ { MAD_F(0x05a37bdb) /* 0.352413041 */, 18 }, - /* 5300 */ { MAD_F(0x05a3d8d7) /* 0.352501718 */, 18 }, - /* 5301 */ { MAD_F(0x05a435d5) /* 0.352590400 */, 18 }, - /* 5302 */ { MAD_F(0x05a492d4) /* 0.352679088 */, 18 }, - /* 5303 */ { MAD_F(0x05a4efd4) /* 0.352767782 */, 18 }, - /* 5304 */ { MAD_F(0x05a54cd6) /* 0.352856481 */, 18 }, - /* 5305 */ { MAD_F(0x05a5a9da) /* 0.352945186 */, 18 }, - /* 5306 */ { MAD_F(0x05a606df) /* 0.353033896 */, 18 }, - /* 5307 */ { MAD_F(0x05a663e5) /* 0.353122612 */, 18 }, - /* 5308 */ { MAD_F(0x05a6c0ed) /* 0.353211333 */, 18 }, - /* 5309 */ { MAD_F(0x05a71df7) /* 0.353300061 */, 18 }, - /* 5310 */ { MAD_F(0x05a77b02) /* 0.353388793 */, 18 }, - /* 5311 */ { MAD_F(0x05a7d80e) /* 0.353477531 */, 18 }, - - /* 5312 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 18 }, - /* 5313 */ { MAD_F(0x05a8922c) /* 0.353655024 */, 18 }, - /* 5314 */ { MAD_F(0x05a8ef3c) /* 0.353743779 */, 18 }, - /* 5315 */ { MAD_F(0x05a94c4f) /* 0.353832540 */, 18 }, - /* 5316 */ { MAD_F(0x05a9a963) /* 0.353921306 */, 18 }, - /* 5317 */ { MAD_F(0x05aa0678) /* 0.354010077 */, 18 }, - /* 5318 */ { MAD_F(0x05aa638f) /* 0.354098855 */, 18 }, - /* 5319 */ { MAD_F(0x05aac0a8) /* 0.354187637 */, 18 }, - /* 5320 */ { MAD_F(0x05ab1dc2) /* 0.354276426 */, 18 }, - /* 5321 */ { MAD_F(0x05ab7add) /* 0.354365220 */, 18 }, - /* 5322 */ { MAD_F(0x05abd7fa) /* 0.354454019 */, 18 }, - /* 5323 */ { MAD_F(0x05ac3518) /* 0.354542824 */, 18 }, - /* 5324 */ { MAD_F(0x05ac9238) /* 0.354631635 */, 18 }, - /* 5325 */ { MAD_F(0x05acef5a) /* 0.354720451 */, 18 }, - /* 5326 */ { MAD_F(0x05ad4c7d) /* 0.354809272 */, 18 }, - /* 5327 */ { MAD_F(0x05ada9a1) /* 0.354898100 */, 18 }, - - /* 5328 */ { MAD_F(0x05ae06c7) /* 0.354986932 */, 18 }, - /* 5329 */ { MAD_F(0x05ae63ee) /* 0.355075771 */, 18 }, - /* 5330 */ { MAD_F(0x05aec117) /* 0.355164615 */, 18 }, - /* 5331 */ { MAD_F(0x05af1e41) /* 0.355253464 */, 18 }, - /* 5332 */ { MAD_F(0x05af7b6d) /* 0.355342319 */, 18 }, - /* 5333 */ { MAD_F(0x05afd89b) /* 0.355431180 */, 18 }, - /* 5334 */ { MAD_F(0x05b035c9) /* 0.355520046 */, 18 }, - /* 5335 */ { MAD_F(0x05b092fa) /* 0.355608917 */, 18 }, - /* 5336 */ { MAD_F(0x05b0f02b) /* 0.355697795 */, 18 }, - /* 5337 */ { MAD_F(0x05b14d5f) /* 0.355786677 */, 18 }, - /* 5338 */ { MAD_F(0x05b1aa94) /* 0.355875566 */, 18 }, - /* 5339 */ { MAD_F(0x05b207ca) /* 0.355964460 */, 18 }, - /* 5340 */ { MAD_F(0x05b26502) /* 0.356053359 */, 18 }, - /* 5341 */ { MAD_F(0x05b2c23b) /* 0.356142264 */, 18 }, - /* 5342 */ { MAD_F(0x05b31f76) /* 0.356231175 */, 18 }, - /* 5343 */ { MAD_F(0x05b37cb2) /* 0.356320091 */, 18 }, - - /* 5344 */ { MAD_F(0x05b3d9f0) /* 0.356409012 */, 18 }, - /* 5345 */ { MAD_F(0x05b4372f) /* 0.356497940 */, 18 }, - /* 5346 */ { MAD_F(0x05b4946f) /* 0.356586872 */, 18 }, - /* 5347 */ { MAD_F(0x05b4f1b2) /* 0.356675811 */, 18 }, - /* 5348 */ { MAD_F(0x05b54ef5) /* 0.356764754 */, 18 }, - /* 5349 */ { MAD_F(0x05b5ac3a) /* 0.356853704 */, 18 }, - /* 5350 */ { MAD_F(0x05b60981) /* 0.356942659 */, 18 }, - /* 5351 */ { MAD_F(0x05b666c9) /* 0.357031619 */, 18 }, - /* 5352 */ { MAD_F(0x05b6c413) /* 0.357120585 */, 18 }, - /* 5353 */ { MAD_F(0x05b7215e) /* 0.357209557 */, 18 }, - /* 5354 */ { MAD_F(0x05b77eab) /* 0.357298534 */, 18 }, - /* 5355 */ { MAD_F(0x05b7dbf9) /* 0.357387516 */, 18 }, - /* 5356 */ { MAD_F(0x05b83948) /* 0.357476504 */, 18 }, - /* 5357 */ { MAD_F(0x05b89699) /* 0.357565498 */, 18 }, - /* 5358 */ { MAD_F(0x05b8f3ec) /* 0.357654497 */, 18 }, - /* 5359 */ { MAD_F(0x05b95140) /* 0.357743502 */, 18 }, - - /* 5360 */ { MAD_F(0x05b9ae95) /* 0.357832512 */, 18 }, - /* 5361 */ { MAD_F(0x05ba0bec) /* 0.357921528 */, 18 }, - /* 5362 */ { MAD_F(0x05ba6945) /* 0.358010550 */, 18 }, - /* 5363 */ { MAD_F(0x05bac69f) /* 0.358099576 */, 18 }, - /* 5364 */ { MAD_F(0x05bb23fa) /* 0.358188609 */, 18 }, - /* 5365 */ { MAD_F(0x05bb8157) /* 0.358277647 */, 18 }, - /* 5366 */ { MAD_F(0x05bbdeb6) /* 0.358366690 */, 18 }, - /* 5367 */ { MAD_F(0x05bc3c16) /* 0.358455739 */, 18 }, - /* 5368 */ { MAD_F(0x05bc9977) /* 0.358544794 */, 18 }, - /* 5369 */ { MAD_F(0x05bcf6da) /* 0.358633854 */, 18 }, - /* 5370 */ { MAD_F(0x05bd543e) /* 0.358722920 */, 18 }, - /* 5371 */ { MAD_F(0x05bdb1a4) /* 0.358811991 */, 18 }, - /* 5372 */ { MAD_F(0x05be0f0b) /* 0.358901067 */, 18 }, - /* 5373 */ { MAD_F(0x05be6c74) /* 0.358990150 */, 18 }, - /* 5374 */ { MAD_F(0x05bec9df) /* 0.359079237 */, 18 }, - /* 5375 */ { MAD_F(0x05bf274a) /* 0.359168331 */, 18 }, - - /* 5376 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 18 }, - /* 5377 */ { MAD_F(0x05bfe226) /* 0.359346534 */, 18 }, - /* 5378 */ { MAD_F(0x05c03f97) /* 0.359435644 */, 18 }, - /* 5379 */ { MAD_F(0x05c09d08) /* 0.359524759 */, 18 }, - /* 5380 */ { MAD_F(0x05c0fa7c) /* 0.359613880 */, 18 }, - /* 5381 */ { MAD_F(0x05c157f0) /* 0.359703006 */, 18 }, - /* 5382 */ { MAD_F(0x05c1b566) /* 0.359792138 */, 18 }, - /* 5383 */ { MAD_F(0x05c212de) /* 0.359881276 */, 18 }, - /* 5384 */ { MAD_F(0x05c27057) /* 0.359970419 */, 18 }, - /* 5385 */ { MAD_F(0x05c2cdd2) /* 0.360059567 */, 18 }, - /* 5386 */ { MAD_F(0x05c32b4e) /* 0.360148721 */, 18 }, - /* 5387 */ { MAD_F(0x05c388cb) /* 0.360237881 */, 18 }, - /* 5388 */ { MAD_F(0x05c3e64b) /* 0.360327046 */, 18 }, - /* 5389 */ { MAD_F(0x05c443cb) /* 0.360416216 */, 18 }, - /* 5390 */ { MAD_F(0x05c4a14d) /* 0.360505392 */, 18 }, - /* 5391 */ { MAD_F(0x05c4fed1) /* 0.360594574 */, 18 }, - - /* 5392 */ { MAD_F(0x05c55c56) /* 0.360683761 */, 18 }, - /* 5393 */ { MAD_F(0x05c5b9dc) /* 0.360772953 */, 18 }, - /* 5394 */ { MAD_F(0x05c61764) /* 0.360862152 */, 18 }, - /* 5395 */ { MAD_F(0x05c674ed) /* 0.360951355 */, 18 }, - /* 5396 */ { MAD_F(0x05c6d278) /* 0.361040564 */, 18 }, - /* 5397 */ { MAD_F(0x05c73005) /* 0.361129779 */, 18 }, - /* 5398 */ { MAD_F(0x05c78d93) /* 0.361218999 */, 18 }, - /* 5399 */ { MAD_F(0x05c7eb22) /* 0.361308225 */, 18 }, - /* 5400 */ { MAD_F(0x05c848b3) /* 0.361397456 */, 18 }, - /* 5401 */ { MAD_F(0x05c8a645) /* 0.361486693 */, 18 }, - /* 5402 */ { MAD_F(0x05c903d9) /* 0.361575935 */, 18 }, - /* 5403 */ { MAD_F(0x05c9616e) /* 0.361665183 */, 18 }, - /* 5404 */ { MAD_F(0x05c9bf05) /* 0.361754436 */, 18 }, - /* 5405 */ { MAD_F(0x05ca1c9d) /* 0.361843695 */, 18 }, - /* 5406 */ { MAD_F(0x05ca7a37) /* 0.361932959 */, 18 }, - /* 5407 */ { MAD_F(0x05cad7d2) /* 0.362022229 */, 18 }, - - /* 5408 */ { MAD_F(0x05cb356e) /* 0.362111504 */, 18 }, - /* 5409 */ { MAD_F(0x05cb930d) /* 0.362200785 */, 18 }, - /* 5410 */ { MAD_F(0x05cbf0ac) /* 0.362290071 */, 18 }, - /* 5411 */ { MAD_F(0x05cc4e4d) /* 0.362379362 */, 18 }, - /* 5412 */ { MAD_F(0x05ccabf0) /* 0.362468660 */, 18 }, - /* 5413 */ { MAD_F(0x05cd0994) /* 0.362557962 */, 18 }, - /* 5414 */ { MAD_F(0x05cd6739) /* 0.362647271 */, 18 }, - /* 5415 */ { MAD_F(0x05cdc4e0) /* 0.362736584 */, 18 }, - /* 5416 */ { MAD_F(0x05ce2289) /* 0.362825904 */, 18 }, - /* 5417 */ { MAD_F(0x05ce8033) /* 0.362915228 */, 18 }, - /* 5418 */ { MAD_F(0x05ceddde) /* 0.363004559 */, 18 }, - /* 5419 */ { MAD_F(0x05cf3b8b) /* 0.363093894 */, 18 }, - /* 5420 */ { MAD_F(0x05cf9939) /* 0.363183236 */, 18 }, - /* 5421 */ { MAD_F(0x05cff6e9) /* 0.363272582 */, 18 }, - /* 5422 */ { MAD_F(0x05d0549a) /* 0.363361935 */, 18 }, - /* 5423 */ { MAD_F(0x05d0b24d) /* 0.363451292 */, 18 }, - - /* 5424 */ { MAD_F(0x05d11001) /* 0.363540655 */, 18 }, - /* 5425 */ { MAD_F(0x05d16db7) /* 0.363630024 */, 18 }, - /* 5426 */ { MAD_F(0x05d1cb6e) /* 0.363719398 */, 18 }, - /* 5427 */ { MAD_F(0x05d22927) /* 0.363808778 */, 18 }, - /* 5428 */ { MAD_F(0x05d286e1) /* 0.363898163 */, 18 }, - /* 5429 */ { MAD_F(0x05d2e49d) /* 0.363987554 */, 18 }, - /* 5430 */ { MAD_F(0x05d3425a) /* 0.364076950 */, 18 }, - /* 5431 */ { MAD_F(0x05d3a018) /* 0.364166352 */, 18 }, - /* 5432 */ { MAD_F(0x05d3fdd8) /* 0.364255759 */, 18 }, - /* 5433 */ { MAD_F(0x05d45b9a) /* 0.364345171 */, 18 }, - /* 5434 */ { MAD_F(0x05d4b95d) /* 0.364434589 */, 18 }, - /* 5435 */ { MAD_F(0x05d51721) /* 0.364524013 */, 18 }, - /* 5436 */ { MAD_F(0x05d574e7) /* 0.364613442 */, 18 }, - /* 5437 */ { MAD_F(0x05d5d2af) /* 0.364702877 */, 18 }, - /* 5438 */ { MAD_F(0x05d63078) /* 0.364792317 */, 18 }, - /* 5439 */ { MAD_F(0x05d68e42) /* 0.364881762 */, 18 }, - - /* 5440 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 18 }, - /* 5441 */ { MAD_F(0x05d749db) /* 0.365060669 */, 18 }, - /* 5442 */ { MAD_F(0x05d7a7aa) /* 0.365150131 */, 18 }, - /* 5443 */ { MAD_F(0x05d8057a) /* 0.365239599 */, 18 }, - /* 5444 */ { MAD_F(0x05d8634c) /* 0.365329072 */, 18 }, - /* 5445 */ { MAD_F(0x05d8c11f) /* 0.365418550 */, 18 }, - /* 5446 */ { MAD_F(0x05d91ef4) /* 0.365508034 */, 18 }, - /* 5447 */ { MAD_F(0x05d97cca) /* 0.365597523 */, 18 }, - /* 5448 */ { MAD_F(0x05d9daa1) /* 0.365687018 */, 18 }, - /* 5449 */ { MAD_F(0x05da387a) /* 0.365776518 */, 18 }, - /* 5450 */ { MAD_F(0x05da9655) /* 0.365866024 */, 18 }, - /* 5451 */ { MAD_F(0x05daf431) /* 0.365955536 */, 18 }, - /* 5452 */ { MAD_F(0x05db520e) /* 0.366045052 */, 18 }, - /* 5453 */ { MAD_F(0x05dbafed) /* 0.366134574 */, 18 }, - /* 5454 */ { MAD_F(0x05dc0dce) /* 0.366224102 */, 18 }, - /* 5455 */ { MAD_F(0x05dc6baf) /* 0.366313635 */, 18 }, - - /* 5456 */ { MAD_F(0x05dcc993) /* 0.366403174 */, 18 }, - /* 5457 */ { MAD_F(0x05dd2778) /* 0.366492718 */, 18 }, - /* 5458 */ { MAD_F(0x05dd855e) /* 0.366582267 */, 18 }, - /* 5459 */ { MAD_F(0x05dde346) /* 0.366671822 */, 18 }, - /* 5460 */ { MAD_F(0x05de412f) /* 0.366761383 */, 18 }, - /* 5461 */ { MAD_F(0x05de9f1a) /* 0.366850949 */, 18 }, - /* 5462 */ { MAD_F(0x05defd06) /* 0.366940520 */, 18 }, - /* 5463 */ { MAD_F(0x05df5af3) /* 0.367030097 */, 18 }, - /* 5464 */ { MAD_F(0x05dfb8e2) /* 0.367119680 */, 18 }, - /* 5465 */ { MAD_F(0x05e016d3) /* 0.367209267 */, 18 }, - /* 5466 */ { MAD_F(0x05e074c5) /* 0.367298861 */, 18 }, - /* 5467 */ { MAD_F(0x05e0d2b8) /* 0.367388459 */, 18 }, - /* 5468 */ { MAD_F(0x05e130ad) /* 0.367478064 */, 18 }, - /* 5469 */ { MAD_F(0x05e18ea4) /* 0.367567673 */, 18 }, - /* 5470 */ { MAD_F(0x05e1ec9c) /* 0.367657288 */, 18 }, - /* 5471 */ { MAD_F(0x05e24a95) /* 0.367746909 */, 18 }, - - /* 5472 */ { MAD_F(0x05e2a890) /* 0.367836535 */, 18 }, - /* 5473 */ { MAD_F(0x05e3068c) /* 0.367926167 */, 18 }, - /* 5474 */ { MAD_F(0x05e3648a) /* 0.368015804 */, 18 }, - /* 5475 */ { MAD_F(0x05e3c289) /* 0.368105446 */, 18 }, - /* 5476 */ { MAD_F(0x05e4208a) /* 0.368195094 */, 18 }, - /* 5477 */ { MAD_F(0x05e47e8c) /* 0.368284747 */, 18 }, - /* 5478 */ { MAD_F(0x05e4dc8f) /* 0.368374406 */, 18 }, - /* 5479 */ { MAD_F(0x05e53a94) /* 0.368464070 */, 18 }, - /* 5480 */ { MAD_F(0x05e5989b) /* 0.368553740 */, 18 }, - /* 5481 */ { MAD_F(0x05e5f6a3) /* 0.368643415 */, 18 }, - /* 5482 */ { MAD_F(0x05e654ac) /* 0.368733096 */, 18 }, - /* 5483 */ { MAD_F(0x05e6b2b7) /* 0.368822782 */, 18 }, - /* 5484 */ { MAD_F(0x05e710c4) /* 0.368912473 */, 18 }, - /* 5485 */ { MAD_F(0x05e76ed2) /* 0.369002170 */, 18 }, - /* 5486 */ { MAD_F(0x05e7cce1) /* 0.369091873 */, 18 }, - /* 5487 */ { MAD_F(0x05e82af2) /* 0.369181581 */, 18 }, - - /* 5488 */ { MAD_F(0x05e88904) /* 0.369271294 */, 18 }, - /* 5489 */ { MAD_F(0x05e8e718) /* 0.369361013 */, 18 }, - /* 5490 */ { MAD_F(0x05e9452d) /* 0.369450737 */, 18 }, - /* 5491 */ { MAD_F(0x05e9a343) /* 0.369540467 */, 18 }, - /* 5492 */ { MAD_F(0x05ea015c) /* 0.369630202 */, 18 }, - /* 5493 */ { MAD_F(0x05ea5f75) /* 0.369719942 */, 18 }, - /* 5494 */ { MAD_F(0x05eabd90) /* 0.369809688 */, 18 }, - /* 5495 */ { MAD_F(0x05eb1bad) /* 0.369899440 */, 18 }, - /* 5496 */ { MAD_F(0x05eb79cb) /* 0.369989197 */, 18 }, - /* 5497 */ { MAD_F(0x05ebd7ea) /* 0.370078959 */, 18 }, - /* 5498 */ { MAD_F(0x05ec360b) /* 0.370168727 */, 18 }, - /* 5499 */ { MAD_F(0x05ec942d) /* 0.370258500 */, 18 }, - /* 5500 */ { MAD_F(0x05ecf251) /* 0.370348279 */, 18 }, - /* 5501 */ { MAD_F(0x05ed5076) /* 0.370438063 */, 18 }, - /* 5502 */ { MAD_F(0x05edae9d) /* 0.370527853 */, 18 }, - /* 5503 */ { MAD_F(0x05ee0cc5) /* 0.370617648 */, 18 }, - - /* 5504 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 18 }, - /* 5505 */ { MAD_F(0x05eec91a) /* 0.370797254 */, 18 }, - /* 5506 */ { MAD_F(0x05ef2746) /* 0.370887065 */, 18 }, - /* 5507 */ { MAD_F(0x05ef8574) /* 0.370976882 */, 18 }, - /* 5508 */ { MAD_F(0x05efe3a4) /* 0.371066704 */, 18 }, - /* 5509 */ { MAD_F(0x05f041d5) /* 0.371156532 */, 18 }, - /* 5510 */ { MAD_F(0x05f0a007) /* 0.371246365 */, 18 }, - /* 5511 */ { MAD_F(0x05f0fe3b) /* 0.371336203 */, 18 }, - /* 5512 */ { MAD_F(0x05f15c70) /* 0.371426047 */, 18 }, - /* 5513 */ { MAD_F(0x05f1baa7) /* 0.371515897 */, 18 }, - /* 5514 */ { MAD_F(0x05f218df) /* 0.371605751 */, 18 }, - /* 5515 */ { MAD_F(0x05f27719) /* 0.371695612 */, 18 }, - /* 5516 */ { MAD_F(0x05f2d554) /* 0.371785477 */, 18 }, - /* 5517 */ { MAD_F(0x05f33390) /* 0.371875348 */, 18 }, - /* 5518 */ { MAD_F(0x05f391cf) /* 0.371965225 */, 18 }, - /* 5519 */ { MAD_F(0x05f3f00e) /* 0.372055107 */, 18 }, - - /* 5520 */ { MAD_F(0x05f44e4f) /* 0.372144994 */, 18 }, - /* 5521 */ { MAD_F(0x05f4ac91) /* 0.372234887 */, 18 }, - /* 5522 */ { MAD_F(0x05f50ad5) /* 0.372324785 */, 18 }, - /* 5523 */ { MAD_F(0x05f5691b) /* 0.372414689 */, 18 }, - /* 5524 */ { MAD_F(0x05f5c761) /* 0.372504598 */, 18 }, - /* 5525 */ { MAD_F(0x05f625aa) /* 0.372594513 */, 18 }, - /* 5526 */ { MAD_F(0x05f683f3) /* 0.372684433 */, 18 }, - /* 5527 */ { MAD_F(0x05f6e23f) /* 0.372774358 */, 18 }, - /* 5528 */ { MAD_F(0x05f7408b) /* 0.372864289 */, 18 }, - /* 5529 */ { MAD_F(0x05f79ed9) /* 0.372954225 */, 18 }, - /* 5530 */ { MAD_F(0x05f7fd29) /* 0.373044167 */, 18 }, - /* 5531 */ { MAD_F(0x05f85b7a) /* 0.373134114 */, 18 }, - /* 5532 */ { MAD_F(0x05f8b9cc) /* 0.373224066 */, 18 }, - /* 5533 */ { MAD_F(0x05f91820) /* 0.373314024 */, 18 }, - /* 5534 */ { MAD_F(0x05f97675) /* 0.373403987 */, 18 }, - /* 5535 */ { MAD_F(0x05f9d4cc) /* 0.373493956 */, 18 }, - - /* 5536 */ { MAD_F(0x05fa3324) /* 0.373583930 */, 18 }, - /* 5537 */ { MAD_F(0x05fa917e) /* 0.373673910 */, 18 }, - /* 5538 */ { MAD_F(0x05faefd9) /* 0.373763895 */, 18 }, - /* 5539 */ { MAD_F(0x05fb4e36) /* 0.373853885 */, 18 }, - /* 5540 */ { MAD_F(0x05fbac94) /* 0.373943881 */, 18 }, - /* 5541 */ { MAD_F(0x05fc0af3) /* 0.374033882 */, 18 }, - /* 5542 */ { MAD_F(0x05fc6954) /* 0.374123889 */, 18 }, - /* 5543 */ { MAD_F(0x05fcc7b7) /* 0.374213901 */, 18 }, - /* 5544 */ { MAD_F(0x05fd261b) /* 0.374303918 */, 18 }, - /* 5545 */ { MAD_F(0x05fd8480) /* 0.374393941 */, 18 }, - /* 5546 */ { MAD_F(0x05fde2e7) /* 0.374483970 */, 18 }, - /* 5547 */ { MAD_F(0x05fe414f) /* 0.374574003 */, 18 }, - /* 5548 */ { MAD_F(0x05fe9fb9) /* 0.374664042 */, 18 }, - /* 5549 */ { MAD_F(0x05fefe24) /* 0.374754087 */, 18 }, - /* 5550 */ { MAD_F(0x05ff5c91) /* 0.374844137 */, 18 }, - /* 5551 */ { MAD_F(0x05ffbaff) /* 0.374934192 */, 18 }, - - /* 5552 */ { MAD_F(0x0600196e) /* 0.375024253 */, 18 }, - /* 5553 */ { MAD_F(0x060077df) /* 0.375114319 */, 18 }, - /* 5554 */ { MAD_F(0x0600d651) /* 0.375204391 */, 18 }, - /* 5555 */ { MAD_F(0x060134c5) /* 0.375294468 */, 18 }, - /* 5556 */ { MAD_F(0x0601933b) /* 0.375384550 */, 18 }, - /* 5557 */ { MAD_F(0x0601f1b1) /* 0.375474638 */, 18 }, - /* 5558 */ { MAD_F(0x0602502a) /* 0.375564731 */, 18 }, - /* 5559 */ { MAD_F(0x0602aea3) /* 0.375654830 */, 18 }, - /* 5560 */ { MAD_F(0x06030d1e) /* 0.375744934 */, 18 }, - /* 5561 */ { MAD_F(0x06036b9b) /* 0.375835043 */, 18 }, - /* 5562 */ { MAD_F(0x0603ca19) /* 0.375925158 */, 18 }, - /* 5563 */ { MAD_F(0x06042898) /* 0.376015278 */, 18 }, - /* 5564 */ { MAD_F(0x06048719) /* 0.376105404 */, 18 }, - /* 5565 */ { MAD_F(0x0604e59c) /* 0.376195535 */, 18 }, - /* 5566 */ { MAD_F(0x0605441f) /* 0.376285671 */, 18 }, - /* 5567 */ { MAD_F(0x0605a2a5) /* 0.376375813 */, 18 }, - - /* 5568 */ { MAD_F(0x0606012b) /* 0.376465960 */, 18 }, - /* 5569 */ { MAD_F(0x06065fb4) /* 0.376556113 */, 18 }, - /* 5570 */ { MAD_F(0x0606be3d) /* 0.376646271 */, 18 }, - /* 5571 */ { MAD_F(0x06071cc8) /* 0.376736434 */, 18 }, - /* 5572 */ { MAD_F(0x06077b55) /* 0.376826603 */, 18 }, - /* 5573 */ { MAD_F(0x0607d9e3) /* 0.376916777 */, 18 }, - /* 5574 */ { MAD_F(0x06083872) /* 0.377006957 */, 18 }, - /* 5575 */ { MAD_F(0x06089703) /* 0.377097141 */, 18 }, - /* 5576 */ { MAD_F(0x0608f595) /* 0.377187332 */, 18 }, - /* 5577 */ { MAD_F(0x06095429) /* 0.377277528 */, 18 }, - /* 5578 */ { MAD_F(0x0609b2be) /* 0.377367729 */, 18 }, - /* 5579 */ { MAD_F(0x060a1155) /* 0.377457935 */, 18 }, - /* 5580 */ { MAD_F(0x060a6fed) /* 0.377548147 */, 18 }, - /* 5581 */ { MAD_F(0x060ace86) /* 0.377638364 */, 18 }, - /* 5582 */ { MAD_F(0x060b2d21) /* 0.377728587 */, 18 }, - /* 5583 */ { MAD_F(0x060b8bbe) /* 0.377818815 */, 18 }, - - /* 5584 */ { MAD_F(0x060bea5c) /* 0.377909049 */, 18 }, - /* 5585 */ { MAD_F(0x060c48fb) /* 0.377999288 */, 18 }, - /* 5586 */ { MAD_F(0x060ca79c) /* 0.378089532 */, 18 }, - /* 5587 */ { MAD_F(0x060d063e) /* 0.378179781 */, 18 }, - /* 5588 */ { MAD_F(0x060d64e1) /* 0.378270036 */, 18 }, - /* 5589 */ { MAD_F(0x060dc387) /* 0.378360297 */, 18 }, - /* 5590 */ { MAD_F(0x060e222d) /* 0.378450563 */, 18 }, - /* 5591 */ { MAD_F(0x060e80d5) /* 0.378540834 */, 18 }, - /* 5592 */ { MAD_F(0x060edf7f) /* 0.378631110 */, 18 }, - /* 5593 */ { MAD_F(0x060f3e29) /* 0.378721392 */, 18 }, - /* 5594 */ { MAD_F(0x060f9cd6) /* 0.378811680 */, 18 }, - /* 5595 */ { MAD_F(0x060ffb83) /* 0.378901972 */, 18 }, - /* 5596 */ { MAD_F(0x06105a33) /* 0.378992270 */, 18 }, - /* 5597 */ { MAD_F(0x0610b8e3) /* 0.379082574 */, 18 }, - /* 5598 */ { MAD_F(0x06111795) /* 0.379172883 */, 18 }, - /* 5599 */ { MAD_F(0x06117649) /* 0.379263197 */, 18 }, - - /* 5600 */ { MAD_F(0x0611d4fe) /* 0.379353516 */, 18 }, - /* 5601 */ { MAD_F(0x061233b4) /* 0.379443841 */, 18 }, - /* 5602 */ { MAD_F(0x0612926c) /* 0.379534172 */, 18 }, - /* 5603 */ { MAD_F(0x0612f125) /* 0.379624507 */, 18 }, - /* 5604 */ { MAD_F(0x06134fe0) /* 0.379714848 */, 18 }, - /* 5605 */ { MAD_F(0x0613ae9c) /* 0.379805195 */, 18 }, - /* 5606 */ { MAD_F(0x06140d5a) /* 0.379895547 */, 18 }, - /* 5607 */ { MAD_F(0x06146c19) /* 0.379985904 */, 18 }, - /* 5608 */ { MAD_F(0x0614cada) /* 0.380076266 */, 18 }, - /* 5609 */ { MAD_F(0x0615299c) /* 0.380166634 */, 18 }, - /* 5610 */ { MAD_F(0x0615885f) /* 0.380257008 */, 18 }, - /* 5611 */ { MAD_F(0x0615e724) /* 0.380347386 */, 18 }, - /* 5612 */ { MAD_F(0x061645ea) /* 0.380437770 */, 18 }, - /* 5613 */ { MAD_F(0x0616a4b2) /* 0.380528160 */, 18 }, - /* 5614 */ { MAD_F(0x0617037b) /* 0.380618555 */, 18 }, - /* 5615 */ { MAD_F(0x06176246) /* 0.380708955 */, 18 }, - - /* 5616 */ { MAD_F(0x0617c112) /* 0.380799360 */, 18 }, - /* 5617 */ { MAD_F(0x06181fdf) /* 0.380889771 */, 18 }, - /* 5618 */ { MAD_F(0x06187eae) /* 0.380980187 */, 18 }, - /* 5619 */ { MAD_F(0x0618dd7e) /* 0.381070609 */, 18 }, - /* 5620 */ { MAD_F(0x06193c50) /* 0.381161036 */, 18 }, - /* 5621 */ { MAD_F(0x06199b24) /* 0.381251468 */, 18 }, - /* 5622 */ { MAD_F(0x0619f9f8) /* 0.381341906 */, 18 }, - /* 5623 */ { MAD_F(0x061a58ce) /* 0.381432349 */, 18 }, - /* 5624 */ { MAD_F(0x061ab7a6) /* 0.381522798 */, 18 }, - /* 5625 */ { MAD_F(0x061b167f) /* 0.381613251 */, 18 }, - /* 5626 */ { MAD_F(0x061b7559) /* 0.381703711 */, 18 }, - /* 5627 */ { MAD_F(0x061bd435) /* 0.381794175 */, 18 }, - /* 5628 */ { MAD_F(0x061c3313) /* 0.381884645 */, 18 }, - /* 5629 */ { MAD_F(0x061c91f1) /* 0.381975120 */, 18 }, - /* 5630 */ { MAD_F(0x061cf0d2) /* 0.382065601 */, 18 }, - /* 5631 */ { MAD_F(0x061d4fb3) /* 0.382156087 */, 18 }, - - /* 5632 */ { MAD_F(0x061dae96) /* 0.382246578 */, 18 }, - /* 5633 */ { MAD_F(0x061e0d7b) /* 0.382337075 */, 18 }, - /* 5634 */ { MAD_F(0x061e6c61) /* 0.382427577 */, 18 }, - /* 5635 */ { MAD_F(0x061ecb48) /* 0.382518084 */, 18 }, - /* 5636 */ { MAD_F(0x061f2a31) /* 0.382608597 */, 18 }, - /* 5637 */ { MAD_F(0x061f891b) /* 0.382699115 */, 18 }, - /* 5638 */ { MAD_F(0x061fe807) /* 0.382789638 */, 18 }, - /* 5639 */ { MAD_F(0x062046f4) /* 0.382880167 */, 18 }, - /* 5640 */ { MAD_F(0x0620a5e3) /* 0.382970701 */, 18 }, - /* 5641 */ { MAD_F(0x062104d3) /* 0.383061241 */, 18 }, - /* 5642 */ { MAD_F(0x062163c4) /* 0.383151786 */, 18 }, - /* 5643 */ { MAD_F(0x0621c2b7) /* 0.383242336 */, 18 }, - /* 5644 */ { MAD_F(0x062221ab) /* 0.383332891 */, 18 }, - /* 5645 */ { MAD_F(0x062280a1) /* 0.383423452 */, 18 }, - /* 5646 */ { MAD_F(0x0622df98) /* 0.383514018 */, 18 }, - /* 5647 */ { MAD_F(0x06233e91) /* 0.383604590 */, 18 }, - - /* 5648 */ { MAD_F(0x06239d8b) /* 0.383695167 */, 18 }, - /* 5649 */ { MAD_F(0x0623fc86) /* 0.383785749 */, 18 }, - /* 5650 */ { MAD_F(0x06245b83) /* 0.383876337 */, 18 }, - /* 5651 */ { MAD_F(0x0624ba82) /* 0.383966930 */, 18 }, - /* 5652 */ { MAD_F(0x06251981) /* 0.384057528 */, 18 }, - /* 5653 */ { MAD_F(0x06257883) /* 0.384148132 */, 18 }, - /* 5654 */ { MAD_F(0x0625d785) /* 0.384238741 */, 18 }, - /* 5655 */ { MAD_F(0x06263689) /* 0.384329355 */, 18 }, - /* 5656 */ { MAD_F(0x0626958f) /* 0.384419975 */, 18 }, - /* 5657 */ { MAD_F(0x0626f496) /* 0.384510600 */, 18 }, - /* 5658 */ { MAD_F(0x0627539e) /* 0.384601230 */, 18 }, - /* 5659 */ { MAD_F(0x0627b2a8) /* 0.384691866 */, 18 }, - /* 5660 */ { MAD_F(0x062811b3) /* 0.384782507 */, 18 }, - /* 5661 */ { MAD_F(0x062870c0) /* 0.384873153 */, 18 }, - /* 5662 */ { MAD_F(0x0628cfce) /* 0.384963805 */, 18 }, - /* 5663 */ { MAD_F(0x06292ede) /* 0.385054462 */, 18 }, - - /* 5664 */ { MAD_F(0x06298def) /* 0.385145124 */, 18 }, - /* 5665 */ { MAD_F(0x0629ed01) /* 0.385235792 */, 18 }, - /* 5666 */ { MAD_F(0x062a4c15) /* 0.385326465 */, 18 }, - /* 5667 */ { MAD_F(0x062aab2a) /* 0.385417143 */, 18 }, - /* 5668 */ { MAD_F(0x062b0a41) /* 0.385507827 */, 18 }, - /* 5669 */ { MAD_F(0x062b6959) /* 0.385598516 */, 18 }, - /* 5670 */ { MAD_F(0x062bc873) /* 0.385689211 */, 18 }, - /* 5671 */ { MAD_F(0x062c278e) /* 0.385779910 */, 18 }, - /* 5672 */ { MAD_F(0x062c86aa) /* 0.385870615 */, 18 }, - /* 5673 */ { MAD_F(0x062ce5c8) /* 0.385961326 */, 18 }, - /* 5674 */ { MAD_F(0x062d44e8) /* 0.386052041 */, 18 }, - /* 5675 */ { MAD_F(0x062da408) /* 0.386142762 */, 18 }, - /* 5676 */ { MAD_F(0x062e032a) /* 0.386233489 */, 18 }, - /* 5677 */ { MAD_F(0x062e624e) /* 0.386324221 */, 18 }, - /* 5678 */ { MAD_F(0x062ec173) /* 0.386414958 */, 18 }, - /* 5679 */ { MAD_F(0x062f209a) /* 0.386505700 */, 18 }, - - /* 5680 */ { MAD_F(0x062f7fc1) /* 0.386596448 */, 18 }, - /* 5681 */ { MAD_F(0x062fdeeb) /* 0.386687201 */, 18 }, - /* 5682 */ { MAD_F(0x06303e16) /* 0.386777959 */, 18 }, - /* 5683 */ { MAD_F(0x06309d42) /* 0.386868723 */, 18 }, - /* 5684 */ { MAD_F(0x0630fc6f) /* 0.386959492 */, 18 }, - /* 5685 */ { MAD_F(0x06315b9e) /* 0.387050266 */, 18 }, - /* 5686 */ { MAD_F(0x0631bacf) /* 0.387141045 */, 18 }, - /* 5687 */ { MAD_F(0x06321a01) /* 0.387231830 */, 18 }, - /* 5688 */ { MAD_F(0x06327934) /* 0.387322621 */, 18 }, - /* 5689 */ { MAD_F(0x0632d869) /* 0.387413416 */, 18 }, - /* 5690 */ { MAD_F(0x0633379f) /* 0.387504217 */, 18 }, - /* 5691 */ { MAD_F(0x063396d7) /* 0.387595023 */, 18 }, - /* 5692 */ { MAD_F(0x0633f610) /* 0.387685835 */, 18 }, - /* 5693 */ { MAD_F(0x0634554a) /* 0.387776652 */, 18 }, - /* 5694 */ { MAD_F(0x0634b486) /* 0.387867474 */, 18 }, - /* 5695 */ { MAD_F(0x063513c3) /* 0.387958301 */, 18 }, - - /* 5696 */ { MAD_F(0x06357302) /* 0.388049134 */, 18 }, - /* 5697 */ { MAD_F(0x0635d242) /* 0.388139972 */, 18 }, - /* 5698 */ { MAD_F(0x06363184) /* 0.388230816 */, 18 }, - /* 5699 */ { MAD_F(0x063690c7) /* 0.388321665 */, 18 }, - /* 5700 */ { MAD_F(0x0636f00b) /* 0.388412519 */, 18 }, - /* 5701 */ { MAD_F(0x06374f51) /* 0.388503378 */, 18 }, - /* 5702 */ { MAD_F(0x0637ae99) /* 0.388594243 */, 18 }, - /* 5703 */ { MAD_F(0x06380de1) /* 0.388685113 */, 18 }, - /* 5704 */ { MAD_F(0x06386d2b) /* 0.388775988 */, 18 }, - /* 5705 */ { MAD_F(0x0638cc77) /* 0.388866869 */, 18 }, - /* 5706 */ { MAD_F(0x06392bc4) /* 0.388957755 */, 18 }, - /* 5707 */ { MAD_F(0x06398b12) /* 0.389048646 */, 18 }, - /* 5708 */ { MAD_F(0x0639ea62) /* 0.389139542 */, 18 }, - /* 5709 */ { MAD_F(0x063a49b4) /* 0.389230444 */, 18 }, - /* 5710 */ { MAD_F(0x063aa906) /* 0.389321352 */, 18 }, - /* 5711 */ { MAD_F(0x063b085a) /* 0.389412264 */, 18 }, - - /* 5712 */ { MAD_F(0x063b67b0) /* 0.389503182 */, 18 }, - /* 5713 */ { MAD_F(0x063bc707) /* 0.389594105 */, 18 }, - /* 5714 */ { MAD_F(0x063c265f) /* 0.389685033 */, 18 }, - /* 5715 */ { MAD_F(0x063c85b9) /* 0.389775967 */, 18 }, - /* 5716 */ { MAD_F(0x063ce514) /* 0.389866906 */, 18 }, - /* 5717 */ { MAD_F(0x063d4471) /* 0.389957850 */, 18 }, - /* 5718 */ { MAD_F(0x063da3cf) /* 0.390048800 */, 18 }, - /* 5719 */ { MAD_F(0x063e032f) /* 0.390139755 */, 18 }, - /* 5720 */ { MAD_F(0x063e6290) /* 0.390230715 */, 18 }, - /* 5721 */ { MAD_F(0x063ec1f2) /* 0.390321681 */, 18 }, - /* 5722 */ { MAD_F(0x063f2156) /* 0.390412651 */, 18 }, - /* 5723 */ { MAD_F(0x063f80bb) /* 0.390503628 */, 18 }, - /* 5724 */ { MAD_F(0x063fe022) /* 0.390594609 */, 18 }, - /* 5725 */ { MAD_F(0x06403f8a) /* 0.390685596 */, 18 }, - /* 5726 */ { MAD_F(0x06409ef3) /* 0.390776588 */, 18 }, - /* 5727 */ { MAD_F(0x0640fe5e) /* 0.390867585 */, 18 }, - - /* 5728 */ { MAD_F(0x06415dcb) /* 0.390958588 */, 18 }, - /* 5729 */ { MAD_F(0x0641bd38) /* 0.391049596 */, 18 }, - /* 5730 */ { MAD_F(0x06421ca7) /* 0.391140609 */, 18 }, - /* 5731 */ { MAD_F(0x06427c18) /* 0.391231627 */, 18 }, - /* 5732 */ { MAD_F(0x0642db8a) /* 0.391322651 */, 18 }, - /* 5733 */ { MAD_F(0x06433afd) /* 0.391413680 */, 18 }, - /* 5734 */ { MAD_F(0x06439a72) /* 0.391504714 */, 18 }, - /* 5735 */ { MAD_F(0x0643f9e9) /* 0.391595754 */, 18 }, - /* 5736 */ { MAD_F(0x06445960) /* 0.391686799 */, 18 }, - /* 5737 */ { MAD_F(0x0644b8d9) /* 0.391777849 */, 18 }, - /* 5738 */ { MAD_F(0x06451854) /* 0.391868905 */, 18 }, - /* 5739 */ { MAD_F(0x064577d0) /* 0.391959966 */, 18 }, - /* 5740 */ { MAD_F(0x0645d74d) /* 0.392051032 */, 18 }, - /* 5741 */ { MAD_F(0x064636cc) /* 0.392142103 */, 18 }, - /* 5742 */ { MAD_F(0x0646964c) /* 0.392233180 */, 18 }, - /* 5743 */ { MAD_F(0x0646f5ce) /* 0.392324262 */, 18 }, - - /* 5744 */ { MAD_F(0x06475551) /* 0.392415349 */, 18 }, - /* 5745 */ { MAD_F(0x0647b4d5) /* 0.392506442 */, 18 }, - /* 5746 */ { MAD_F(0x0648145b) /* 0.392597540 */, 18 }, - /* 5747 */ { MAD_F(0x064873e3) /* 0.392688643 */, 18 }, - /* 5748 */ { MAD_F(0x0648d36b) /* 0.392779751 */, 18 }, - /* 5749 */ { MAD_F(0x064932f6) /* 0.392870865 */, 18 }, - /* 5750 */ { MAD_F(0x06499281) /* 0.392961984 */, 18 }, - /* 5751 */ { MAD_F(0x0649f20e) /* 0.393053108 */, 18 }, - /* 5752 */ { MAD_F(0x064a519c) /* 0.393144238 */, 18 }, - /* 5753 */ { MAD_F(0x064ab12c) /* 0.393235372 */, 18 }, - /* 5754 */ { MAD_F(0x064b10be) /* 0.393326513 */, 18 }, - /* 5755 */ { MAD_F(0x064b7050) /* 0.393417658 */, 18 }, - /* 5756 */ { MAD_F(0x064bcfe4) /* 0.393508809 */, 18 }, - /* 5757 */ { MAD_F(0x064c2f7a) /* 0.393599965 */, 18 }, - /* 5758 */ { MAD_F(0x064c8f11) /* 0.393691126 */, 18 }, - /* 5759 */ { MAD_F(0x064ceea9) /* 0.393782292 */, 18 }, - - /* 5760 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 18 }, - /* 5761 */ { MAD_F(0x064dadde) /* 0.393964641 */, 18 }, - /* 5762 */ { MAD_F(0x064e0d7a) /* 0.394055823 */, 18 }, - /* 5763 */ { MAD_F(0x064e6d18) /* 0.394147011 */, 18 }, - /* 5764 */ { MAD_F(0x064eccb8) /* 0.394238204 */, 18 }, - /* 5765 */ { MAD_F(0x064f2c59) /* 0.394329402 */, 18 }, - /* 5766 */ { MAD_F(0x064f8bfb) /* 0.394420605 */, 18 }, - /* 5767 */ { MAD_F(0x064feb9e) /* 0.394511814 */, 18 }, - /* 5768 */ { MAD_F(0x06504b44) /* 0.394603028 */, 18 }, - /* 5769 */ { MAD_F(0x0650aaea) /* 0.394694247 */, 18 }, - /* 5770 */ { MAD_F(0x06510a92) /* 0.394785472 */, 18 }, - /* 5771 */ { MAD_F(0x06516a3b) /* 0.394876702 */, 18 }, - /* 5772 */ { MAD_F(0x0651c9e6) /* 0.394967937 */, 18 }, - /* 5773 */ { MAD_F(0x06522992) /* 0.395059177 */, 18 }, - /* 5774 */ { MAD_F(0x06528940) /* 0.395150423 */, 18 }, - /* 5775 */ { MAD_F(0x0652e8ef) /* 0.395241673 */, 18 }, - - /* 5776 */ { MAD_F(0x0653489f) /* 0.395332930 */, 18 }, - /* 5777 */ { MAD_F(0x0653a851) /* 0.395424191 */, 18 }, - /* 5778 */ { MAD_F(0x06540804) /* 0.395515458 */, 18 }, - /* 5779 */ { MAD_F(0x065467b9) /* 0.395606730 */, 18 }, - /* 5780 */ { MAD_F(0x0654c76f) /* 0.395698007 */, 18 }, - /* 5781 */ { MAD_F(0x06552726) /* 0.395789289 */, 18 }, - /* 5782 */ { MAD_F(0x065586df) /* 0.395880577 */, 18 }, - /* 5783 */ { MAD_F(0x0655e699) /* 0.395971870 */, 18 }, - /* 5784 */ { MAD_F(0x06564655) /* 0.396063168 */, 18 }, - /* 5785 */ { MAD_F(0x0656a612) /* 0.396154472 */, 18 }, - /* 5786 */ { MAD_F(0x065705d0) /* 0.396245780 */, 18 }, - /* 5787 */ { MAD_F(0x06576590) /* 0.396337094 */, 18 }, - /* 5788 */ { MAD_F(0x0657c552) /* 0.396428414 */, 18 }, - /* 5789 */ { MAD_F(0x06582514) /* 0.396519738 */, 18 }, - /* 5790 */ { MAD_F(0x065884d9) /* 0.396611068 */, 18 }, - /* 5791 */ { MAD_F(0x0658e49e) /* 0.396702403 */, 18 }, - - /* 5792 */ { MAD_F(0x06594465) /* 0.396793743 */, 18 }, - /* 5793 */ { MAD_F(0x0659a42e) /* 0.396885089 */, 18 }, - /* 5794 */ { MAD_F(0x065a03f7) /* 0.396976440 */, 18 }, - /* 5795 */ { MAD_F(0x065a63c3) /* 0.397067796 */, 18 }, - /* 5796 */ { MAD_F(0x065ac38f) /* 0.397159157 */, 18 }, - /* 5797 */ { MAD_F(0x065b235d) /* 0.397250524 */, 18 }, - /* 5798 */ { MAD_F(0x065b832d) /* 0.397341896 */, 18 }, - /* 5799 */ { MAD_F(0x065be2fe) /* 0.397433273 */, 18 }, - /* 5800 */ { MAD_F(0x065c42d0) /* 0.397524655 */, 18 }, - /* 5801 */ { MAD_F(0x065ca2a3) /* 0.397616043 */, 18 }, - /* 5802 */ { MAD_F(0x065d0279) /* 0.397707436 */, 18 }, - /* 5803 */ { MAD_F(0x065d624f) /* 0.397798834 */, 18 }, - /* 5804 */ { MAD_F(0x065dc227) /* 0.397890237 */, 18 }, - /* 5805 */ { MAD_F(0x065e2200) /* 0.397981646 */, 18 }, - /* 5806 */ { MAD_F(0x065e81db) /* 0.398073059 */, 18 }, - /* 5807 */ { MAD_F(0x065ee1b7) /* 0.398164479 */, 18 }, - - /* 5808 */ { MAD_F(0x065f4195) /* 0.398255903 */, 18 }, - /* 5809 */ { MAD_F(0x065fa174) /* 0.398347333 */, 18 }, - /* 5810 */ { MAD_F(0x06600154) /* 0.398438767 */, 18 }, - /* 5811 */ { MAD_F(0x06606136) /* 0.398530207 */, 18 }, - /* 5812 */ { MAD_F(0x0660c119) /* 0.398621653 */, 18 }, - /* 5813 */ { MAD_F(0x066120fd) /* 0.398713103 */, 18 }, - /* 5814 */ { MAD_F(0x066180e3) /* 0.398804559 */, 18 }, - /* 5815 */ { MAD_F(0x0661e0cb) /* 0.398896020 */, 18 }, - /* 5816 */ { MAD_F(0x066240b4) /* 0.398987487 */, 18 }, - /* 5817 */ { MAD_F(0x0662a09e) /* 0.399078958 */, 18 }, - /* 5818 */ { MAD_F(0x06630089) /* 0.399170435 */, 18 }, - /* 5819 */ { MAD_F(0x06636077) /* 0.399261917 */, 18 }, - /* 5820 */ { MAD_F(0x0663c065) /* 0.399353404 */, 18 }, - /* 5821 */ { MAD_F(0x06642055) /* 0.399444897 */, 18 }, - /* 5822 */ { MAD_F(0x06648046) /* 0.399536395 */, 18 }, - /* 5823 */ { MAD_F(0x0664e039) /* 0.399627898 */, 18 }, - - /* 5824 */ { MAD_F(0x0665402d) /* 0.399719406 */, 18 }, - /* 5825 */ { MAD_F(0x0665a022) /* 0.399810919 */, 18 }, - /* 5826 */ { MAD_F(0x06660019) /* 0.399902438 */, 18 }, - /* 5827 */ { MAD_F(0x06666011) /* 0.399993962 */, 18 }, - /* 5828 */ { MAD_F(0x0666c00b) /* 0.400085491 */, 18 }, - /* 5829 */ { MAD_F(0x06672006) /* 0.400177026 */, 18 }, - /* 5830 */ { MAD_F(0x06678003) /* 0.400268565 */, 18 }, - /* 5831 */ { MAD_F(0x0667e000) /* 0.400360110 */, 18 }, - /* 5832 */ { MAD_F(0x06684000) /* 0.400451660 */, 18 }, - /* 5833 */ { MAD_F(0x0668a000) /* 0.400543216 */, 18 }, - /* 5834 */ { MAD_F(0x06690003) /* 0.400634776 */, 18 }, - /* 5835 */ { MAD_F(0x06696006) /* 0.400726342 */, 18 }, - /* 5836 */ { MAD_F(0x0669c00b) /* 0.400817913 */, 18 }, - /* 5837 */ { MAD_F(0x066a2011) /* 0.400909489 */, 18 }, - /* 5838 */ { MAD_F(0x066a8019) /* 0.401001071 */, 18 }, - /* 5839 */ { MAD_F(0x066ae022) /* 0.401092657 */, 18 }, - - /* 5840 */ { MAD_F(0x066b402d) /* 0.401184249 */, 18 }, - /* 5841 */ { MAD_F(0x066ba039) /* 0.401275847 */, 18 }, - /* 5842 */ { MAD_F(0x066c0046) /* 0.401367449 */, 18 }, - /* 5843 */ { MAD_F(0x066c6055) /* 0.401459057 */, 18 }, - /* 5844 */ { MAD_F(0x066cc065) /* 0.401550670 */, 18 }, - /* 5845 */ { MAD_F(0x066d2076) /* 0.401642288 */, 18 }, - /* 5846 */ { MAD_F(0x066d8089) /* 0.401733911 */, 18 }, - /* 5847 */ { MAD_F(0x066de09e) /* 0.401825540 */, 18 }, - /* 5848 */ { MAD_F(0x066e40b3) /* 0.401917173 */, 18 }, - /* 5849 */ { MAD_F(0x066ea0cb) /* 0.402008812 */, 18 }, - /* 5850 */ { MAD_F(0x066f00e3) /* 0.402100457 */, 18 }, - /* 5851 */ { MAD_F(0x066f60fd) /* 0.402192106 */, 18 }, - /* 5852 */ { MAD_F(0x066fc118) /* 0.402283761 */, 18 }, - /* 5853 */ { MAD_F(0x06702135) /* 0.402375420 */, 18 }, - /* 5854 */ { MAD_F(0x06708153) /* 0.402467086 */, 18 }, - /* 5855 */ { MAD_F(0x0670e173) /* 0.402558756 */, 18 }, - - /* 5856 */ { MAD_F(0x06714194) /* 0.402650431 */, 18 }, - /* 5857 */ { MAD_F(0x0671a1b6) /* 0.402742112 */, 18 }, - /* 5858 */ { MAD_F(0x067201da) /* 0.402833798 */, 18 }, - /* 5859 */ { MAD_F(0x067261ff) /* 0.402925489 */, 18 }, - /* 5860 */ { MAD_F(0x0672c226) /* 0.403017186 */, 18 }, - /* 5861 */ { MAD_F(0x0673224e) /* 0.403108887 */, 18 }, - /* 5862 */ { MAD_F(0x06738277) /* 0.403200594 */, 18 }, - /* 5863 */ { MAD_F(0x0673e2a2) /* 0.403292306 */, 18 }, - /* 5864 */ { MAD_F(0x067442ce) /* 0.403384024 */, 18 }, - /* 5865 */ { MAD_F(0x0674a2fc) /* 0.403475746 */, 18 }, - /* 5866 */ { MAD_F(0x0675032b) /* 0.403567474 */, 18 }, - /* 5867 */ { MAD_F(0x0675635b) /* 0.403659207 */, 18 }, - /* 5868 */ { MAD_F(0x0675c38d) /* 0.403750945 */, 18 }, - /* 5869 */ { MAD_F(0x067623c0) /* 0.403842688 */, 18 }, - /* 5870 */ { MAD_F(0x067683f4) /* 0.403934437 */, 18 }, - /* 5871 */ { MAD_F(0x0676e42a) /* 0.404026190 */, 18 }, - - /* 5872 */ { MAD_F(0x06774462) /* 0.404117949 */, 18 }, - /* 5873 */ { MAD_F(0x0677a49b) /* 0.404209714 */, 18 }, - /* 5874 */ { MAD_F(0x067804d5) /* 0.404301483 */, 18 }, - /* 5875 */ { MAD_F(0x06786510) /* 0.404393258 */, 18 }, - /* 5876 */ { MAD_F(0x0678c54d) /* 0.404485037 */, 18 }, - /* 5877 */ { MAD_F(0x0679258c) /* 0.404576822 */, 18 }, - /* 5878 */ { MAD_F(0x067985cb) /* 0.404668613 */, 18 }, - /* 5879 */ { MAD_F(0x0679e60c) /* 0.404760408 */, 18 }, - /* 5880 */ { MAD_F(0x067a464f) /* 0.404852209 */, 18 }, - /* 5881 */ { MAD_F(0x067aa693) /* 0.404944014 */, 18 }, - /* 5882 */ { MAD_F(0x067b06d8) /* 0.405035825 */, 18 }, - /* 5883 */ { MAD_F(0x067b671f) /* 0.405127642 */, 18 }, - /* 5884 */ { MAD_F(0x067bc767) /* 0.405219463 */, 18 }, - /* 5885 */ { MAD_F(0x067c27b1) /* 0.405311290 */, 18 }, - /* 5886 */ { MAD_F(0x067c87fc) /* 0.405403122 */, 18 }, - /* 5887 */ { MAD_F(0x067ce848) /* 0.405494959 */, 18 }, - - /* 5888 */ { MAD_F(0x067d4896) /* 0.405586801 */, 18 }, - /* 5889 */ { MAD_F(0x067da8e5) /* 0.405678648 */, 18 }, - /* 5890 */ { MAD_F(0x067e0935) /* 0.405770501 */, 18 }, - /* 5891 */ { MAD_F(0x067e6987) /* 0.405862359 */, 18 }, - /* 5892 */ { MAD_F(0x067ec9da) /* 0.405954222 */, 18 }, - /* 5893 */ { MAD_F(0x067f2a2f) /* 0.406046090 */, 18 }, - /* 5894 */ { MAD_F(0x067f8a85) /* 0.406137963 */, 18 }, - /* 5895 */ { MAD_F(0x067feadd) /* 0.406229842 */, 18 }, - /* 5896 */ { MAD_F(0x06804b36) /* 0.406321726 */, 18 }, - /* 5897 */ { MAD_F(0x0680ab90) /* 0.406413615 */, 18 }, - /* 5898 */ { MAD_F(0x06810beb) /* 0.406505509 */, 18 }, - /* 5899 */ { MAD_F(0x06816c49) /* 0.406597408 */, 18 }, - /* 5900 */ { MAD_F(0x0681cca7) /* 0.406689313 */, 18 }, - /* 5901 */ { MAD_F(0x06822d07) /* 0.406781223 */, 18 }, - /* 5902 */ { MAD_F(0x06828d68) /* 0.406873138 */, 18 }, - /* 5903 */ { MAD_F(0x0682edcb) /* 0.406965058 */, 18 }, - - /* 5904 */ { MAD_F(0x06834e2f) /* 0.407056983 */, 18 }, - /* 5905 */ { MAD_F(0x0683ae94) /* 0.407148914 */, 18 }, - /* 5906 */ { MAD_F(0x06840efb) /* 0.407240850 */, 18 }, - /* 5907 */ { MAD_F(0x06846f63) /* 0.407332791 */, 18 }, - /* 5908 */ { MAD_F(0x0684cfcd) /* 0.407424737 */, 18 }, - /* 5909 */ { MAD_F(0x06853038) /* 0.407516688 */, 18 }, - /* 5910 */ { MAD_F(0x068590a4) /* 0.407608645 */, 18 }, - /* 5911 */ { MAD_F(0x0685f112) /* 0.407700606 */, 18 }, - /* 5912 */ { MAD_F(0x06865181) /* 0.407792573 */, 18 }, - /* 5913 */ { MAD_F(0x0686b1f2) /* 0.407884545 */, 18 }, - /* 5914 */ { MAD_F(0x06871264) /* 0.407976522 */, 18 }, - /* 5915 */ { MAD_F(0x068772d7) /* 0.408068505 */, 18 }, - /* 5916 */ { MAD_F(0x0687d34c) /* 0.408160492 */, 18 }, - /* 5917 */ { MAD_F(0x068833c2) /* 0.408252485 */, 18 }, - /* 5918 */ { MAD_F(0x06889439) /* 0.408344483 */, 18 }, - /* 5919 */ { MAD_F(0x0688f4b2) /* 0.408436486 */, 18 }, - - /* 5920 */ { MAD_F(0x0689552c) /* 0.408528495 */, 18 }, - /* 5921 */ { MAD_F(0x0689b5a8) /* 0.408620508 */, 18 }, - /* 5922 */ { MAD_F(0x068a1625) /* 0.408712527 */, 18 }, - /* 5923 */ { MAD_F(0x068a76a4) /* 0.408804551 */, 18 }, - /* 5924 */ { MAD_F(0x068ad724) /* 0.408896580 */, 18 }, - /* 5925 */ { MAD_F(0x068b37a5) /* 0.408988614 */, 18 }, - /* 5926 */ { MAD_F(0x068b9827) /* 0.409080653 */, 18 }, - /* 5927 */ { MAD_F(0x068bf8ac) /* 0.409172698 */, 18 }, - /* 5928 */ { MAD_F(0x068c5931) /* 0.409264748 */, 18 }, - /* 5929 */ { MAD_F(0x068cb9b8) /* 0.409356803 */, 18 }, - /* 5930 */ { MAD_F(0x068d1a40) /* 0.409448863 */, 18 }, - /* 5931 */ { MAD_F(0x068d7aca) /* 0.409540928 */, 18 }, - /* 5932 */ { MAD_F(0x068ddb54) /* 0.409632999 */, 18 }, - /* 5933 */ { MAD_F(0x068e3be1) /* 0.409725074 */, 18 }, - /* 5934 */ { MAD_F(0x068e9c6f) /* 0.409817155 */, 18 }, - /* 5935 */ { MAD_F(0x068efcfe) /* 0.409909241 */, 18 }, - - /* 5936 */ { MAD_F(0x068f5d8e) /* 0.410001332 */, 18 }, - /* 5937 */ { MAD_F(0x068fbe20) /* 0.410093428 */, 18 }, - /* 5938 */ { MAD_F(0x06901eb4) /* 0.410185530 */, 18 }, - /* 5939 */ { MAD_F(0x06907f48) /* 0.410277637 */, 18 }, - /* 5940 */ { MAD_F(0x0690dfde) /* 0.410369748 */, 18 }, - /* 5941 */ { MAD_F(0x06914076) /* 0.410461865 */, 18 }, - /* 5942 */ { MAD_F(0x0691a10f) /* 0.410553988 */, 18 }, - /* 5943 */ { MAD_F(0x069201a9) /* 0.410646115 */, 18 }, - /* 5944 */ { MAD_F(0x06926245) /* 0.410738247 */, 18 }, - /* 5945 */ { MAD_F(0x0692c2e2) /* 0.410830385 */, 18 }, - /* 5946 */ { MAD_F(0x06932380) /* 0.410922528 */, 18 }, - /* 5947 */ { MAD_F(0x06938420) /* 0.411014676 */, 18 }, - /* 5948 */ { MAD_F(0x0693e4c1) /* 0.411106829 */, 18 }, - /* 5949 */ { MAD_F(0x06944563) /* 0.411198987 */, 18 }, - /* 5950 */ { MAD_F(0x0694a607) /* 0.411291151 */, 18 }, - /* 5951 */ { MAD_F(0x069506ad) /* 0.411383320 */, 18 }, - - /* 5952 */ { MAD_F(0x06956753) /* 0.411475493 */, 18 }, - /* 5953 */ { MAD_F(0x0695c7fc) /* 0.411567672 */, 18 }, - /* 5954 */ { MAD_F(0x069628a5) /* 0.411659857 */, 18 }, - /* 5955 */ { MAD_F(0x06968950) /* 0.411752046 */, 18 }, - /* 5956 */ { MAD_F(0x0696e9fc) /* 0.411844240 */, 18 }, - /* 5957 */ { MAD_F(0x06974aaa) /* 0.411936440 */, 18 }, - /* 5958 */ { MAD_F(0x0697ab59) /* 0.412028645 */, 18 }, - /* 5959 */ { MAD_F(0x06980c09) /* 0.412120855 */, 18 }, - /* 5960 */ { MAD_F(0x06986cbb) /* 0.412213070 */, 18 }, - /* 5961 */ { MAD_F(0x0698cd6e) /* 0.412305290 */, 18 }, - /* 5962 */ { MAD_F(0x06992e23) /* 0.412397516 */, 18 }, - /* 5963 */ { MAD_F(0x06998ed9) /* 0.412489746 */, 18 }, - /* 5964 */ { MAD_F(0x0699ef90) /* 0.412581982 */, 18 }, - /* 5965 */ { MAD_F(0x069a5049) /* 0.412674223 */, 18 }, - /* 5966 */ { MAD_F(0x069ab103) /* 0.412766469 */, 18 }, - /* 5967 */ { MAD_F(0x069b11bf) /* 0.412858720 */, 18 }, - - /* 5968 */ { MAD_F(0x069b727b) /* 0.412950976 */, 18 }, - /* 5969 */ { MAD_F(0x069bd33a) /* 0.413043238 */, 18 }, - /* 5970 */ { MAD_F(0x069c33f9) /* 0.413135505 */, 18 }, - /* 5971 */ { MAD_F(0x069c94ba) /* 0.413227776 */, 18 }, - /* 5972 */ { MAD_F(0x069cf57d) /* 0.413320053 */, 18 }, - /* 5973 */ { MAD_F(0x069d5641) /* 0.413412335 */, 18 }, - /* 5974 */ { MAD_F(0x069db706) /* 0.413504623 */, 18 }, - /* 5975 */ { MAD_F(0x069e17cc) /* 0.413596915 */, 18 }, - /* 5976 */ { MAD_F(0x069e7894) /* 0.413689213 */, 18 }, - /* 5977 */ { MAD_F(0x069ed95e) /* 0.413781515 */, 18 }, - /* 5978 */ { MAD_F(0x069f3a28) /* 0.413873823 */, 18 }, - /* 5979 */ { MAD_F(0x069f9af4) /* 0.413966136 */, 18 }, - /* 5980 */ { MAD_F(0x069ffbc2) /* 0.414058454 */, 18 }, - /* 5981 */ { MAD_F(0x06a05c91) /* 0.414150778 */, 18 }, - /* 5982 */ { MAD_F(0x06a0bd61) /* 0.414243106 */, 18 }, - /* 5983 */ { MAD_F(0x06a11e32) /* 0.414335440 */, 18 }, - - /* 5984 */ { MAD_F(0x06a17f05) /* 0.414427779 */, 18 }, - /* 5985 */ { MAD_F(0x06a1dfda) /* 0.414520122 */, 18 }, - /* 5986 */ { MAD_F(0x06a240b0) /* 0.414612471 */, 18 }, - /* 5987 */ { MAD_F(0x06a2a187) /* 0.414704826 */, 18 }, - /* 5988 */ { MAD_F(0x06a3025f) /* 0.414797185 */, 18 }, - /* 5989 */ { MAD_F(0x06a36339) /* 0.414889549 */, 18 }, - /* 5990 */ { MAD_F(0x06a3c414) /* 0.414981919 */, 18 }, - /* 5991 */ { MAD_F(0x06a424f1) /* 0.415074294 */, 18 }, - /* 5992 */ { MAD_F(0x06a485cf) /* 0.415166674 */, 18 }, - /* 5993 */ { MAD_F(0x06a4e6ae) /* 0.415259059 */, 18 }, - /* 5994 */ { MAD_F(0x06a5478f) /* 0.415351449 */, 18 }, - /* 5995 */ { MAD_F(0x06a5a871) /* 0.415443844 */, 18 }, - /* 5996 */ { MAD_F(0x06a60955) /* 0.415536244 */, 18 }, - /* 5997 */ { MAD_F(0x06a66a3a) /* 0.415628650 */, 18 }, - /* 5998 */ { MAD_F(0x06a6cb20) /* 0.415721061 */, 18 }, - /* 5999 */ { MAD_F(0x06a72c08) /* 0.415813476 */, 18 }, - - /* 6000 */ { MAD_F(0x06a78cf1) /* 0.415905897 */, 18 }, - /* 6001 */ { MAD_F(0x06a7eddb) /* 0.415998324 */, 18 }, - /* 6002 */ { MAD_F(0x06a84ec7) /* 0.416090755 */, 18 }, - /* 6003 */ { MAD_F(0x06a8afb4) /* 0.416183191 */, 18 }, - /* 6004 */ { MAD_F(0x06a910a3) /* 0.416275633 */, 18 }, - /* 6005 */ { MAD_F(0x06a97193) /* 0.416368079 */, 18 }, - /* 6006 */ { MAD_F(0x06a9d284) /* 0.416460531 */, 18 }, - /* 6007 */ { MAD_F(0x06aa3377) /* 0.416552988 */, 18 }, - /* 6008 */ { MAD_F(0x06aa946b) /* 0.416645450 */, 18 }, - /* 6009 */ { MAD_F(0x06aaf561) /* 0.416737917 */, 18 }, - /* 6010 */ { MAD_F(0x06ab5657) /* 0.416830389 */, 18 }, - /* 6011 */ { MAD_F(0x06abb750) /* 0.416922867 */, 18 }, - /* 6012 */ { MAD_F(0x06ac1849) /* 0.417015349 */, 18 }, - /* 6013 */ { MAD_F(0x06ac7944) /* 0.417107837 */, 18 }, - /* 6014 */ { MAD_F(0x06acda41) /* 0.417200330 */, 18 }, - /* 6015 */ { MAD_F(0x06ad3b3e) /* 0.417292828 */, 18 }, - - /* 6016 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 18 }, - /* 6017 */ { MAD_F(0x06adfd3e) /* 0.417477839 */, 18 }, - /* 6018 */ { MAD_F(0x06ae5e40) /* 0.417570352 */, 18 }, - /* 6019 */ { MAD_F(0x06aebf43) /* 0.417662871 */, 18 }, - /* 6020 */ { MAD_F(0x06af2047) /* 0.417755394 */, 18 }, - /* 6021 */ { MAD_F(0x06af814d) /* 0.417847923 */, 18 }, - /* 6022 */ { MAD_F(0x06afe255) /* 0.417940457 */, 18 }, - /* 6023 */ { MAD_F(0x06b0435e) /* 0.418032996 */, 18 }, - /* 6024 */ { MAD_F(0x06b0a468) /* 0.418125540 */, 18 }, - /* 6025 */ { MAD_F(0x06b10573) /* 0.418218089 */, 18 }, - /* 6026 */ { MAD_F(0x06b16680) /* 0.418310643 */, 18 }, - /* 6027 */ { MAD_F(0x06b1c78e) /* 0.418403203 */, 18 }, - /* 6028 */ { MAD_F(0x06b2289e) /* 0.418495767 */, 18 }, - /* 6029 */ { MAD_F(0x06b289af) /* 0.418588337 */, 18 }, - /* 6030 */ { MAD_F(0x06b2eac1) /* 0.418680911 */, 18 }, - /* 6031 */ { MAD_F(0x06b34bd5) /* 0.418773491 */, 18 }, - - /* 6032 */ { MAD_F(0x06b3acea) /* 0.418866076 */, 18 }, - /* 6033 */ { MAD_F(0x06b40e00) /* 0.418958666 */, 18 }, - /* 6034 */ { MAD_F(0x06b46f18) /* 0.419051262 */, 18 }, - /* 6035 */ { MAD_F(0x06b4d031) /* 0.419143862 */, 18 }, - /* 6036 */ { MAD_F(0x06b5314c) /* 0.419236467 */, 18 }, - /* 6037 */ { MAD_F(0x06b59268) /* 0.419329078 */, 18 }, - /* 6038 */ { MAD_F(0x06b5f385) /* 0.419421694 */, 18 }, - /* 6039 */ { MAD_F(0x06b654a4) /* 0.419514314 */, 18 }, - /* 6040 */ { MAD_F(0x06b6b5c4) /* 0.419606940 */, 18 }, - /* 6041 */ { MAD_F(0x06b716e6) /* 0.419699571 */, 18 }, - /* 6042 */ { MAD_F(0x06b77808) /* 0.419792208 */, 18 }, - /* 6043 */ { MAD_F(0x06b7d92d) /* 0.419884849 */, 18 }, - /* 6044 */ { MAD_F(0x06b83a52) /* 0.419977495 */, 18 }, - /* 6045 */ { MAD_F(0x06b89b79) /* 0.420070147 */, 18 }, - /* 6046 */ { MAD_F(0x06b8fca1) /* 0.420162803 */, 18 }, - /* 6047 */ { MAD_F(0x06b95dcb) /* 0.420255465 */, 18 }, - - /* 6048 */ { MAD_F(0x06b9bef6) /* 0.420348132 */, 18 }, - /* 6049 */ { MAD_F(0x06ba2023) /* 0.420440803 */, 18 }, - /* 6050 */ { MAD_F(0x06ba8150) /* 0.420533481 */, 18 }, - /* 6051 */ { MAD_F(0x06bae280) /* 0.420626163 */, 18 }, - /* 6052 */ { MAD_F(0x06bb43b0) /* 0.420718850 */, 18 }, - /* 6053 */ { MAD_F(0x06bba4e2) /* 0.420811542 */, 18 }, - /* 6054 */ { MAD_F(0x06bc0615) /* 0.420904240 */, 18 }, - /* 6055 */ { MAD_F(0x06bc674a) /* 0.420996942 */, 18 }, - /* 6056 */ { MAD_F(0x06bcc880) /* 0.421089650 */, 18 }, - /* 6057 */ { MAD_F(0x06bd29b7) /* 0.421182362 */, 18 }, - /* 6058 */ { MAD_F(0x06bd8af0) /* 0.421275080 */, 18 }, - /* 6059 */ { MAD_F(0x06bdec2a) /* 0.421367803 */, 18 }, - /* 6060 */ { MAD_F(0x06be4d66) /* 0.421460531 */, 18 }, - /* 6061 */ { MAD_F(0x06beaea3) /* 0.421553264 */, 18 }, - /* 6062 */ { MAD_F(0x06bf0fe1) /* 0.421646003 */, 18 }, - /* 6063 */ { MAD_F(0x06bf7120) /* 0.421738746 */, 18 }, - - /* 6064 */ { MAD_F(0x06bfd261) /* 0.421831494 */, 18 }, - /* 6065 */ { MAD_F(0x06c033a4) /* 0.421924248 */, 18 }, - /* 6066 */ { MAD_F(0x06c094e7) /* 0.422017007 */, 18 }, - /* 6067 */ { MAD_F(0x06c0f62c) /* 0.422109770 */, 18 }, - /* 6068 */ { MAD_F(0x06c15773) /* 0.422202539 */, 18 }, - /* 6069 */ { MAD_F(0x06c1b8bb) /* 0.422295313 */, 18 }, - /* 6070 */ { MAD_F(0x06c21a04) /* 0.422388092 */, 18 }, - /* 6071 */ { MAD_F(0x06c27b4e) /* 0.422480876 */, 18 }, - /* 6072 */ { MAD_F(0x06c2dc9a) /* 0.422573665 */, 18 }, - /* 6073 */ { MAD_F(0x06c33de8) /* 0.422666460 */, 18 }, - /* 6074 */ { MAD_F(0x06c39f36) /* 0.422759259 */, 18 }, - /* 6075 */ { MAD_F(0x06c40086) /* 0.422852064 */, 18 }, - /* 6076 */ { MAD_F(0x06c461d8) /* 0.422944873 */, 18 }, - /* 6077 */ { MAD_F(0x06c4c32a) /* 0.423037688 */, 18 }, - /* 6078 */ { MAD_F(0x06c5247f) /* 0.423130508 */, 18 }, - /* 6079 */ { MAD_F(0x06c585d4) /* 0.423223333 */, 18 }, - - /* 6080 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 18 }, - /* 6081 */ { MAD_F(0x06c64883) /* 0.423408997 */, 18 }, - /* 6082 */ { MAD_F(0x06c6a9dd) /* 0.423501838 */, 18 }, - /* 6083 */ { MAD_F(0x06c70b38) /* 0.423594683 */, 18 }, - /* 6084 */ { MAD_F(0x06c76c94) /* 0.423687533 */, 18 }, - /* 6085 */ { MAD_F(0x06c7cdf2) /* 0.423780389 */, 18 }, - /* 6086 */ { MAD_F(0x06c82f51) /* 0.423873249 */, 18 }, - /* 6087 */ { MAD_F(0x06c890b1) /* 0.423966115 */, 18 }, - /* 6088 */ { MAD_F(0x06c8f213) /* 0.424058985 */, 18 }, - /* 6089 */ { MAD_F(0x06c95376) /* 0.424151861 */, 18 }, - /* 6090 */ { MAD_F(0x06c9b4da) /* 0.424244742 */, 18 }, - /* 6091 */ { MAD_F(0x06ca1640) /* 0.424337628 */, 18 }, - /* 6092 */ { MAD_F(0x06ca77a8) /* 0.424430519 */, 18 }, - /* 6093 */ { MAD_F(0x06cad910) /* 0.424523415 */, 18 }, - /* 6094 */ { MAD_F(0x06cb3a7a) /* 0.424616316 */, 18 }, - /* 6095 */ { MAD_F(0x06cb9be5) /* 0.424709222 */, 18 }, - - /* 6096 */ { MAD_F(0x06cbfd52) /* 0.424802133 */, 18 }, - /* 6097 */ { MAD_F(0x06cc5ec0) /* 0.424895050 */, 18 }, - /* 6098 */ { MAD_F(0x06ccc030) /* 0.424987971 */, 18 }, - /* 6099 */ { MAD_F(0x06cd21a0) /* 0.425080898 */, 18 }, - /* 6100 */ { MAD_F(0x06cd8313) /* 0.425173829 */, 18 }, - /* 6101 */ { MAD_F(0x06cde486) /* 0.425266766 */, 18 }, - /* 6102 */ { MAD_F(0x06ce45fb) /* 0.425359708 */, 18 }, - /* 6103 */ { MAD_F(0x06cea771) /* 0.425452655 */, 18 }, - /* 6104 */ { MAD_F(0x06cf08e9) /* 0.425545607 */, 18 }, - /* 6105 */ { MAD_F(0x06cf6a62) /* 0.425638564 */, 18 }, - /* 6106 */ { MAD_F(0x06cfcbdc) /* 0.425731526 */, 18 }, - /* 6107 */ { MAD_F(0x06d02d58) /* 0.425824493 */, 18 }, - /* 6108 */ { MAD_F(0x06d08ed5) /* 0.425917465 */, 18 }, - /* 6109 */ { MAD_F(0x06d0f053) /* 0.426010443 */, 18 }, - /* 6110 */ { MAD_F(0x06d151d3) /* 0.426103425 */, 18 }, - /* 6111 */ { MAD_F(0x06d1b354) /* 0.426196412 */, 18 }, - - /* 6112 */ { MAD_F(0x06d214d7) /* 0.426289405 */, 18 }, - /* 6113 */ { MAD_F(0x06d2765a) /* 0.426382403 */, 18 }, - /* 6114 */ { MAD_F(0x06d2d7e0) /* 0.426475405 */, 18 }, - /* 6115 */ { MAD_F(0x06d33966) /* 0.426568413 */, 18 }, - /* 6116 */ { MAD_F(0x06d39aee) /* 0.426661426 */, 18 }, - /* 6117 */ { MAD_F(0x06d3fc77) /* 0.426754444 */, 18 }, - /* 6118 */ { MAD_F(0x06d45e02) /* 0.426847467 */, 18 }, - /* 6119 */ { MAD_F(0x06d4bf8e) /* 0.426940495 */, 18 }, - /* 6120 */ { MAD_F(0x06d5211c) /* 0.427033528 */, 18 }, - /* 6121 */ { MAD_F(0x06d582aa) /* 0.427126566 */, 18 }, - /* 6122 */ { MAD_F(0x06d5e43a) /* 0.427219609 */, 18 }, - /* 6123 */ { MAD_F(0x06d645cc) /* 0.427312657 */, 18 }, - /* 6124 */ { MAD_F(0x06d6a75f) /* 0.427405711 */, 18 }, - /* 6125 */ { MAD_F(0x06d708f3) /* 0.427498769 */, 18 }, - /* 6126 */ { MAD_F(0x06d76a88) /* 0.427591833 */, 18 }, - /* 6127 */ { MAD_F(0x06d7cc1f) /* 0.427684901 */, 18 }, - - /* 6128 */ { MAD_F(0x06d82db8) /* 0.427777975 */, 18 }, - /* 6129 */ { MAD_F(0x06d88f51) /* 0.427871054 */, 18 }, - /* 6130 */ { MAD_F(0x06d8f0ec) /* 0.427964137 */, 18 }, - /* 6131 */ { MAD_F(0x06d95288) /* 0.428057226 */, 18 }, - /* 6132 */ { MAD_F(0x06d9b426) /* 0.428150320 */, 18 }, - /* 6133 */ { MAD_F(0x06da15c5) /* 0.428243419 */, 18 }, - /* 6134 */ { MAD_F(0x06da7766) /* 0.428336523 */, 18 }, - /* 6135 */ { MAD_F(0x06dad907) /* 0.428429632 */, 18 }, - /* 6136 */ { MAD_F(0x06db3aaa) /* 0.428522746 */, 18 }, - /* 6137 */ { MAD_F(0x06db9c4f) /* 0.428615865 */, 18 }, - /* 6138 */ { MAD_F(0x06dbfdf5) /* 0.428708989 */, 18 }, - /* 6139 */ { MAD_F(0x06dc5f9c) /* 0.428802119 */, 18 }, - /* 6140 */ { MAD_F(0x06dcc145) /* 0.428895253 */, 18 }, - /* 6141 */ { MAD_F(0x06dd22ee) /* 0.428988392 */, 18 }, - /* 6142 */ { MAD_F(0x06dd849a) /* 0.429081537 */, 18 }, - /* 6143 */ { MAD_F(0x06dde646) /* 0.429174686 */, 18 }, - - /* 6144 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 18 }, - /* 6145 */ { MAD_F(0x06dea9a4) /* 0.429361001 */, 18 }, - /* 6146 */ { MAD_F(0x06df0b54) /* 0.429454165 */, 18 }, - /* 6147 */ { MAD_F(0x06df6d06) /* 0.429547335 */, 18 }, - /* 6148 */ { MAD_F(0x06dfceba) /* 0.429640510 */, 18 }, - /* 6149 */ { MAD_F(0x06e0306f) /* 0.429733690 */, 18 }, - /* 6150 */ { MAD_F(0x06e09225) /* 0.429826874 */, 18 }, - /* 6151 */ { MAD_F(0x06e0f3dc) /* 0.429920064 */, 18 }, - /* 6152 */ { MAD_F(0x06e15595) /* 0.430013259 */, 18 }, - /* 6153 */ { MAD_F(0x06e1b74f) /* 0.430106459 */, 18 }, - /* 6154 */ { MAD_F(0x06e2190b) /* 0.430199664 */, 18 }, - /* 6155 */ { MAD_F(0x06e27ac8) /* 0.430292875 */, 18 }, - /* 6156 */ { MAD_F(0x06e2dc86) /* 0.430386090 */, 18 }, - /* 6157 */ { MAD_F(0x06e33e46) /* 0.430479310 */, 18 }, - /* 6158 */ { MAD_F(0x06e3a007) /* 0.430572535 */, 18 }, - /* 6159 */ { MAD_F(0x06e401c9) /* 0.430665765 */, 18 }, - - /* 6160 */ { MAD_F(0x06e4638d) /* 0.430759001 */, 18 }, - /* 6161 */ { MAD_F(0x06e4c552) /* 0.430852241 */, 18 }, - /* 6162 */ { MAD_F(0x06e52718) /* 0.430945487 */, 18 }, - /* 6163 */ { MAD_F(0x06e588e0) /* 0.431038737 */, 18 }, - /* 6164 */ { MAD_F(0x06e5eaa9) /* 0.431131993 */, 18 }, - /* 6165 */ { MAD_F(0x06e64c73) /* 0.431225253 */, 18 }, - /* 6166 */ { MAD_F(0x06e6ae3f) /* 0.431318519 */, 18 }, - /* 6167 */ { MAD_F(0x06e7100c) /* 0.431411790 */, 18 }, - /* 6168 */ { MAD_F(0x06e771db) /* 0.431505065 */, 18 }, - /* 6169 */ { MAD_F(0x06e7d3ab) /* 0.431598346 */, 18 }, - /* 6170 */ { MAD_F(0x06e8357c) /* 0.431691632 */, 18 }, - /* 6171 */ { MAD_F(0x06e8974e) /* 0.431784923 */, 18 }, - /* 6172 */ { MAD_F(0x06e8f922) /* 0.431878218 */, 18 }, - /* 6173 */ { MAD_F(0x06e95af8) /* 0.431971519 */, 18 }, - /* 6174 */ { MAD_F(0x06e9bcce) /* 0.432064825 */, 18 }, - /* 6175 */ { MAD_F(0x06ea1ea6) /* 0.432158136 */, 18 }, - - /* 6176 */ { MAD_F(0x06ea807f) /* 0.432251452 */, 18 }, - /* 6177 */ { MAD_F(0x06eae25a) /* 0.432344773 */, 18 }, - /* 6178 */ { MAD_F(0x06eb4436) /* 0.432438099 */, 18 }, - /* 6179 */ { MAD_F(0x06eba614) /* 0.432531431 */, 18 }, - /* 6180 */ { MAD_F(0x06ec07f2) /* 0.432624767 */, 18 }, - /* 6181 */ { MAD_F(0x06ec69d2) /* 0.432718108 */, 18 }, - /* 6182 */ { MAD_F(0x06eccbb4) /* 0.432811454 */, 18 }, - /* 6183 */ { MAD_F(0x06ed2d97) /* 0.432904805 */, 18 }, - /* 6184 */ { MAD_F(0x06ed8f7b) /* 0.432998162 */, 18 }, - /* 6185 */ { MAD_F(0x06edf160) /* 0.433091523 */, 18 }, - /* 6186 */ { MAD_F(0x06ee5347) /* 0.433184889 */, 18 }, - /* 6187 */ { MAD_F(0x06eeb52f) /* 0.433278261 */, 18 }, - /* 6188 */ { MAD_F(0x06ef1719) /* 0.433371637 */, 18 }, - /* 6189 */ { MAD_F(0x06ef7904) /* 0.433465019 */, 18 }, - /* 6190 */ { MAD_F(0x06efdaf0) /* 0.433558405 */, 18 }, - /* 6191 */ { MAD_F(0x06f03cde) /* 0.433651797 */, 18 }, - - /* 6192 */ { MAD_F(0x06f09ecc) /* 0.433745193 */, 18 }, - /* 6193 */ { MAD_F(0x06f100bd) /* 0.433838595 */, 18 }, - /* 6194 */ { MAD_F(0x06f162ae) /* 0.433932001 */, 18 }, - /* 6195 */ { MAD_F(0x06f1c4a1) /* 0.434025413 */, 18 }, - /* 6196 */ { MAD_F(0x06f22696) /* 0.434118830 */, 18 }, - /* 6197 */ { MAD_F(0x06f2888b) /* 0.434212251 */, 18 }, - /* 6198 */ { MAD_F(0x06f2ea82) /* 0.434305678 */, 18 }, - /* 6199 */ { MAD_F(0x06f34c7b) /* 0.434399110 */, 18 }, - /* 6200 */ { MAD_F(0x06f3ae75) /* 0.434492546 */, 18 }, - /* 6201 */ { MAD_F(0x06f41070) /* 0.434585988 */, 18 }, - /* 6202 */ { MAD_F(0x06f4726c) /* 0.434679435 */, 18 }, - /* 6203 */ { MAD_F(0x06f4d46a) /* 0.434772887 */, 18 }, - /* 6204 */ { MAD_F(0x06f53669) /* 0.434866344 */, 18 }, - /* 6205 */ { MAD_F(0x06f59869) /* 0.434959806 */, 18 }, - /* 6206 */ { MAD_F(0x06f5fa6b) /* 0.435053272 */, 18 }, - /* 6207 */ { MAD_F(0x06f65c6e) /* 0.435146744 */, 18 }, - - /* 6208 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 18 }, - /* 6209 */ { MAD_F(0x06f72079) /* 0.435333703 */, 18 }, - /* 6210 */ { MAD_F(0x06f78280) /* 0.435427190 */, 18 }, - /* 6211 */ { MAD_F(0x06f7e489) /* 0.435520682 */, 18 }, - /* 6212 */ { MAD_F(0x06f84693) /* 0.435614179 */, 18 }, - /* 6213 */ { MAD_F(0x06f8a89e) /* 0.435707681 */, 18 }, - /* 6214 */ { MAD_F(0x06f90aaa) /* 0.435801188 */, 18 }, - /* 6215 */ { MAD_F(0x06f96cb8) /* 0.435894700 */, 18 }, - /* 6216 */ { MAD_F(0x06f9cec8) /* 0.435988217 */, 18 }, - /* 6217 */ { MAD_F(0x06fa30d8) /* 0.436081739 */, 18 }, - /* 6218 */ { MAD_F(0x06fa92ea) /* 0.436175266 */, 18 }, - /* 6219 */ { MAD_F(0x06faf4fe) /* 0.436268799 */, 18 }, - /* 6220 */ { MAD_F(0x06fb5712) /* 0.436362336 */, 18 }, - /* 6221 */ { MAD_F(0x06fbb928) /* 0.436455878 */, 18 }, - /* 6222 */ { MAD_F(0x06fc1b40) /* 0.436549425 */, 18 }, - /* 6223 */ { MAD_F(0x06fc7d58) /* 0.436642977 */, 18 }, - - /* 6224 */ { MAD_F(0x06fcdf72) /* 0.436736534 */, 18 }, - /* 6225 */ { MAD_F(0x06fd418e) /* 0.436830096 */, 18 }, - /* 6226 */ { MAD_F(0x06fda3ab) /* 0.436923664 */, 18 }, - /* 6227 */ { MAD_F(0x06fe05c9) /* 0.437017236 */, 18 }, - /* 6228 */ { MAD_F(0x06fe67e8) /* 0.437110813 */, 18 }, - /* 6229 */ { MAD_F(0x06feca09) /* 0.437204395 */, 18 }, - /* 6230 */ { MAD_F(0x06ff2c2b) /* 0.437297982 */, 18 }, - /* 6231 */ { MAD_F(0x06ff8e4f) /* 0.437391575 */, 18 }, - /* 6232 */ { MAD_F(0x06fff073) /* 0.437485172 */, 18 }, - /* 6233 */ { MAD_F(0x0700529a) /* 0.437578774 */, 18 }, - /* 6234 */ { MAD_F(0x0700b4c1) /* 0.437672381 */, 18 }, - /* 6235 */ { MAD_F(0x070116ea) /* 0.437765994 */, 18 }, - /* 6236 */ { MAD_F(0x07017914) /* 0.437859611 */, 18 }, - /* 6237 */ { MAD_F(0x0701db40) /* 0.437953233 */, 18 }, - /* 6238 */ { MAD_F(0x07023d6c) /* 0.438046860 */, 18 }, - /* 6239 */ { MAD_F(0x07029f9b) /* 0.438140493 */, 18 }, - - /* 6240 */ { MAD_F(0x070301ca) /* 0.438234130 */, 18 }, - /* 6241 */ { MAD_F(0x070363fb) /* 0.438327772 */, 18 }, - /* 6242 */ { MAD_F(0x0703c62d) /* 0.438421419 */, 18 }, - /* 6243 */ { MAD_F(0x07042861) /* 0.438515072 */, 18 }, - /* 6244 */ { MAD_F(0x07048a96) /* 0.438608729 */, 18 }, - /* 6245 */ { MAD_F(0x0704eccc) /* 0.438702391 */, 18 }, - /* 6246 */ { MAD_F(0x07054f04) /* 0.438796059 */, 18 }, - /* 6247 */ { MAD_F(0x0705b13d) /* 0.438889731 */, 18 }, - /* 6248 */ { MAD_F(0x07061377) /* 0.438983408 */, 18 }, - /* 6249 */ { MAD_F(0x070675b3) /* 0.439077090 */, 18 }, - /* 6250 */ { MAD_F(0x0706d7f0) /* 0.439170778 */, 18 }, - /* 6251 */ { MAD_F(0x07073a2e) /* 0.439264470 */, 18 }, - /* 6252 */ { MAD_F(0x07079c6e) /* 0.439358167 */, 18 }, - /* 6253 */ { MAD_F(0x0707feaf) /* 0.439451869 */, 18 }, - /* 6254 */ { MAD_F(0x070860f1) /* 0.439545577 */, 18 }, - /* 6255 */ { MAD_F(0x0708c335) /* 0.439639289 */, 18 }, - - /* 6256 */ { MAD_F(0x0709257a) /* 0.439733006 */, 18 }, - /* 6257 */ { MAD_F(0x070987c0) /* 0.439826728 */, 18 }, - /* 6258 */ { MAD_F(0x0709ea08) /* 0.439920456 */, 18 }, - /* 6259 */ { MAD_F(0x070a4c51) /* 0.440014188 */, 18 }, - /* 6260 */ { MAD_F(0x070aae9b) /* 0.440107925 */, 18 }, - /* 6261 */ { MAD_F(0x070b10e7) /* 0.440201667 */, 18 }, - /* 6262 */ { MAD_F(0x070b7334) /* 0.440295414 */, 18 }, - /* 6263 */ { MAD_F(0x070bd583) /* 0.440389167 */, 18 }, - /* 6264 */ { MAD_F(0x070c37d2) /* 0.440482924 */, 18 }, - /* 6265 */ { MAD_F(0x070c9a23) /* 0.440576686 */, 18 }, - /* 6266 */ { MAD_F(0x070cfc76) /* 0.440670453 */, 18 }, - /* 6267 */ { MAD_F(0x070d5eca) /* 0.440764225 */, 18 }, - /* 6268 */ { MAD_F(0x070dc11f) /* 0.440858002 */, 18 }, - /* 6269 */ { MAD_F(0x070e2375) /* 0.440951784 */, 18 }, - /* 6270 */ { MAD_F(0x070e85cd) /* 0.441045572 */, 18 }, - /* 6271 */ { MAD_F(0x070ee826) /* 0.441139364 */, 18 }, - - /* 6272 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 18 }, - /* 6273 */ { MAD_F(0x070facdc) /* 0.441326963 */, 18 }, - /* 6274 */ { MAD_F(0x07100f39) /* 0.441420770 */, 18 }, - /* 6275 */ { MAD_F(0x07107198) /* 0.441514582 */, 18 }, - /* 6276 */ { MAD_F(0x0710d3f8) /* 0.441608399 */, 18 }, - /* 6277 */ { MAD_F(0x07113659) /* 0.441702221 */, 18 }, - /* 6278 */ { MAD_F(0x071198bb) /* 0.441796048 */, 18 }, - /* 6279 */ { MAD_F(0x0711fb1f) /* 0.441889880 */, 18 }, - /* 6280 */ { MAD_F(0x07125d84) /* 0.441983717 */, 18 }, - /* 6281 */ { MAD_F(0x0712bfeb) /* 0.442077559 */, 18 }, - /* 6282 */ { MAD_F(0x07132253) /* 0.442171406 */, 18 }, - /* 6283 */ { MAD_F(0x071384bc) /* 0.442265257 */, 18 }, - /* 6284 */ { MAD_F(0x0713e726) /* 0.442359114 */, 18 }, - /* 6285 */ { MAD_F(0x07144992) /* 0.442452976 */, 18 }, - /* 6286 */ { MAD_F(0x0714abff) /* 0.442546843 */, 18 }, - /* 6287 */ { MAD_F(0x07150e6e) /* 0.442640715 */, 18 }, - - /* 6288 */ { MAD_F(0x071570de) /* 0.442734592 */, 18 }, - /* 6289 */ { MAD_F(0x0715d34f) /* 0.442828473 */, 18 }, - /* 6290 */ { MAD_F(0x071635c1) /* 0.442922360 */, 18 }, - /* 6291 */ { MAD_F(0x07169835) /* 0.443016252 */, 18 }, - /* 6292 */ { MAD_F(0x0716faaa) /* 0.443110148 */, 18 }, - /* 6293 */ { MAD_F(0x07175d21) /* 0.443204050 */, 18 }, - /* 6294 */ { MAD_F(0x0717bf99) /* 0.443297957 */, 18 }, - /* 6295 */ { MAD_F(0x07182212) /* 0.443391868 */, 18 }, - /* 6296 */ { MAD_F(0x0718848d) /* 0.443485785 */, 18 }, - /* 6297 */ { MAD_F(0x0718e709) /* 0.443579706 */, 18 }, - /* 6298 */ { MAD_F(0x07194986) /* 0.443673633 */, 18 }, - /* 6299 */ { MAD_F(0x0719ac04) /* 0.443767564 */, 18 }, - /* 6300 */ { MAD_F(0x071a0e84) /* 0.443861501 */, 18 }, - /* 6301 */ { MAD_F(0x071a7105) /* 0.443955442 */, 18 }, - /* 6302 */ { MAD_F(0x071ad388) /* 0.444049389 */, 18 }, - /* 6303 */ { MAD_F(0x071b360c) /* 0.444143340 */, 18 }, - - /* 6304 */ { MAD_F(0x071b9891) /* 0.444237296 */, 18 }, - /* 6305 */ { MAD_F(0x071bfb18) /* 0.444331258 */, 18 }, - /* 6306 */ { MAD_F(0x071c5d9f) /* 0.444425224 */, 18 }, - /* 6307 */ { MAD_F(0x071cc029) /* 0.444519195 */, 18 }, - /* 6308 */ { MAD_F(0x071d22b3) /* 0.444613171 */, 18 }, - /* 6309 */ { MAD_F(0x071d853f) /* 0.444707153 */, 18 }, - /* 6310 */ { MAD_F(0x071de7cc) /* 0.444801139 */, 18 }, - /* 6311 */ { MAD_F(0x071e4a5b) /* 0.444895130 */, 18 }, - /* 6312 */ { MAD_F(0x071eaceb) /* 0.444989126 */, 18 }, - /* 6313 */ { MAD_F(0x071f0f7c) /* 0.445083127 */, 18 }, - /* 6314 */ { MAD_F(0x071f720e) /* 0.445177133 */, 18 }, - /* 6315 */ { MAD_F(0x071fd4a2) /* 0.445271144 */, 18 }, - /* 6316 */ { MAD_F(0x07203737) /* 0.445365160 */, 18 }, - /* 6317 */ { MAD_F(0x072099ce) /* 0.445459181 */, 18 }, - /* 6318 */ { MAD_F(0x0720fc66) /* 0.445553206 */, 18 }, - /* 6319 */ { MAD_F(0x07215eff) /* 0.445647237 */, 18 }, - - /* 6320 */ { MAD_F(0x0721c19a) /* 0.445741273 */, 18 }, - /* 6321 */ { MAD_F(0x07222436) /* 0.445835314 */, 18 }, - /* 6322 */ { MAD_F(0x072286d3) /* 0.445929359 */, 18 }, - /* 6323 */ { MAD_F(0x0722e971) /* 0.446023410 */, 18 }, - /* 6324 */ { MAD_F(0x07234c11) /* 0.446117466 */, 18 }, - /* 6325 */ { MAD_F(0x0723aeb2) /* 0.446211526 */, 18 }, - /* 6326 */ { MAD_F(0x07241155) /* 0.446305592 */, 18 }, - /* 6327 */ { MAD_F(0x072473f9) /* 0.446399662 */, 18 }, - /* 6328 */ { MAD_F(0x0724d69e) /* 0.446493738 */, 18 }, - /* 6329 */ { MAD_F(0x07253944) /* 0.446587818 */, 18 }, - /* 6330 */ { MAD_F(0x07259bec) /* 0.446681903 */, 18 }, - /* 6331 */ { MAD_F(0x0725fe95) /* 0.446775994 */, 18 }, - /* 6332 */ { MAD_F(0x07266140) /* 0.446870089 */, 18 }, - /* 6333 */ { MAD_F(0x0726c3ec) /* 0.446964189 */, 18 }, - /* 6334 */ { MAD_F(0x07272699) /* 0.447058294 */, 18 }, - /* 6335 */ { MAD_F(0x07278947) /* 0.447152404 */, 18 }, - - /* 6336 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 18 }, - /* 6337 */ { MAD_F(0x07284ea8) /* 0.447340639 */, 18 }, - /* 6338 */ { MAD_F(0x0728b15b) /* 0.447434764 */, 18 }, - /* 6339 */ { MAD_F(0x0729140f) /* 0.447528894 */, 18 }, - /* 6340 */ { MAD_F(0x072976c4) /* 0.447623029 */, 18 }, - /* 6341 */ { MAD_F(0x0729d97a) /* 0.447717169 */, 18 }, - /* 6342 */ { MAD_F(0x072a3c32) /* 0.447811314 */, 18 }, - /* 6343 */ { MAD_F(0x072a9eeb) /* 0.447905463 */, 18 }, - /* 6344 */ { MAD_F(0x072b01a6) /* 0.447999618 */, 18 }, - /* 6345 */ { MAD_F(0x072b6461) /* 0.448093778 */, 18 }, - /* 6346 */ { MAD_F(0x072bc71e) /* 0.448187942 */, 18 }, - /* 6347 */ { MAD_F(0x072c29dd) /* 0.448282112 */, 18 }, - /* 6348 */ { MAD_F(0x072c8c9d) /* 0.448376286 */, 18 }, - /* 6349 */ { MAD_F(0x072cef5e) /* 0.448470466 */, 18 }, - /* 6350 */ { MAD_F(0x072d5220) /* 0.448564650 */, 18 }, - /* 6351 */ { MAD_F(0x072db4e4) /* 0.448658839 */, 18 }, - - /* 6352 */ { MAD_F(0x072e17a9) /* 0.448753033 */, 18 }, - /* 6353 */ { MAD_F(0x072e7a6f) /* 0.448847233 */, 18 }, - /* 6354 */ { MAD_F(0x072edd37) /* 0.448941437 */, 18 }, - /* 6355 */ { MAD_F(0x072f4000) /* 0.449035646 */, 18 }, - /* 6356 */ { MAD_F(0x072fa2ca) /* 0.449129860 */, 18 }, - /* 6357 */ { MAD_F(0x07300596) /* 0.449224079 */, 18 }, - /* 6358 */ { MAD_F(0x07306863) /* 0.449318303 */, 18 }, - /* 6359 */ { MAD_F(0x0730cb32) /* 0.449412531 */, 18 }, - /* 6360 */ { MAD_F(0x07312e01) /* 0.449506765 */, 18 }, - /* 6361 */ { MAD_F(0x073190d2) /* 0.449601004 */, 18 }, - /* 6362 */ { MAD_F(0x0731f3a5) /* 0.449695247 */, 18 }, - /* 6363 */ { MAD_F(0x07325678) /* 0.449789496 */, 18 }, - /* 6364 */ { MAD_F(0x0732b94d) /* 0.449883749 */, 18 }, - /* 6365 */ { MAD_F(0x07331c23) /* 0.449978008 */, 18 }, - /* 6366 */ { MAD_F(0x07337efb) /* 0.450072271 */, 18 }, - /* 6367 */ { MAD_F(0x0733e1d4) /* 0.450166540 */, 18 }, - - /* 6368 */ { MAD_F(0x073444ae) /* 0.450260813 */, 18 }, - /* 6369 */ { MAD_F(0x0734a78a) /* 0.450355091 */, 18 }, - /* 6370 */ { MAD_F(0x07350a67) /* 0.450449374 */, 18 }, - /* 6371 */ { MAD_F(0x07356d45) /* 0.450543662 */, 18 }, - /* 6372 */ { MAD_F(0x0735d025) /* 0.450637955 */, 18 }, - /* 6373 */ { MAD_F(0x07363306) /* 0.450732253 */, 18 }, - /* 6374 */ { MAD_F(0x073695e8) /* 0.450826556 */, 18 }, - /* 6375 */ { MAD_F(0x0736f8cb) /* 0.450920864 */, 18 }, - /* 6376 */ { MAD_F(0x07375bb0) /* 0.451015176 */, 18 }, - /* 6377 */ { MAD_F(0x0737be96) /* 0.451109494 */, 18 }, - /* 6378 */ { MAD_F(0x0738217e) /* 0.451203817 */, 18 }, - /* 6379 */ { MAD_F(0x07388467) /* 0.451298144 */, 18 }, - /* 6380 */ { MAD_F(0x0738e751) /* 0.451392477 */, 18 }, - /* 6381 */ { MAD_F(0x07394a3d) /* 0.451486814 */, 18 }, - /* 6382 */ { MAD_F(0x0739ad29) /* 0.451581156 */, 18 }, - /* 6383 */ { MAD_F(0x073a1017) /* 0.451675503 */, 18 }, - - /* 6384 */ { MAD_F(0x073a7307) /* 0.451769856 */, 18 }, - /* 6385 */ { MAD_F(0x073ad5f8) /* 0.451864213 */, 18 }, - /* 6386 */ { MAD_F(0x073b38ea) /* 0.451958575 */, 18 }, - /* 6387 */ { MAD_F(0x073b9bdd) /* 0.452052942 */, 18 }, - /* 6388 */ { MAD_F(0x073bfed2) /* 0.452147313 */, 18 }, - /* 6389 */ { MAD_F(0x073c61c8) /* 0.452241690 */, 18 }, - /* 6390 */ { MAD_F(0x073cc4bf) /* 0.452336072 */, 18 }, - /* 6391 */ { MAD_F(0x073d27b8) /* 0.452430458 */, 18 }, - /* 6392 */ { MAD_F(0x073d8ab2) /* 0.452524850 */, 18 }, - /* 6393 */ { MAD_F(0x073dedae) /* 0.452619246 */, 18 }, - /* 6394 */ { MAD_F(0x073e50aa) /* 0.452713648 */, 18 }, - /* 6395 */ { MAD_F(0x073eb3a8) /* 0.452808054 */, 18 }, - /* 6396 */ { MAD_F(0x073f16a8) /* 0.452902465 */, 18 }, - /* 6397 */ { MAD_F(0x073f79a8) /* 0.452996882 */, 18 }, - /* 6398 */ { MAD_F(0x073fdcaa) /* 0.453091303 */, 18 }, - /* 6399 */ { MAD_F(0x07403fad) /* 0.453185729 */, 18 }, - - /* 6400 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 18 }, - /* 6401 */ { MAD_F(0x074105b8) /* 0.453374595 */, 18 }, - /* 6402 */ { MAD_F(0x074168bf) /* 0.453469036 */, 18 }, - /* 6403 */ { MAD_F(0x0741cbc8) /* 0.453563482 */, 18 }, - /* 6404 */ { MAD_F(0x07422ed2) /* 0.453657932 */, 18 }, - /* 6405 */ { MAD_F(0x074291dd) /* 0.453752388 */, 18 }, - /* 6406 */ { MAD_F(0x0742f4e9) /* 0.453846848 */, 18 }, - /* 6407 */ { MAD_F(0x074357f7) /* 0.453941314 */, 18 }, - /* 6408 */ { MAD_F(0x0743bb06) /* 0.454035784 */, 18 }, - /* 6409 */ { MAD_F(0x07441e17) /* 0.454130259 */, 18 }, - /* 6410 */ { MAD_F(0x07448129) /* 0.454224739 */, 18 }, - /* 6411 */ { MAD_F(0x0744e43c) /* 0.454319224 */, 18 }, - /* 6412 */ { MAD_F(0x07454750) /* 0.454413714 */, 18 }, - /* 6413 */ { MAD_F(0x0745aa66) /* 0.454508209 */, 18 }, - /* 6414 */ { MAD_F(0x07460d7d) /* 0.454602708 */, 18 }, - /* 6415 */ { MAD_F(0x07467095) /* 0.454697213 */, 18 }, - - /* 6416 */ { MAD_F(0x0746d3af) /* 0.454791723 */, 18 }, - /* 6417 */ { MAD_F(0x074736ca) /* 0.454886237 */, 18 }, - /* 6418 */ { MAD_F(0x074799e7) /* 0.454980756 */, 18 }, - /* 6419 */ { MAD_F(0x0747fd04) /* 0.455075281 */, 18 }, - /* 6420 */ { MAD_F(0x07486023) /* 0.455169810 */, 18 }, - /* 6421 */ { MAD_F(0x0748c344) /* 0.455264344 */, 18 }, - /* 6422 */ { MAD_F(0x07492665) /* 0.455358883 */, 18 }, - /* 6423 */ { MAD_F(0x07498988) /* 0.455453427 */, 18 }, - /* 6424 */ { MAD_F(0x0749ecac) /* 0.455547976 */, 18 }, - /* 6425 */ { MAD_F(0x074a4fd2) /* 0.455642529 */, 18 }, - /* 6426 */ { MAD_F(0x074ab2f9) /* 0.455737088 */, 18 }, - /* 6427 */ { MAD_F(0x074b1621) /* 0.455831652 */, 18 }, - /* 6428 */ { MAD_F(0x074b794b) /* 0.455926220 */, 18 }, - /* 6429 */ { MAD_F(0x074bdc75) /* 0.456020793 */, 18 }, - /* 6430 */ { MAD_F(0x074c3fa1) /* 0.456115372 */, 18 }, - /* 6431 */ { MAD_F(0x074ca2cf) /* 0.456209955 */, 18 }, - - /* 6432 */ { MAD_F(0x074d05fe) /* 0.456304543 */, 18 }, - /* 6433 */ { MAD_F(0x074d692e) /* 0.456399136 */, 18 }, - /* 6434 */ { MAD_F(0x074dcc5f) /* 0.456493733 */, 18 }, - /* 6435 */ { MAD_F(0x074e2f92) /* 0.456588336 */, 18 }, - /* 6436 */ { MAD_F(0x074e92c6) /* 0.456682944 */, 18 }, - /* 6437 */ { MAD_F(0x074ef5fb) /* 0.456777556 */, 18 }, - /* 6438 */ { MAD_F(0x074f5932) /* 0.456872174 */, 18 }, - /* 6439 */ { MAD_F(0x074fbc6a) /* 0.456966796 */, 18 }, - /* 6440 */ { MAD_F(0x07501fa3) /* 0.457061423 */, 18 }, - /* 6441 */ { MAD_F(0x075082de) /* 0.457156056 */, 18 }, - /* 6442 */ { MAD_F(0x0750e61a) /* 0.457250693 */, 18 }, - /* 6443 */ { MAD_F(0x07514957) /* 0.457345335 */, 18 }, - /* 6444 */ { MAD_F(0x0751ac96) /* 0.457439981 */, 18 }, - /* 6445 */ { MAD_F(0x07520fd6) /* 0.457534633 */, 18 }, - /* 6446 */ { MAD_F(0x07527317) /* 0.457629290 */, 18 }, - /* 6447 */ { MAD_F(0x0752d659) /* 0.457723951 */, 18 }, - - /* 6448 */ { MAD_F(0x0753399d) /* 0.457818618 */, 18 }, - /* 6449 */ { MAD_F(0x07539ce2) /* 0.457913289 */, 18 }, - /* 6450 */ { MAD_F(0x07540029) /* 0.458007965 */, 18 }, - /* 6451 */ { MAD_F(0x07546371) /* 0.458102646 */, 18 }, - /* 6452 */ { MAD_F(0x0754c6ba) /* 0.458197332 */, 18 }, - /* 6453 */ { MAD_F(0x07552a04) /* 0.458292023 */, 18 }, - /* 6454 */ { MAD_F(0x07558d50) /* 0.458386719 */, 18 }, - /* 6455 */ { MAD_F(0x0755f09d) /* 0.458481420 */, 18 }, - /* 6456 */ { MAD_F(0x075653eb) /* 0.458576125 */, 18 }, - /* 6457 */ { MAD_F(0x0756b73b) /* 0.458670836 */, 18 }, - /* 6458 */ { MAD_F(0x07571a8c) /* 0.458765551 */, 18 }, - /* 6459 */ { MAD_F(0x07577dde) /* 0.458860271 */, 18 }, - /* 6460 */ { MAD_F(0x0757e131) /* 0.458954996 */, 18 }, - /* 6461 */ { MAD_F(0x07584486) /* 0.459049726 */, 18 }, - /* 6462 */ { MAD_F(0x0758a7dd) /* 0.459144461 */, 18 }, - /* 6463 */ { MAD_F(0x07590b34) /* 0.459239201 */, 18 }, - - /* 6464 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 18 }, - /* 6465 */ { MAD_F(0x0759d1e7) /* 0.459428695 */, 18 }, - /* 6466 */ { MAD_F(0x075a3542) /* 0.459523450 */, 18 }, - /* 6467 */ { MAD_F(0x075a989f) /* 0.459618209 */, 18 }, - /* 6468 */ { MAD_F(0x075afbfd) /* 0.459712973 */, 18 }, - /* 6469 */ { MAD_F(0x075b5f5d) /* 0.459807742 */, 18 }, - /* 6470 */ { MAD_F(0x075bc2bd) /* 0.459902516 */, 18 }, - /* 6471 */ { MAD_F(0x075c261f) /* 0.459997295 */, 18 }, - /* 6472 */ { MAD_F(0x075c8983) /* 0.460092079 */, 18 }, - /* 6473 */ { MAD_F(0x075cece7) /* 0.460186867 */, 18 }, - /* 6474 */ { MAD_F(0x075d504d) /* 0.460281661 */, 18 }, - /* 6475 */ { MAD_F(0x075db3b5) /* 0.460376459 */, 18 }, - /* 6476 */ { MAD_F(0x075e171d) /* 0.460471262 */, 18 }, - /* 6477 */ { MAD_F(0x075e7a87) /* 0.460566071 */, 18 }, - /* 6478 */ { MAD_F(0x075eddf2) /* 0.460660884 */, 18 }, - /* 6479 */ { MAD_F(0x075f415f) /* 0.460755701 */, 18 }, - - /* 6480 */ { MAD_F(0x075fa4cc) /* 0.460850524 */, 18 }, - /* 6481 */ { MAD_F(0x0760083b) /* 0.460945352 */, 18 }, - /* 6482 */ { MAD_F(0x07606bac) /* 0.461040184 */, 18 }, - /* 6483 */ { MAD_F(0x0760cf1e) /* 0.461135022 */, 18 }, - /* 6484 */ { MAD_F(0x07613291) /* 0.461229864 */, 18 }, - /* 6485 */ { MAD_F(0x07619605) /* 0.461324711 */, 18 }, - /* 6486 */ { MAD_F(0x0761f97b) /* 0.461419563 */, 18 }, - /* 6487 */ { MAD_F(0x07625cf2) /* 0.461514420 */, 18 }, - /* 6488 */ { MAD_F(0x0762c06a) /* 0.461609282 */, 18 }, - /* 6489 */ { MAD_F(0x076323e3) /* 0.461704149 */, 18 }, - /* 6490 */ { MAD_F(0x0763875e) /* 0.461799020 */, 18 }, - /* 6491 */ { MAD_F(0x0763eadb) /* 0.461893897 */, 18 }, - /* 6492 */ { MAD_F(0x07644e58) /* 0.461988778 */, 18 }, - /* 6493 */ { MAD_F(0x0764b1d7) /* 0.462083664 */, 18 }, - /* 6494 */ { MAD_F(0x07651557) /* 0.462178555 */, 18 }, - /* 6495 */ { MAD_F(0x076578d8) /* 0.462273451 */, 18 }, - - /* 6496 */ { MAD_F(0x0765dc5b) /* 0.462368352 */, 18 }, - /* 6497 */ { MAD_F(0x07663fdf) /* 0.462463257 */, 18 }, - /* 6498 */ { MAD_F(0x0766a364) /* 0.462558168 */, 18 }, - /* 6499 */ { MAD_F(0x076706eb) /* 0.462653083 */, 18 }, - /* 6500 */ { MAD_F(0x07676a73) /* 0.462748003 */, 18 }, - /* 6501 */ { MAD_F(0x0767cdfc) /* 0.462842928 */, 18 }, - /* 6502 */ { MAD_F(0x07683187) /* 0.462937858 */, 18 }, - /* 6503 */ { MAD_F(0x07689513) /* 0.463032793 */, 18 }, - /* 6504 */ { MAD_F(0x0768f8a0) /* 0.463127733 */, 18 }, - /* 6505 */ { MAD_F(0x07695c2e) /* 0.463222678 */, 18 }, - /* 6506 */ { MAD_F(0x0769bfbe) /* 0.463317627 */, 18 }, - /* 6507 */ { MAD_F(0x076a234f) /* 0.463412581 */, 18 }, - /* 6508 */ { MAD_F(0x076a86e2) /* 0.463507540 */, 18 }, - /* 6509 */ { MAD_F(0x076aea75) /* 0.463602504 */, 18 }, - /* 6510 */ { MAD_F(0x076b4e0a) /* 0.463697473 */, 18 }, - /* 6511 */ { MAD_F(0x076bb1a1) /* 0.463792447 */, 18 }, - - /* 6512 */ { MAD_F(0x076c1538) /* 0.463887426 */, 18 }, - /* 6513 */ { MAD_F(0x076c78d1) /* 0.463982409 */, 18 }, - /* 6514 */ { MAD_F(0x076cdc6c) /* 0.464077398 */, 18 }, - /* 6515 */ { MAD_F(0x076d4007) /* 0.464172391 */, 18 }, - /* 6516 */ { MAD_F(0x076da3a4) /* 0.464267389 */, 18 }, - /* 6517 */ { MAD_F(0x076e0742) /* 0.464362392 */, 18 }, - /* 6518 */ { MAD_F(0x076e6ae2) /* 0.464457399 */, 18 }, - /* 6519 */ { MAD_F(0x076ece82) /* 0.464552412 */, 18 }, - /* 6520 */ { MAD_F(0x076f3224) /* 0.464647430 */, 18 }, - /* 6521 */ { MAD_F(0x076f95c8) /* 0.464742452 */, 18 }, - /* 6522 */ { MAD_F(0x076ff96c) /* 0.464837479 */, 18 }, - /* 6523 */ { MAD_F(0x07705d12) /* 0.464932511 */, 18 }, - /* 6524 */ { MAD_F(0x0770c0ba) /* 0.465027548 */, 18 }, - /* 6525 */ { MAD_F(0x07712462) /* 0.465122590 */, 18 }, - /* 6526 */ { MAD_F(0x0771880c) /* 0.465217637 */, 18 }, - /* 6527 */ { MAD_F(0x0771ebb7) /* 0.465312688 */, 18 }, - - /* 6528 */ { MAD_F(0x07724f64) /* 0.465407744 */, 18 }, - /* 6529 */ { MAD_F(0x0772b312) /* 0.465502806 */, 18 }, - /* 6530 */ { MAD_F(0x077316c1) /* 0.465597872 */, 18 }, - /* 6531 */ { MAD_F(0x07737a71) /* 0.465692943 */, 18 }, - /* 6532 */ { MAD_F(0x0773de23) /* 0.465788018 */, 18 }, - /* 6533 */ { MAD_F(0x077441d6) /* 0.465883099 */, 18 }, - /* 6534 */ { MAD_F(0x0774a58a) /* 0.465978184 */, 18 }, - /* 6535 */ { MAD_F(0x07750940) /* 0.466073275 */, 18 }, - /* 6536 */ { MAD_F(0x07756cf7) /* 0.466168370 */, 18 }, - /* 6537 */ { MAD_F(0x0775d0af) /* 0.466263470 */, 18 }, - /* 6538 */ { MAD_F(0x07763468) /* 0.466358575 */, 18 }, - /* 6539 */ { MAD_F(0x07769823) /* 0.466453684 */, 18 }, - /* 6540 */ { MAD_F(0x0776fbdf) /* 0.466548799 */, 18 }, - /* 6541 */ { MAD_F(0x07775f9d) /* 0.466643918 */, 18 }, - /* 6542 */ { MAD_F(0x0777c35c) /* 0.466739043 */, 18 }, - /* 6543 */ { MAD_F(0x0778271c) /* 0.466834172 */, 18 }, - - /* 6544 */ { MAD_F(0x07788add) /* 0.466929306 */, 18 }, - /* 6545 */ { MAD_F(0x0778ee9f) /* 0.467024445 */, 18 }, - /* 6546 */ { MAD_F(0x07795263) /* 0.467119588 */, 18 }, - /* 6547 */ { MAD_F(0x0779b629) /* 0.467214737 */, 18 }, - /* 6548 */ { MAD_F(0x077a19ef) /* 0.467309890 */, 18 }, - /* 6549 */ { MAD_F(0x077a7db7) /* 0.467405048 */, 18 }, - /* 6550 */ { MAD_F(0x077ae180) /* 0.467500211 */, 18 }, - /* 6551 */ { MAD_F(0x077b454b) /* 0.467595379 */, 18 }, - /* 6552 */ { MAD_F(0x077ba916) /* 0.467690552 */, 18 }, - /* 6553 */ { MAD_F(0x077c0ce3) /* 0.467785729 */, 18 }, - /* 6554 */ { MAD_F(0x077c70b2) /* 0.467880912 */, 18 }, - /* 6555 */ { MAD_F(0x077cd481) /* 0.467976099 */, 18 }, - /* 6556 */ { MAD_F(0x077d3852) /* 0.468071291 */, 18 }, - /* 6557 */ { MAD_F(0x077d9c24) /* 0.468166488 */, 18 }, - /* 6558 */ { MAD_F(0x077dfff8) /* 0.468261690 */, 18 }, - /* 6559 */ { MAD_F(0x077e63cd) /* 0.468356896 */, 18 }, - - /* 6560 */ { MAD_F(0x077ec7a3) /* 0.468452108 */, 18 }, - /* 6561 */ { MAD_F(0x077f2b7a) /* 0.468547324 */, 18 }, - /* 6562 */ { MAD_F(0x077f8f53) /* 0.468642545 */, 18 }, - /* 6563 */ { MAD_F(0x077ff32d) /* 0.468737771 */, 18 }, - /* 6564 */ { MAD_F(0x07805708) /* 0.468833002 */, 18 }, - /* 6565 */ { MAD_F(0x0780bae5) /* 0.468928237 */, 18 }, - /* 6566 */ { MAD_F(0x07811ec3) /* 0.469023478 */, 18 }, - /* 6567 */ { MAD_F(0x078182a2) /* 0.469118723 */, 18 }, - /* 6568 */ { MAD_F(0x0781e683) /* 0.469213973 */, 18 }, - /* 6569 */ { MAD_F(0x07824a64) /* 0.469309228 */, 18 }, - /* 6570 */ { MAD_F(0x0782ae47) /* 0.469404488 */, 18 }, - /* 6571 */ { MAD_F(0x0783122c) /* 0.469499752 */, 18 }, - /* 6572 */ { MAD_F(0x07837612) /* 0.469595022 */, 18 }, - /* 6573 */ { MAD_F(0x0783d9f9) /* 0.469690296 */, 18 }, - /* 6574 */ { MAD_F(0x07843de1) /* 0.469785575 */, 18 }, - /* 6575 */ { MAD_F(0x0784a1ca) /* 0.469880859 */, 18 }, - - /* 6576 */ { MAD_F(0x078505b5) /* 0.469976148 */, 18 }, - /* 6577 */ { MAD_F(0x078569a2) /* 0.470071442 */, 18 }, - /* 6578 */ { MAD_F(0x0785cd8f) /* 0.470166740 */, 18 }, - /* 6579 */ { MAD_F(0x0786317e) /* 0.470262043 */, 18 }, - /* 6580 */ { MAD_F(0x0786956e) /* 0.470357351 */, 18 }, - /* 6581 */ { MAD_F(0x0786f95f) /* 0.470452664 */, 18 }, - /* 6582 */ { MAD_F(0x07875d52) /* 0.470547982 */, 18 }, - /* 6583 */ { MAD_F(0x0787c146) /* 0.470643305 */, 18 }, - /* 6584 */ { MAD_F(0x0788253b) /* 0.470738632 */, 18 }, - /* 6585 */ { MAD_F(0x07888932) /* 0.470833964 */, 18 }, - /* 6586 */ { MAD_F(0x0788ed2a) /* 0.470929301 */, 18 }, - /* 6587 */ { MAD_F(0x07895123) /* 0.471024643 */, 18 }, - /* 6588 */ { MAD_F(0x0789b51d) /* 0.471119990 */, 18 }, - /* 6589 */ { MAD_F(0x078a1919) /* 0.471215341 */, 18 }, - /* 6590 */ { MAD_F(0x078a7d16) /* 0.471310698 */, 18 }, - /* 6591 */ { MAD_F(0x078ae114) /* 0.471406059 */, 18 }, - - /* 6592 */ { MAD_F(0x078b4514) /* 0.471501425 */, 18 }, - /* 6593 */ { MAD_F(0x078ba915) /* 0.471596796 */, 18 }, - /* 6594 */ { MAD_F(0x078c0d17) /* 0.471692171 */, 18 }, - /* 6595 */ { MAD_F(0x078c711a) /* 0.471787552 */, 18 }, - /* 6596 */ { MAD_F(0x078cd51f) /* 0.471882937 */, 18 }, - /* 6597 */ { MAD_F(0x078d3925) /* 0.471978327 */, 18 }, - /* 6598 */ { MAD_F(0x078d9d2d) /* 0.472073722 */, 18 }, - /* 6599 */ { MAD_F(0x078e0135) /* 0.472169122 */, 18 }, - /* 6600 */ { MAD_F(0x078e653f) /* 0.472264527 */, 18 }, - /* 6601 */ { MAD_F(0x078ec94b) /* 0.472359936 */, 18 }, - /* 6602 */ { MAD_F(0x078f2d57) /* 0.472455350 */, 18 }, - /* 6603 */ { MAD_F(0x078f9165) /* 0.472550769 */, 18 }, - /* 6604 */ { MAD_F(0x078ff574) /* 0.472646193 */, 18 }, - /* 6605 */ { MAD_F(0x07905985) /* 0.472741622 */, 18 }, - /* 6606 */ { MAD_F(0x0790bd96) /* 0.472837055 */, 18 }, - /* 6607 */ { MAD_F(0x079121a9) /* 0.472932493 */, 18 }, - - /* 6608 */ { MAD_F(0x079185be) /* 0.473027937 */, 18 }, - /* 6609 */ { MAD_F(0x0791e9d3) /* 0.473123384 */, 18 }, - /* 6610 */ { MAD_F(0x07924dea) /* 0.473218837 */, 18 }, - /* 6611 */ { MAD_F(0x0792b202) /* 0.473314295 */, 18 }, - /* 6612 */ { MAD_F(0x0793161c) /* 0.473409757 */, 18 }, - /* 6613 */ { MAD_F(0x07937a37) /* 0.473505224 */, 18 }, - /* 6614 */ { MAD_F(0x0793de53) /* 0.473600696 */, 18 }, - /* 6615 */ { MAD_F(0x07944270) /* 0.473696173 */, 18 }, - /* 6616 */ { MAD_F(0x0794a68f) /* 0.473791655 */, 18 }, - /* 6617 */ { MAD_F(0x07950aaf) /* 0.473887141 */, 18 }, - /* 6618 */ { MAD_F(0x07956ed0) /* 0.473982632 */, 18 }, - /* 6619 */ { MAD_F(0x0795d2f2) /* 0.474078128 */, 18 }, - /* 6620 */ { MAD_F(0x07963716) /* 0.474173629 */, 18 }, - /* 6621 */ { MAD_F(0x07969b3b) /* 0.474269135 */, 18 }, - /* 6622 */ { MAD_F(0x0796ff62) /* 0.474364645 */, 18 }, - /* 6623 */ { MAD_F(0x07976389) /* 0.474460161 */, 18 }, - - /* 6624 */ { MAD_F(0x0797c7b2) /* 0.474555681 */, 18 }, - /* 6625 */ { MAD_F(0x07982bdd) /* 0.474651205 */, 18 }, - /* 6626 */ { MAD_F(0x07989008) /* 0.474746735 */, 18 }, - /* 6627 */ { MAD_F(0x0798f435) /* 0.474842270 */, 18 }, - /* 6628 */ { MAD_F(0x07995863) /* 0.474937809 */, 18 }, - /* 6629 */ { MAD_F(0x0799bc92) /* 0.475033353 */, 18 }, - /* 6630 */ { MAD_F(0x079a20c3) /* 0.475128902 */, 18 }, - /* 6631 */ { MAD_F(0x079a84f5) /* 0.475224456 */, 18 }, - /* 6632 */ { MAD_F(0x079ae929) /* 0.475320014 */, 18 }, - /* 6633 */ { MAD_F(0x079b4d5d) /* 0.475415578 */, 18 }, - /* 6634 */ { MAD_F(0x079bb193) /* 0.475511146 */, 18 }, - /* 6635 */ { MAD_F(0x079c15ca) /* 0.475606719 */, 18 }, - /* 6636 */ { MAD_F(0x079c7a03) /* 0.475702296 */, 18 }, - /* 6637 */ { MAD_F(0x079cde3c) /* 0.475797879 */, 18 }, - /* 6638 */ { MAD_F(0x079d4277) /* 0.475893466 */, 18 }, - /* 6639 */ { MAD_F(0x079da6b4) /* 0.475989058 */, 18 }, - - /* 6640 */ { MAD_F(0x079e0af1) /* 0.476084655 */, 18 }, - /* 6641 */ { MAD_F(0x079e6f30) /* 0.476180257 */, 18 }, - /* 6642 */ { MAD_F(0x079ed370) /* 0.476275863 */, 18 }, - /* 6643 */ { MAD_F(0x079f37b2) /* 0.476371475 */, 18 }, - /* 6644 */ { MAD_F(0x079f9bf5) /* 0.476467091 */, 18 }, - /* 6645 */ { MAD_F(0x07a00039) /* 0.476562712 */, 18 }, - /* 6646 */ { MAD_F(0x07a0647e) /* 0.476658338 */, 18 }, - /* 6647 */ { MAD_F(0x07a0c8c5) /* 0.476753968 */, 18 }, - /* 6648 */ { MAD_F(0x07a12d0c) /* 0.476849603 */, 18 }, - /* 6649 */ { MAD_F(0x07a19156) /* 0.476945243 */, 18 }, - /* 6650 */ { MAD_F(0x07a1f5a0) /* 0.477040888 */, 18 }, - /* 6651 */ { MAD_F(0x07a259ec) /* 0.477136538 */, 18 }, - /* 6652 */ { MAD_F(0x07a2be39) /* 0.477232193 */, 18 }, - /* 6653 */ { MAD_F(0x07a32287) /* 0.477327852 */, 18 }, - /* 6654 */ { MAD_F(0x07a386d7) /* 0.477423516 */, 18 }, - /* 6655 */ { MAD_F(0x07a3eb28) /* 0.477519185 */, 18 }, - - /* 6656 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 18 }, - /* 6657 */ { MAD_F(0x07a4b3ce) /* 0.477710537 */, 18 }, - /* 6658 */ { MAD_F(0x07a51822) /* 0.477806220 */, 18 }, - /* 6659 */ { MAD_F(0x07a57c78) /* 0.477901908 */, 18 }, - /* 6660 */ { MAD_F(0x07a5e0d0) /* 0.477997601 */, 18 }, - /* 6661 */ { MAD_F(0x07a64528) /* 0.478093299 */, 18 }, - /* 6662 */ { MAD_F(0x07a6a982) /* 0.478189001 */, 18 }, - /* 6663 */ { MAD_F(0x07a70ddd) /* 0.478284708 */, 18 }, - /* 6664 */ { MAD_F(0x07a7723a) /* 0.478380420 */, 18 }, - /* 6665 */ { MAD_F(0x07a7d698) /* 0.478476137 */, 18 }, - /* 6666 */ { MAD_F(0x07a83af7) /* 0.478571858 */, 18 }, - /* 6667 */ { MAD_F(0x07a89f57) /* 0.478667585 */, 18 }, - /* 6668 */ { MAD_F(0x07a903b9) /* 0.478763316 */, 18 }, - /* 6669 */ { MAD_F(0x07a9681c) /* 0.478859052 */, 18 }, - /* 6670 */ { MAD_F(0x07a9cc80) /* 0.478954793 */, 18 }, - /* 6671 */ { MAD_F(0x07aa30e5) /* 0.479050538 */, 18 }, - - /* 6672 */ { MAD_F(0x07aa954c) /* 0.479146288 */, 18 }, - /* 6673 */ { MAD_F(0x07aaf9b4) /* 0.479242043 */, 18 }, - /* 6674 */ { MAD_F(0x07ab5e1e) /* 0.479337803 */, 18 }, - /* 6675 */ { MAD_F(0x07abc288) /* 0.479433568 */, 18 }, - /* 6676 */ { MAD_F(0x07ac26f4) /* 0.479529337 */, 18 }, - /* 6677 */ { MAD_F(0x07ac8b61) /* 0.479625111 */, 18 }, - /* 6678 */ { MAD_F(0x07acefd0) /* 0.479720890 */, 18 }, - /* 6679 */ { MAD_F(0x07ad543f) /* 0.479816674 */, 18 }, - /* 6680 */ { MAD_F(0x07adb8b0) /* 0.479912463 */, 18 }, - /* 6681 */ { MAD_F(0x07ae1d23) /* 0.480008256 */, 18 }, - /* 6682 */ { MAD_F(0x07ae8196) /* 0.480104054 */, 18 }, - /* 6683 */ { MAD_F(0x07aee60b) /* 0.480199857 */, 18 }, - /* 6684 */ { MAD_F(0x07af4a81) /* 0.480295664 */, 18 }, - /* 6685 */ { MAD_F(0x07afaef9) /* 0.480391477 */, 18 }, - /* 6686 */ { MAD_F(0x07b01372) /* 0.480487294 */, 18 }, - /* 6687 */ { MAD_F(0x07b077ec) /* 0.480583116 */, 18 }, - - /* 6688 */ { MAD_F(0x07b0dc67) /* 0.480678943 */, 18 }, - /* 6689 */ { MAD_F(0x07b140e4) /* 0.480774774 */, 18 }, - /* 6690 */ { MAD_F(0x07b1a561) /* 0.480870611 */, 18 }, - /* 6691 */ { MAD_F(0x07b209e1) /* 0.480966452 */, 18 }, - /* 6692 */ { MAD_F(0x07b26e61) /* 0.481062298 */, 18 }, - /* 6693 */ { MAD_F(0x07b2d2e3) /* 0.481158148 */, 18 }, - /* 6694 */ { MAD_F(0x07b33766) /* 0.481254004 */, 18 }, - /* 6695 */ { MAD_F(0x07b39bea) /* 0.481349864 */, 18 }, - /* 6696 */ { MAD_F(0x07b4006f) /* 0.481445729 */, 18 }, - /* 6697 */ { MAD_F(0x07b464f6) /* 0.481541598 */, 18 }, - /* 6698 */ { MAD_F(0x07b4c97e) /* 0.481637473 */, 18 }, - /* 6699 */ { MAD_F(0x07b52e08) /* 0.481733352 */, 18 }, - /* 6700 */ { MAD_F(0x07b59292) /* 0.481829236 */, 18 }, - /* 6701 */ { MAD_F(0x07b5f71e) /* 0.481925125 */, 18 }, - /* 6702 */ { MAD_F(0x07b65bac) /* 0.482021019 */, 18 }, - /* 6703 */ { MAD_F(0x07b6c03a) /* 0.482116917 */, 18 }, - - /* 6704 */ { MAD_F(0x07b724ca) /* 0.482212820 */, 18 }, - /* 6705 */ { MAD_F(0x07b7895b) /* 0.482308728 */, 18 }, - /* 6706 */ { MAD_F(0x07b7eded) /* 0.482404640 */, 18 }, - /* 6707 */ { MAD_F(0x07b85281) /* 0.482500558 */, 18 }, - /* 6708 */ { MAD_F(0x07b8b716) /* 0.482596480 */, 18 }, - /* 6709 */ { MAD_F(0x07b91bac) /* 0.482692407 */, 18 }, - /* 6710 */ { MAD_F(0x07b98044) /* 0.482788339 */, 18 }, - /* 6711 */ { MAD_F(0x07b9e4dc) /* 0.482884275 */, 18 }, - /* 6712 */ { MAD_F(0x07ba4976) /* 0.482980216 */, 18 }, - /* 6713 */ { MAD_F(0x07baae12) /* 0.483076162 */, 18 }, - /* 6714 */ { MAD_F(0x07bb12ae) /* 0.483172113 */, 18 }, - /* 6715 */ { MAD_F(0x07bb774c) /* 0.483268069 */, 18 }, - /* 6716 */ { MAD_F(0x07bbdbeb) /* 0.483364029 */, 18 }, - /* 6717 */ { MAD_F(0x07bc408c) /* 0.483459994 */, 18 }, - /* 6718 */ { MAD_F(0x07bca52d) /* 0.483555964 */, 18 }, - /* 6719 */ { MAD_F(0x07bd09d0) /* 0.483651939 */, 18 }, - - /* 6720 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 18 }, - /* 6721 */ { MAD_F(0x07bdd31a) /* 0.483843902 */, 18 }, - /* 6722 */ { MAD_F(0x07be37c1) /* 0.483939891 */, 18 }, - /* 6723 */ { MAD_F(0x07be9c69) /* 0.484035885 */, 18 }, - /* 6724 */ { MAD_F(0x07bf0113) /* 0.484131883 */, 18 }, - /* 6725 */ { MAD_F(0x07bf65bd) /* 0.484227886 */, 18 }, - /* 6726 */ { MAD_F(0x07bfca69) /* 0.484323894 */, 18 }, - /* 6727 */ { MAD_F(0x07c02f16) /* 0.484419907 */, 18 }, - /* 6728 */ { MAD_F(0x07c093c5) /* 0.484515924 */, 18 }, - /* 6729 */ { MAD_F(0x07c0f875) /* 0.484611946 */, 18 }, - /* 6730 */ { MAD_F(0x07c15d26) /* 0.484707973 */, 18 }, - /* 6731 */ { MAD_F(0x07c1c1d8) /* 0.484804005 */, 18 }, - /* 6732 */ { MAD_F(0x07c2268b) /* 0.484900041 */, 18 }, - /* 6733 */ { MAD_F(0x07c28b40) /* 0.484996083 */, 18 }, - /* 6734 */ { MAD_F(0x07c2eff6) /* 0.485092128 */, 18 }, - /* 6735 */ { MAD_F(0x07c354ae) /* 0.485188179 */, 18 }, - - /* 6736 */ { MAD_F(0x07c3b967) /* 0.485284235 */, 18 }, - /* 6737 */ { MAD_F(0x07c41e21) /* 0.485380295 */, 18 }, - /* 6738 */ { MAD_F(0x07c482dc) /* 0.485476360 */, 18 }, - /* 6739 */ { MAD_F(0x07c4e798) /* 0.485572430 */, 18 }, - /* 6740 */ { MAD_F(0x07c54c56) /* 0.485668504 */, 18 }, - /* 6741 */ { MAD_F(0x07c5b115) /* 0.485764583 */, 18 }, - /* 6742 */ { MAD_F(0x07c615d6) /* 0.485860667 */, 18 }, - /* 6743 */ { MAD_F(0x07c67a97) /* 0.485956756 */, 18 }, - /* 6744 */ { MAD_F(0x07c6df5a) /* 0.486052849 */, 18 }, - /* 6745 */ { MAD_F(0x07c7441e) /* 0.486148948 */, 18 }, - /* 6746 */ { MAD_F(0x07c7a8e4) /* 0.486245051 */, 18 }, - /* 6747 */ { MAD_F(0x07c80daa) /* 0.486341158 */, 18 }, - /* 6748 */ { MAD_F(0x07c87272) /* 0.486437271 */, 18 }, - /* 6749 */ { MAD_F(0x07c8d73c) /* 0.486533388 */, 18 }, - /* 6750 */ { MAD_F(0x07c93c06) /* 0.486629510 */, 18 }, - /* 6751 */ { MAD_F(0x07c9a0d2) /* 0.486725637 */, 18 }, - - /* 6752 */ { MAD_F(0x07ca059f) /* 0.486821768 */, 18 }, - /* 6753 */ { MAD_F(0x07ca6a6d) /* 0.486917905 */, 18 }, - /* 6754 */ { MAD_F(0x07cacf3d) /* 0.487014045 */, 18 }, - /* 6755 */ { MAD_F(0x07cb340e) /* 0.487110191 */, 18 }, - /* 6756 */ { MAD_F(0x07cb98e0) /* 0.487206342 */, 18 }, - /* 6757 */ { MAD_F(0x07cbfdb4) /* 0.487302497 */, 18 }, - /* 6758 */ { MAD_F(0x07cc6288) /* 0.487398657 */, 18 }, - /* 6759 */ { MAD_F(0x07ccc75e) /* 0.487494821 */, 18 }, - /* 6760 */ { MAD_F(0x07cd2c36) /* 0.487590991 */, 18 }, - /* 6761 */ { MAD_F(0x07cd910e) /* 0.487687165 */, 18 }, - /* 6762 */ { MAD_F(0x07cdf5e8) /* 0.487783344 */, 18 }, - /* 6763 */ { MAD_F(0x07ce5ac3) /* 0.487879528 */, 18 }, - /* 6764 */ { MAD_F(0x07cebfa0) /* 0.487975716 */, 18 }, - /* 6765 */ { MAD_F(0x07cf247d) /* 0.488071909 */, 18 }, - /* 6766 */ { MAD_F(0x07cf895c) /* 0.488168107 */, 18 }, - /* 6767 */ { MAD_F(0x07cfee3c) /* 0.488264310 */, 18 }, - - /* 6768 */ { MAD_F(0x07d0531e) /* 0.488360517 */, 18 }, - /* 6769 */ { MAD_F(0x07d0b801) /* 0.488456729 */, 18 }, - /* 6770 */ { MAD_F(0x07d11ce5) /* 0.488552946 */, 18 }, - /* 6771 */ { MAD_F(0x07d181ca) /* 0.488649167 */, 18 }, - /* 6772 */ { MAD_F(0x07d1e6b0) /* 0.488745394 */, 18 }, - /* 6773 */ { MAD_F(0x07d24b98) /* 0.488841625 */, 18 }, - /* 6774 */ { MAD_F(0x07d2b081) /* 0.488937860 */, 18 }, - /* 6775 */ { MAD_F(0x07d3156c) /* 0.489034101 */, 18 }, - /* 6776 */ { MAD_F(0x07d37a57) /* 0.489130346 */, 18 }, - /* 6777 */ { MAD_F(0x07d3df44) /* 0.489226596 */, 18 }, - /* 6778 */ { MAD_F(0x07d44432) /* 0.489322851 */, 18 }, - /* 6779 */ { MAD_F(0x07d4a922) /* 0.489419110 */, 18 }, - /* 6780 */ { MAD_F(0x07d50e13) /* 0.489515375 */, 18 }, - /* 6781 */ { MAD_F(0x07d57305) /* 0.489611643 */, 18 }, - /* 6782 */ { MAD_F(0x07d5d7f8) /* 0.489707917 */, 18 }, - /* 6783 */ { MAD_F(0x07d63cec) /* 0.489804195 */, 18 }, - - /* 6784 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 18 }, - /* 6785 */ { MAD_F(0x07d706d9) /* 0.489996766 */, 18 }, - /* 6786 */ { MAD_F(0x07d76bd2) /* 0.490093059 */, 18 }, - /* 6787 */ { MAD_F(0x07d7d0cb) /* 0.490189356 */, 18 }, - /* 6788 */ { MAD_F(0x07d835c6) /* 0.490285658 */, 18 }, - /* 6789 */ { MAD_F(0x07d89ac2) /* 0.490381965 */, 18 }, - /* 6790 */ { MAD_F(0x07d8ffc0) /* 0.490478277 */, 18 }, - /* 6791 */ { MAD_F(0x07d964be) /* 0.490574593 */, 18 }, - /* 6792 */ { MAD_F(0x07d9c9be) /* 0.490670914 */, 18 }, - /* 6793 */ { MAD_F(0x07da2ebf) /* 0.490767239 */, 18 }, - /* 6794 */ { MAD_F(0x07da93c2) /* 0.490863570 */, 18 }, - /* 6795 */ { MAD_F(0x07daf8c6) /* 0.490959905 */, 18 }, - /* 6796 */ { MAD_F(0x07db5dcb) /* 0.491056245 */, 18 }, - /* 6797 */ { MAD_F(0x07dbc2d1) /* 0.491152589 */, 18 }, - /* 6798 */ { MAD_F(0x07dc27d9) /* 0.491248939 */, 18 }, - /* 6799 */ { MAD_F(0x07dc8ce1) /* 0.491345293 */, 18 }, - - /* 6800 */ { MAD_F(0x07dcf1ec) /* 0.491441651 */, 18 }, - /* 6801 */ { MAD_F(0x07dd56f7) /* 0.491538015 */, 18 }, - /* 6802 */ { MAD_F(0x07ddbc04) /* 0.491634383 */, 18 }, - /* 6803 */ { MAD_F(0x07de2111) /* 0.491730756 */, 18 }, - /* 6804 */ { MAD_F(0x07de8621) /* 0.491827134 */, 18 }, - /* 6805 */ { MAD_F(0x07deeb31) /* 0.491923516 */, 18 }, - /* 6806 */ { MAD_F(0x07df5043) /* 0.492019903 */, 18 }, - /* 6807 */ { MAD_F(0x07dfb556) /* 0.492116295 */, 18 }, - /* 6808 */ { MAD_F(0x07e01a6a) /* 0.492212691 */, 18 }, - /* 6809 */ { MAD_F(0x07e07f80) /* 0.492309093 */, 18 }, - /* 6810 */ { MAD_F(0x07e0e496) /* 0.492405499 */, 18 }, - /* 6811 */ { MAD_F(0x07e149ae) /* 0.492501909 */, 18 }, - /* 6812 */ { MAD_F(0x07e1aec8) /* 0.492598325 */, 18 }, - /* 6813 */ { MAD_F(0x07e213e2) /* 0.492694745 */, 18 }, - /* 6814 */ { MAD_F(0x07e278fe) /* 0.492791170 */, 18 }, - /* 6815 */ { MAD_F(0x07e2de1b) /* 0.492887599 */, 18 }, - - /* 6816 */ { MAD_F(0x07e3433a) /* 0.492984033 */, 18 }, - /* 6817 */ { MAD_F(0x07e3a859) /* 0.493080472 */, 18 }, - /* 6818 */ { MAD_F(0x07e40d7a) /* 0.493176916 */, 18 }, - /* 6819 */ { MAD_F(0x07e4729c) /* 0.493273365 */, 18 }, - /* 6820 */ { MAD_F(0x07e4d7c0) /* 0.493369818 */, 18 }, - /* 6821 */ { MAD_F(0x07e53ce4) /* 0.493466275 */, 18 }, - /* 6822 */ { MAD_F(0x07e5a20a) /* 0.493562738 */, 18 }, - /* 6823 */ { MAD_F(0x07e60732) /* 0.493659205 */, 18 }, - /* 6824 */ { MAD_F(0x07e66c5a) /* 0.493755677 */, 18 }, - /* 6825 */ { MAD_F(0x07e6d184) /* 0.493852154 */, 18 }, - /* 6826 */ { MAD_F(0x07e736af) /* 0.493948635 */, 18 }, - /* 6827 */ { MAD_F(0x07e79bdb) /* 0.494045122 */, 18 }, - /* 6828 */ { MAD_F(0x07e80109) /* 0.494141612 */, 18 }, - /* 6829 */ { MAD_F(0x07e86638) /* 0.494238108 */, 18 }, - /* 6830 */ { MAD_F(0x07e8cb68) /* 0.494334608 */, 18 }, - /* 6831 */ { MAD_F(0x07e93099) /* 0.494431113 */, 18 }, - - /* 6832 */ { MAD_F(0x07e995cc) /* 0.494527623 */, 18 }, - /* 6833 */ { MAD_F(0x07e9fb00) /* 0.494624137 */, 18 }, - /* 6834 */ { MAD_F(0x07ea6035) /* 0.494720656 */, 18 }, - /* 6835 */ { MAD_F(0x07eac56b) /* 0.494817180 */, 18 }, - /* 6836 */ { MAD_F(0x07eb2aa3) /* 0.494913709 */, 18 }, - /* 6837 */ { MAD_F(0x07eb8fdc) /* 0.495010242 */, 18 }, - /* 6838 */ { MAD_F(0x07ebf516) /* 0.495106780 */, 18 }, - /* 6839 */ { MAD_F(0x07ec5a51) /* 0.495203322 */, 18 }, - /* 6840 */ { MAD_F(0x07ecbf8e) /* 0.495299870 */, 18 }, - /* 6841 */ { MAD_F(0x07ed24cc) /* 0.495396422 */, 18 }, - /* 6842 */ { MAD_F(0x07ed8a0b) /* 0.495492978 */, 18 }, - /* 6843 */ { MAD_F(0x07edef4c) /* 0.495589540 */, 18 }, - /* 6844 */ { MAD_F(0x07ee548e) /* 0.495686106 */, 18 }, - /* 6845 */ { MAD_F(0x07eeb9d1) /* 0.495782677 */, 18 }, - /* 6846 */ { MAD_F(0x07ef1f15) /* 0.495879252 */, 18 }, - /* 6847 */ { MAD_F(0x07ef845b) /* 0.495975833 */, 18 }, - - /* 6848 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 18 }, - /* 6849 */ { MAD_F(0x07f04ee9) /* 0.496169007 */, 18 }, - /* 6850 */ { MAD_F(0x07f0b433) /* 0.496265602 */, 18 }, - /* 6851 */ { MAD_F(0x07f1197d) /* 0.496362201 */, 18 }, - /* 6852 */ { MAD_F(0x07f17ec9) /* 0.496458804 */, 18 }, - /* 6853 */ { MAD_F(0x07f1e416) /* 0.496555413 */, 18 }, - /* 6854 */ { MAD_F(0x07f24965) /* 0.496652026 */, 18 }, - /* 6855 */ { MAD_F(0x07f2aeb5) /* 0.496748644 */, 18 }, - /* 6856 */ { MAD_F(0x07f31405) /* 0.496845266 */, 18 }, - /* 6857 */ { MAD_F(0x07f37958) /* 0.496941894 */, 18 }, - /* 6858 */ { MAD_F(0x07f3deab) /* 0.497038526 */, 18 }, - /* 6859 */ { MAD_F(0x07f44400) /* 0.497135162 */, 18 }, - /* 6860 */ { MAD_F(0x07f4a956) /* 0.497231804 */, 18 }, - /* 6861 */ { MAD_F(0x07f50ead) /* 0.497328450 */, 18 }, - /* 6862 */ { MAD_F(0x07f57405) /* 0.497425100 */, 18 }, - /* 6863 */ { MAD_F(0x07f5d95f) /* 0.497521756 */, 18 }, - - /* 6864 */ { MAD_F(0x07f63eba) /* 0.497618416 */, 18 }, - /* 6865 */ { MAD_F(0x07f6a416) /* 0.497715081 */, 18 }, - /* 6866 */ { MAD_F(0x07f70974) /* 0.497811750 */, 18 }, - /* 6867 */ { MAD_F(0x07f76ed3) /* 0.497908425 */, 18 }, - /* 6868 */ { MAD_F(0x07f7d433) /* 0.498005103 */, 18 }, - /* 6869 */ { MAD_F(0x07f83994) /* 0.498101787 */, 18 }, - /* 6870 */ { MAD_F(0x07f89ef7) /* 0.498198475 */, 18 }, - /* 6871 */ { MAD_F(0x07f9045a) /* 0.498295168 */, 18 }, - /* 6872 */ { MAD_F(0x07f969c0) /* 0.498391866 */, 18 }, - /* 6873 */ { MAD_F(0x07f9cf26) /* 0.498488568 */, 18 }, - /* 6874 */ { MAD_F(0x07fa348e) /* 0.498585275 */, 18 }, - /* 6875 */ { MAD_F(0x07fa99f6) /* 0.498681987 */, 18 }, - /* 6876 */ { MAD_F(0x07faff60) /* 0.498778704 */, 18 }, - /* 6877 */ { MAD_F(0x07fb64cc) /* 0.498875425 */, 18 }, - /* 6878 */ { MAD_F(0x07fbca38) /* 0.498972150 */, 18 }, - /* 6879 */ { MAD_F(0x07fc2fa6) /* 0.499068881 */, 18 }, - - /* 6880 */ { MAD_F(0x07fc9516) /* 0.499165616 */, 18 }, - /* 6881 */ { MAD_F(0x07fcfa86) /* 0.499262356 */, 18 }, - /* 6882 */ { MAD_F(0x07fd5ff8) /* 0.499359101 */, 18 }, - /* 6883 */ { MAD_F(0x07fdc56b) /* 0.499455850 */, 18 }, - /* 6884 */ { MAD_F(0x07fe2adf) /* 0.499552604 */, 18 }, - /* 6885 */ { MAD_F(0x07fe9054) /* 0.499649362 */, 18 }, - /* 6886 */ { MAD_F(0x07fef5cb) /* 0.499746126 */, 18 }, - /* 6887 */ { MAD_F(0x07ff5b43) /* 0.499842894 */, 18 }, - /* 6888 */ { MAD_F(0x07ffc0bc) /* 0.499939666 */, 18 }, - /* 6889 */ { MAD_F(0x0400131b) /* 0.250018222 */, 19 }, - /* 6890 */ { MAD_F(0x040045d9) /* 0.250066613 */, 19 }, - /* 6891 */ { MAD_F(0x04007897) /* 0.250115006 */, 19 }, - /* 6892 */ { MAD_F(0x0400ab57) /* 0.250163402 */, 19 }, - /* 6893 */ { MAD_F(0x0400de16) /* 0.250211800 */, 19 }, - /* 6894 */ { MAD_F(0x040110d7) /* 0.250260200 */, 19 }, - /* 6895 */ { MAD_F(0x04014398) /* 0.250308603 */, 19 }, - - /* 6896 */ { MAD_F(0x04017659) /* 0.250357008 */, 19 }, - /* 6897 */ { MAD_F(0x0401a91c) /* 0.250405415 */, 19 }, - /* 6898 */ { MAD_F(0x0401dbdf) /* 0.250453825 */, 19 }, - /* 6899 */ { MAD_F(0x04020ea2) /* 0.250502237 */, 19 }, - /* 6900 */ { MAD_F(0x04024166) /* 0.250550652 */, 19 }, - /* 6901 */ { MAD_F(0x0402742b) /* 0.250599068 */, 19 }, - /* 6902 */ { MAD_F(0x0402a6f0) /* 0.250647488 */, 19 }, - /* 6903 */ { MAD_F(0x0402d9b6) /* 0.250695909 */, 19 }, - /* 6904 */ { MAD_F(0x04030c7d) /* 0.250744333 */, 19 }, - /* 6905 */ { MAD_F(0x04033f44) /* 0.250792759 */, 19 }, - /* 6906 */ { MAD_F(0x0403720c) /* 0.250841187 */, 19 }, - /* 6907 */ { MAD_F(0x0403a4d5) /* 0.250889618 */, 19 }, - /* 6908 */ { MAD_F(0x0403d79e) /* 0.250938051 */, 19 }, - /* 6909 */ { MAD_F(0x04040a68) /* 0.250986487 */, 19 }, - /* 6910 */ { MAD_F(0x04043d32) /* 0.251034924 */, 19 }, - /* 6911 */ { MAD_F(0x04046ffd) /* 0.251083365 */, 19 }, - - /* 6912 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 19 }, - /* 6913 */ { MAD_F(0x0404d595) /* 0.251180252 */, 19 }, - /* 6914 */ { MAD_F(0x04050862) /* 0.251228699 */, 19 }, - /* 6915 */ { MAD_F(0x04053b30) /* 0.251277148 */, 19 }, - /* 6916 */ { MAD_F(0x04056dfe) /* 0.251325600 */, 19 }, - /* 6917 */ { MAD_F(0x0405a0cd) /* 0.251374054 */, 19 }, - /* 6918 */ { MAD_F(0x0405d39c) /* 0.251422511 */, 19 }, - /* 6919 */ { MAD_F(0x0406066c) /* 0.251470970 */, 19 }, - /* 6920 */ { MAD_F(0x0406393d) /* 0.251519431 */, 19 }, - /* 6921 */ { MAD_F(0x04066c0e) /* 0.251567894 */, 19 }, - /* 6922 */ { MAD_F(0x04069ee0) /* 0.251616360 */, 19 }, - /* 6923 */ { MAD_F(0x0406d1b3) /* 0.251664828 */, 19 }, - /* 6924 */ { MAD_F(0x04070486) /* 0.251713299 */, 19 }, - /* 6925 */ { MAD_F(0x0407375a) /* 0.251761772 */, 19 }, - /* 6926 */ { MAD_F(0x04076a2e) /* 0.251810247 */, 19 }, - /* 6927 */ { MAD_F(0x04079d03) /* 0.251858724 */, 19 }, - - /* 6928 */ { MAD_F(0x0407cfd9) /* 0.251907204 */, 19 }, - /* 6929 */ { MAD_F(0x040802af) /* 0.251955686 */, 19 }, - /* 6930 */ { MAD_F(0x04083586) /* 0.252004171 */, 19 }, - /* 6931 */ { MAD_F(0x0408685e) /* 0.252052658 */, 19 }, - /* 6932 */ { MAD_F(0x04089b36) /* 0.252101147 */, 19 }, - /* 6933 */ { MAD_F(0x0408ce0f) /* 0.252149638 */, 19 }, - /* 6934 */ { MAD_F(0x040900e8) /* 0.252198132 */, 19 }, - /* 6935 */ { MAD_F(0x040933c2) /* 0.252246628 */, 19 }, - /* 6936 */ { MAD_F(0x0409669d) /* 0.252295127 */, 19 }, - /* 6937 */ { MAD_F(0x04099978) /* 0.252343627 */, 19 }, - /* 6938 */ { MAD_F(0x0409cc54) /* 0.252392131 */, 19 }, - /* 6939 */ { MAD_F(0x0409ff31) /* 0.252440636 */, 19 }, - /* 6940 */ { MAD_F(0x040a320e) /* 0.252489144 */, 19 }, - /* 6941 */ { MAD_F(0x040a64ec) /* 0.252537654 */, 19 }, - /* 6942 */ { MAD_F(0x040a97cb) /* 0.252586166 */, 19 }, - /* 6943 */ { MAD_F(0x040acaaa) /* 0.252634681 */, 19 }, - - /* 6944 */ { MAD_F(0x040afd89) /* 0.252683198 */, 19 }, - /* 6945 */ { MAD_F(0x040b306a) /* 0.252731718 */, 19 }, - /* 6946 */ { MAD_F(0x040b634b) /* 0.252780240 */, 19 }, - /* 6947 */ { MAD_F(0x040b962c) /* 0.252828764 */, 19 }, - /* 6948 */ { MAD_F(0x040bc90e) /* 0.252877290 */, 19 }, - /* 6949 */ { MAD_F(0x040bfbf1) /* 0.252925819 */, 19 }, - /* 6950 */ { MAD_F(0x040c2ed5) /* 0.252974350 */, 19 }, - /* 6951 */ { MAD_F(0x040c61b9) /* 0.253022883 */, 19 }, - /* 6952 */ { MAD_F(0x040c949e) /* 0.253071419 */, 19 }, - /* 6953 */ { MAD_F(0x040cc783) /* 0.253119957 */, 19 }, - /* 6954 */ { MAD_F(0x040cfa69) /* 0.253168498 */, 19 }, - /* 6955 */ { MAD_F(0x040d2d4f) /* 0.253217040 */, 19 }, - /* 6956 */ { MAD_F(0x040d6037) /* 0.253265585 */, 19 }, - /* 6957 */ { MAD_F(0x040d931e) /* 0.253314133 */, 19 }, - /* 6958 */ { MAD_F(0x040dc607) /* 0.253362682 */, 19 }, - /* 6959 */ { MAD_F(0x040df8f0) /* 0.253411234 */, 19 }, - - /* 6960 */ { MAD_F(0x040e2bda) /* 0.253459789 */, 19 }, - /* 6961 */ { MAD_F(0x040e5ec4) /* 0.253508345 */, 19 }, - /* 6962 */ { MAD_F(0x040e91af) /* 0.253556904 */, 19 }, - /* 6963 */ { MAD_F(0x040ec49b) /* 0.253605466 */, 19 }, - /* 6964 */ { MAD_F(0x040ef787) /* 0.253654029 */, 19 }, - /* 6965 */ { MAD_F(0x040f2a74) /* 0.253702595 */, 19 }, - /* 6966 */ { MAD_F(0x040f5d61) /* 0.253751164 */, 19 }, - /* 6967 */ { MAD_F(0x040f904f) /* 0.253799734 */, 19 }, - /* 6968 */ { MAD_F(0x040fc33e) /* 0.253848307 */, 19 }, - /* 6969 */ { MAD_F(0x040ff62d) /* 0.253896883 */, 19 }, - /* 6970 */ { MAD_F(0x0410291d) /* 0.253945460 */, 19 }, - /* 6971 */ { MAD_F(0x04105c0e) /* 0.253994040 */, 19 }, - /* 6972 */ { MAD_F(0x04108eff) /* 0.254042622 */, 19 }, - /* 6973 */ { MAD_F(0x0410c1f1) /* 0.254091207 */, 19 }, - /* 6974 */ { MAD_F(0x0410f4e3) /* 0.254139794 */, 19 }, - /* 6975 */ { MAD_F(0x041127d6) /* 0.254188383 */, 19 }, - - /* 6976 */ { MAD_F(0x04115aca) /* 0.254236974 */, 19 }, - /* 6977 */ { MAD_F(0x04118dbe) /* 0.254285568 */, 19 }, - /* 6978 */ { MAD_F(0x0411c0b3) /* 0.254334165 */, 19 }, - /* 6979 */ { MAD_F(0x0411f3a9) /* 0.254382763 */, 19 }, - /* 6980 */ { MAD_F(0x0412269f) /* 0.254431364 */, 19 }, - /* 6981 */ { MAD_F(0x04125996) /* 0.254479967 */, 19 }, - /* 6982 */ { MAD_F(0x04128c8d) /* 0.254528572 */, 19 }, - /* 6983 */ { MAD_F(0x0412bf85) /* 0.254577180 */, 19 }, - /* 6984 */ { MAD_F(0x0412f27e) /* 0.254625790 */, 19 }, - /* 6985 */ { MAD_F(0x04132577) /* 0.254674403 */, 19 }, - /* 6986 */ { MAD_F(0x04135871) /* 0.254723017 */, 19 }, - /* 6987 */ { MAD_F(0x04138b6c) /* 0.254771635 */, 19 }, - /* 6988 */ { MAD_F(0x0413be67) /* 0.254820254 */, 19 }, - /* 6989 */ { MAD_F(0x0413f163) /* 0.254868876 */, 19 }, - /* 6990 */ { MAD_F(0x0414245f) /* 0.254917500 */, 19 }, - /* 6991 */ { MAD_F(0x0414575c) /* 0.254966126 */, 19 }, - - /* 6992 */ { MAD_F(0x04148a5a) /* 0.255014755 */, 19 }, - /* 6993 */ { MAD_F(0x0414bd58) /* 0.255063386 */, 19 }, - /* 6994 */ { MAD_F(0x0414f057) /* 0.255112019 */, 19 }, - /* 6995 */ { MAD_F(0x04152356) /* 0.255160655 */, 19 }, - /* 6996 */ { MAD_F(0x04155657) /* 0.255209292 */, 19 }, - /* 6997 */ { MAD_F(0x04158957) /* 0.255257933 */, 19 }, - /* 6998 */ { MAD_F(0x0415bc59) /* 0.255306575 */, 19 }, - /* 6999 */ { MAD_F(0x0415ef5b) /* 0.255355220 */, 19 }, - /* 7000 */ { MAD_F(0x0416225d) /* 0.255403867 */, 19 }, - /* 7001 */ { MAD_F(0x04165561) /* 0.255452517 */, 19 }, - /* 7002 */ { MAD_F(0x04168864) /* 0.255501169 */, 19 }, - /* 7003 */ { MAD_F(0x0416bb69) /* 0.255549823 */, 19 }, - /* 7004 */ { MAD_F(0x0416ee6e) /* 0.255598479 */, 19 }, - /* 7005 */ { MAD_F(0x04172174) /* 0.255647138 */, 19 }, - /* 7006 */ { MAD_F(0x0417547a) /* 0.255695799 */, 19 }, - /* 7007 */ { MAD_F(0x04178781) /* 0.255744463 */, 19 }, - - /* 7008 */ { MAD_F(0x0417ba89) /* 0.255793128 */, 19 }, - /* 7009 */ { MAD_F(0x0417ed91) /* 0.255841796 */, 19 }, - /* 7010 */ { MAD_F(0x0418209a) /* 0.255890467 */, 19 }, - /* 7011 */ { MAD_F(0x041853a3) /* 0.255939139 */, 19 }, - /* 7012 */ { MAD_F(0x041886ad) /* 0.255987814 */, 19 }, - /* 7013 */ { MAD_F(0x0418b9b8) /* 0.256036492 */, 19 }, - /* 7014 */ { MAD_F(0x0418ecc3) /* 0.256085171 */, 19 }, - /* 7015 */ { MAD_F(0x04191fcf) /* 0.256133853 */, 19 }, - /* 7016 */ { MAD_F(0x041952dc) /* 0.256182537 */, 19 }, - /* 7017 */ { MAD_F(0x041985e9) /* 0.256231224 */, 19 }, - /* 7018 */ { MAD_F(0x0419b8f7) /* 0.256279913 */, 19 }, - /* 7019 */ { MAD_F(0x0419ec05) /* 0.256328604 */, 19 }, - /* 7020 */ { MAD_F(0x041a1f15) /* 0.256377297 */, 19 }, - /* 7021 */ { MAD_F(0x041a5224) /* 0.256425993 */, 19 }, - /* 7022 */ { MAD_F(0x041a8534) /* 0.256474691 */, 19 }, - /* 7023 */ { MAD_F(0x041ab845) /* 0.256523392 */, 19 }, - - /* 7024 */ { MAD_F(0x041aeb57) /* 0.256572095 */, 19 }, - /* 7025 */ { MAD_F(0x041b1e69) /* 0.256620800 */, 19 }, - /* 7026 */ { MAD_F(0x041b517c) /* 0.256669507 */, 19 }, - /* 7027 */ { MAD_F(0x041b848f) /* 0.256718217 */, 19 }, - /* 7028 */ { MAD_F(0x041bb7a3) /* 0.256766929 */, 19 }, - /* 7029 */ { MAD_F(0x041beab8) /* 0.256815643 */, 19 }, - /* 7030 */ { MAD_F(0x041c1dcd) /* 0.256864359 */, 19 }, - /* 7031 */ { MAD_F(0x041c50e3) /* 0.256913078 */, 19 }, - /* 7032 */ { MAD_F(0x041c83fa) /* 0.256961800 */, 19 }, - /* 7033 */ { MAD_F(0x041cb711) /* 0.257010523 */, 19 }, - /* 7034 */ { MAD_F(0x041cea28) /* 0.257059249 */, 19 }, - /* 7035 */ { MAD_F(0x041d1d41) /* 0.257107977 */, 19 }, - /* 7036 */ { MAD_F(0x041d505a) /* 0.257156708 */, 19 }, - /* 7037 */ { MAD_F(0x041d8373) /* 0.257205440 */, 19 }, - /* 7038 */ { MAD_F(0x041db68e) /* 0.257254175 */, 19 }, - /* 7039 */ { MAD_F(0x041de9a8) /* 0.257302913 */, 19 }, - - /* 7040 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 19 }, - /* 7041 */ { MAD_F(0x041e4fe0) /* 0.257400394 */, 19 }, - /* 7042 */ { MAD_F(0x041e82fd) /* 0.257449139 */, 19 }, - /* 7043 */ { MAD_F(0x041eb61a) /* 0.257497885 */, 19 }, - /* 7044 */ { MAD_F(0x041ee938) /* 0.257546634 */, 19 }, - /* 7045 */ { MAD_F(0x041f1c57) /* 0.257595386 */, 19 }, - /* 7046 */ { MAD_F(0x041f4f76) /* 0.257644139 */, 19 }, - /* 7047 */ { MAD_F(0x041f8296) /* 0.257692895 */, 19 }, - /* 7048 */ { MAD_F(0x041fb5b6) /* 0.257741653 */, 19 }, - /* 7049 */ { MAD_F(0x041fe8d7) /* 0.257790414 */, 19 }, - /* 7050 */ { MAD_F(0x04201bf9) /* 0.257839176 */, 19 }, - /* 7051 */ { MAD_F(0x04204f1b) /* 0.257887941 */, 19 }, - /* 7052 */ { MAD_F(0x0420823e) /* 0.257936709 */, 19 }, - /* 7053 */ { MAD_F(0x0420b561) /* 0.257985478 */, 19 }, - /* 7054 */ { MAD_F(0x0420e885) /* 0.258034250 */, 19 }, - /* 7055 */ { MAD_F(0x04211baa) /* 0.258083025 */, 19 }, - - /* 7056 */ { MAD_F(0x04214ed0) /* 0.258131801 */, 19 }, - /* 7057 */ { MAD_F(0x042181f6) /* 0.258180580 */, 19 }, - /* 7058 */ { MAD_F(0x0421b51c) /* 0.258229361 */, 19 }, - /* 7059 */ { MAD_F(0x0421e843) /* 0.258278145 */, 19 }, - /* 7060 */ { MAD_F(0x04221b6b) /* 0.258326931 */, 19 }, - /* 7061 */ { MAD_F(0x04224e94) /* 0.258375719 */, 19 }, - /* 7062 */ { MAD_F(0x042281bd) /* 0.258424509 */, 19 }, - /* 7063 */ { MAD_F(0x0422b4e6) /* 0.258473302 */, 19 }, - /* 7064 */ { MAD_F(0x0422e811) /* 0.258522097 */, 19 }, - /* 7065 */ { MAD_F(0x04231b3c) /* 0.258570894 */, 19 }, - /* 7066 */ { MAD_F(0x04234e67) /* 0.258619694 */, 19 }, - /* 7067 */ { MAD_F(0x04238193) /* 0.258668496 */, 19 }, - /* 7068 */ { MAD_F(0x0423b4c0) /* 0.258717300 */, 19 }, - /* 7069 */ { MAD_F(0x0423e7ee) /* 0.258766106 */, 19 }, - /* 7070 */ { MAD_F(0x04241b1c) /* 0.258814915 */, 19 }, - /* 7071 */ { MAD_F(0x04244e4a) /* 0.258863726 */, 19 }, - - /* 7072 */ { MAD_F(0x04248179) /* 0.258912540 */, 19 }, - /* 7073 */ { MAD_F(0x0424b4a9) /* 0.258961356 */, 19 }, - /* 7074 */ { MAD_F(0x0424e7da) /* 0.259010174 */, 19 }, - /* 7075 */ { MAD_F(0x04251b0b) /* 0.259058994 */, 19 }, - /* 7076 */ { MAD_F(0x04254e3d) /* 0.259107817 */, 19 }, - /* 7077 */ { MAD_F(0x0425816f) /* 0.259156642 */, 19 }, - /* 7078 */ { MAD_F(0x0425b4a2) /* 0.259205469 */, 19 }, - /* 7079 */ { MAD_F(0x0425e7d6) /* 0.259254298 */, 19 }, - /* 7080 */ { MAD_F(0x04261b0a) /* 0.259303130 */, 19 }, - /* 7081 */ { MAD_F(0x04264e3f) /* 0.259351964 */, 19 }, - /* 7082 */ { MAD_F(0x04268174) /* 0.259400801 */, 19 }, - /* 7083 */ { MAD_F(0x0426b4aa) /* 0.259449639 */, 19 }, - /* 7084 */ { MAD_F(0x0426e7e1) /* 0.259498480 */, 19 }, - /* 7085 */ { MAD_F(0x04271b18) /* 0.259547324 */, 19 }, - /* 7086 */ { MAD_F(0x04274e50) /* 0.259596169 */, 19 }, - /* 7087 */ { MAD_F(0x04278188) /* 0.259645017 */, 19 }, - - /* 7088 */ { MAD_F(0x0427b4c2) /* 0.259693868 */, 19 }, - /* 7089 */ { MAD_F(0x0427e7fb) /* 0.259742720 */, 19 }, - /* 7090 */ { MAD_F(0x04281b36) /* 0.259791575 */, 19 }, - /* 7091 */ { MAD_F(0x04284e71) /* 0.259840432 */, 19 }, - /* 7092 */ { MAD_F(0x042881ac) /* 0.259889291 */, 19 }, - /* 7093 */ { MAD_F(0x0428b4e8) /* 0.259938153 */, 19 }, - /* 7094 */ { MAD_F(0x0428e825) /* 0.259987017 */, 19 }, - /* 7095 */ { MAD_F(0x04291b63) /* 0.260035883 */, 19 }, - /* 7096 */ { MAD_F(0x04294ea1) /* 0.260084752 */, 19 }, - /* 7097 */ { MAD_F(0x042981df) /* 0.260133623 */, 19 }, - /* 7098 */ { MAD_F(0x0429b51f) /* 0.260182496 */, 19 }, - /* 7099 */ { MAD_F(0x0429e85f) /* 0.260231372 */, 19 }, - /* 7100 */ { MAD_F(0x042a1b9f) /* 0.260280249 */, 19 }, - /* 7101 */ { MAD_F(0x042a4ee0) /* 0.260329129 */, 19 }, - /* 7102 */ { MAD_F(0x042a8222) /* 0.260378012 */, 19 }, - /* 7103 */ { MAD_F(0x042ab564) /* 0.260426896 */, 19 }, - - /* 7104 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 19 }, - /* 7105 */ { MAD_F(0x042b1beb) /* 0.260524673 */, 19 }, - /* 7106 */ { MAD_F(0x042b4f2f) /* 0.260573564 */, 19 }, - /* 7107 */ { MAD_F(0x042b8274) /* 0.260622458 */, 19 }, - /* 7108 */ { MAD_F(0x042bb5ba) /* 0.260671354 */, 19 }, - /* 7109 */ { MAD_F(0x042be900) /* 0.260720252 */, 19 }, - /* 7110 */ { MAD_F(0x042c1c46) /* 0.260769153 */, 19 }, - /* 7111 */ { MAD_F(0x042c4f8e) /* 0.260818056 */, 19 }, - /* 7112 */ { MAD_F(0x042c82d6) /* 0.260866961 */, 19 }, - /* 7113 */ { MAD_F(0x042cb61e) /* 0.260915869 */, 19 }, - /* 7114 */ { MAD_F(0x042ce967) /* 0.260964779 */, 19 }, - /* 7115 */ { MAD_F(0x042d1cb1) /* 0.261013691 */, 19 }, - /* 7116 */ { MAD_F(0x042d4ffb) /* 0.261062606 */, 19 }, - /* 7117 */ { MAD_F(0x042d8346) /* 0.261111522 */, 19 }, - /* 7118 */ { MAD_F(0x042db692) /* 0.261160441 */, 19 }, - /* 7119 */ { MAD_F(0x042de9de) /* 0.261209363 */, 19 }, - - /* 7120 */ { MAD_F(0x042e1d2b) /* 0.261258286 */, 19 }, - /* 7121 */ { MAD_F(0x042e5078) /* 0.261307212 */, 19 }, - /* 7122 */ { MAD_F(0x042e83c6) /* 0.261356140 */, 19 }, - /* 7123 */ { MAD_F(0x042eb715) /* 0.261405071 */, 19 }, - /* 7124 */ { MAD_F(0x042eea64) /* 0.261454004 */, 19 }, - /* 7125 */ { MAD_F(0x042f1db4) /* 0.261502939 */, 19 }, - /* 7126 */ { MAD_F(0x042f5105) /* 0.261551876 */, 19 }, - /* 7127 */ { MAD_F(0x042f8456) /* 0.261600816 */, 19 }, - /* 7128 */ { MAD_F(0x042fb7a8) /* 0.261649758 */, 19 }, - /* 7129 */ { MAD_F(0x042feafa) /* 0.261698702 */, 19 }, - /* 7130 */ { MAD_F(0x04301e4d) /* 0.261747649 */, 19 }, - /* 7131 */ { MAD_F(0x043051a1) /* 0.261796597 */, 19 }, - /* 7132 */ { MAD_F(0x043084f5) /* 0.261845548 */, 19 }, - /* 7133 */ { MAD_F(0x0430b84a) /* 0.261894502 */, 19 }, - /* 7134 */ { MAD_F(0x0430eb9f) /* 0.261943458 */, 19 }, - /* 7135 */ { MAD_F(0x04311ef5) /* 0.261992416 */, 19 }, - - /* 7136 */ { MAD_F(0x0431524c) /* 0.262041376 */, 19 }, - /* 7137 */ { MAD_F(0x043185a3) /* 0.262090338 */, 19 }, - /* 7138 */ { MAD_F(0x0431b8fb) /* 0.262139303 */, 19 }, - /* 7139 */ { MAD_F(0x0431ec54) /* 0.262188270 */, 19 }, - /* 7140 */ { MAD_F(0x04321fad) /* 0.262237240 */, 19 }, - /* 7141 */ { MAD_F(0x04325306) /* 0.262286211 */, 19 }, - /* 7142 */ { MAD_F(0x04328661) /* 0.262335185 */, 19 }, - /* 7143 */ { MAD_F(0x0432b9bc) /* 0.262384162 */, 19 }, - /* 7144 */ { MAD_F(0x0432ed17) /* 0.262433140 */, 19 }, - /* 7145 */ { MAD_F(0x04332074) /* 0.262482121 */, 19 }, - /* 7146 */ { MAD_F(0x043353d0) /* 0.262531104 */, 19 }, - /* 7147 */ { MAD_F(0x0433872e) /* 0.262580089 */, 19 }, - /* 7148 */ { MAD_F(0x0433ba8c) /* 0.262629077 */, 19 }, - /* 7149 */ { MAD_F(0x0433edea) /* 0.262678067 */, 19 }, - /* 7150 */ { MAD_F(0x0434214a) /* 0.262727059 */, 19 }, - /* 7151 */ { MAD_F(0x043454aa) /* 0.262776054 */, 19 }, - - /* 7152 */ { MAD_F(0x0434880a) /* 0.262825051 */, 19 }, - /* 7153 */ { MAD_F(0x0434bb6b) /* 0.262874050 */, 19 }, - /* 7154 */ { MAD_F(0x0434eecd) /* 0.262923051 */, 19 }, - /* 7155 */ { MAD_F(0x0435222f) /* 0.262972055 */, 19 }, - /* 7156 */ { MAD_F(0x04355592) /* 0.263021061 */, 19 }, - /* 7157 */ { MAD_F(0x043588f6) /* 0.263070069 */, 19 }, - /* 7158 */ { MAD_F(0x0435bc5a) /* 0.263119079 */, 19 }, - /* 7159 */ { MAD_F(0x0435efbf) /* 0.263168092 */, 19 }, - /* 7160 */ { MAD_F(0x04362324) /* 0.263217107 */, 19 }, - /* 7161 */ { MAD_F(0x0436568a) /* 0.263266125 */, 19 }, - /* 7162 */ { MAD_F(0x043689f1) /* 0.263315144 */, 19 }, - /* 7163 */ { MAD_F(0x0436bd58) /* 0.263364166 */, 19 }, - /* 7164 */ { MAD_F(0x0436f0c0) /* 0.263413191 */, 19 }, - /* 7165 */ { MAD_F(0x04372428) /* 0.263462217 */, 19 }, - /* 7166 */ { MAD_F(0x04375791) /* 0.263511246 */, 19 }, - /* 7167 */ { MAD_F(0x04378afb) /* 0.263560277 */, 19 }, - - /* 7168 */ { MAD_F(0x0437be65) /* 0.263609310 */, 19 }, - /* 7169 */ { MAD_F(0x0437f1d0) /* 0.263658346 */, 19 }, - /* 7170 */ { MAD_F(0x0438253c) /* 0.263707384 */, 19 }, - /* 7171 */ { MAD_F(0x043858a8) /* 0.263756424 */, 19 }, - /* 7172 */ { MAD_F(0x04388c14) /* 0.263805466 */, 19 }, - /* 7173 */ { MAD_F(0x0438bf82) /* 0.263854511 */, 19 }, - /* 7174 */ { MAD_F(0x0438f2f0) /* 0.263903558 */, 19 }, - /* 7175 */ { MAD_F(0x0439265e) /* 0.263952607 */, 19 }, - /* 7176 */ { MAD_F(0x043959cd) /* 0.264001659 */, 19 }, - /* 7177 */ { MAD_F(0x04398d3d) /* 0.264050713 */, 19 }, - /* 7178 */ { MAD_F(0x0439c0ae) /* 0.264099769 */, 19 }, - /* 7179 */ { MAD_F(0x0439f41f) /* 0.264148827 */, 19 }, - /* 7180 */ { MAD_F(0x043a2790) /* 0.264197888 */, 19 }, - /* 7181 */ { MAD_F(0x043a5b02) /* 0.264246951 */, 19 }, - /* 7182 */ { MAD_F(0x043a8e75) /* 0.264296016 */, 19 }, - /* 7183 */ { MAD_F(0x043ac1e9) /* 0.264345084 */, 19 }, - - /* 7184 */ { MAD_F(0x043af55d) /* 0.264394153 */, 19 }, - /* 7185 */ { MAD_F(0x043b28d2) /* 0.264443225 */, 19 }, - /* 7186 */ { MAD_F(0x043b5c47) /* 0.264492300 */, 19 }, - /* 7187 */ { MAD_F(0x043b8fbd) /* 0.264541376 */, 19 }, - /* 7188 */ { MAD_F(0x043bc333) /* 0.264590455 */, 19 }, - /* 7189 */ { MAD_F(0x043bf6aa) /* 0.264639536 */, 19 }, - /* 7190 */ { MAD_F(0x043c2a22) /* 0.264688620 */, 19 }, - /* 7191 */ { MAD_F(0x043c5d9a) /* 0.264737706 */, 19 }, - /* 7192 */ { MAD_F(0x043c9113) /* 0.264786794 */, 19 }, - /* 7193 */ { MAD_F(0x043cc48d) /* 0.264835884 */, 19 }, - /* 7194 */ { MAD_F(0x043cf807) /* 0.264884976 */, 19 }, - /* 7195 */ { MAD_F(0x043d2b82) /* 0.264934071 */, 19 }, - /* 7196 */ { MAD_F(0x043d5efd) /* 0.264983168 */, 19 }, - /* 7197 */ { MAD_F(0x043d9279) /* 0.265032268 */, 19 }, - /* 7198 */ { MAD_F(0x043dc5f6) /* 0.265081369 */, 19 }, - /* 7199 */ { MAD_F(0x043df973) /* 0.265130473 */, 19 }, - - /* 7200 */ { MAD_F(0x043e2cf1) /* 0.265179580 */, 19 }, - /* 7201 */ { MAD_F(0x043e6070) /* 0.265228688 */, 19 }, - /* 7202 */ { MAD_F(0x043e93ef) /* 0.265277799 */, 19 }, - /* 7203 */ { MAD_F(0x043ec76e) /* 0.265326912 */, 19 }, - /* 7204 */ { MAD_F(0x043efaef) /* 0.265376027 */, 19 }, - /* 7205 */ { MAD_F(0x043f2e6f) /* 0.265425145 */, 19 }, - /* 7206 */ { MAD_F(0x043f61f1) /* 0.265474264 */, 19 }, - /* 7207 */ { MAD_F(0x043f9573) /* 0.265523387 */, 19 }, - /* 7208 */ { MAD_F(0x043fc8f6) /* 0.265572511 */, 19 }, - /* 7209 */ { MAD_F(0x043ffc79) /* 0.265621638 */, 19 }, - /* 7210 */ { MAD_F(0x04402ffd) /* 0.265670766 */, 19 }, - /* 7211 */ { MAD_F(0x04406382) /* 0.265719898 */, 19 }, - /* 7212 */ { MAD_F(0x04409707) /* 0.265769031 */, 19 }, - /* 7213 */ { MAD_F(0x0440ca8d) /* 0.265818167 */, 19 }, - /* 7214 */ { MAD_F(0x0440fe13) /* 0.265867305 */, 19 }, - /* 7215 */ { MAD_F(0x0441319a) /* 0.265916445 */, 19 }, - - /* 7216 */ { MAD_F(0x04416522) /* 0.265965588 */, 19 }, - /* 7217 */ { MAD_F(0x044198aa) /* 0.266014732 */, 19 }, - /* 7218 */ { MAD_F(0x0441cc33) /* 0.266063880 */, 19 }, - /* 7219 */ { MAD_F(0x0441ffbc) /* 0.266113029 */, 19 }, - /* 7220 */ { MAD_F(0x04423346) /* 0.266162181 */, 19 }, - /* 7221 */ { MAD_F(0x044266d1) /* 0.266211334 */, 19 }, - /* 7222 */ { MAD_F(0x04429a5c) /* 0.266260491 */, 19 }, - /* 7223 */ { MAD_F(0x0442cde8) /* 0.266309649 */, 19 }, - /* 7224 */ { MAD_F(0x04430174) /* 0.266358810 */, 19 }, - /* 7225 */ { MAD_F(0x04433501) /* 0.266407973 */, 19 }, - /* 7226 */ { MAD_F(0x0443688f) /* 0.266457138 */, 19 }, - /* 7227 */ { MAD_F(0x04439c1d) /* 0.266506305 */, 19 }, - /* 7228 */ { MAD_F(0x0443cfac) /* 0.266555475 */, 19 }, - /* 7229 */ { MAD_F(0x0444033c) /* 0.266604647 */, 19 }, - /* 7230 */ { MAD_F(0x044436cc) /* 0.266653822 */, 19 }, - /* 7231 */ { MAD_F(0x04446a5d) /* 0.266702998 */, 19 }, - - /* 7232 */ { MAD_F(0x04449dee) /* 0.266752177 */, 19 }, - /* 7233 */ { MAD_F(0x0444d180) /* 0.266801358 */, 19 }, - /* 7234 */ { MAD_F(0x04450513) /* 0.266850541 */, 19 }, - /* 7235 */ { MAD_F(0x044538a6) /* 0.266899727 */, 19 }, - /* 7236 */ { MAD_F(0x04456c39) /* 0.266948915 */, 19 }, - /* 7237 */ { MAD_F(0x04459fce) /* 0.266998105 */, 19 }, - /* 7238 */ { MAD_F(0x0445d363) /* 0.267047298 */, 19 }, - /* 7239 */ { MAD_F(0x044606f8) /* 0.267096492 */, 19 }, - /* 7240 */ { MAD_F(0x04463a8f) /* 0.267145689 */, 19 }, - /* 7241 */ { MAD_F(0x04466e25) /* 0.267194888 */, 19 }, - /* 7242 */ { MAD_F(0x0446a1bd) /* 0.267244090 */, 19 }, - /* 7243 */ { MAD_F(0x0446d555) /* 0.267293294 */, 19 }, - /* 7244 */ { MAD_F(0x044708ee) /* 0.267342500 */, 19 }, - /* 7245 */ { MAD_F(0x04473c87) /* 0.267391708 */, 19 }, - /* 7246 */ { MAD_F(0x04477021) /* 0.267440919 */, 19 }, - /* 7247 */ { MAD_F(0x0447a3bb) /* 0.267490131 */, 19 }, - - /* 7248 */ { MAD_F(0x0447d756) /* 0.267539347 */, 19 }, - /* 7249 */ { MAD_F(0x04480af2) /* 0.267588564 */, 19 }, - /* 7250 */ { MAD_F(0x04483e8e) /* 0.267637783 */, 19 }, - /* 7251 */ { MAD_F(0x0448722b) /* 0.267687005 */, 19 }, - /* 7252 */ { MAD_F(0x0448a5c9) /* 0.267736229 */, 19 }, - /* 7253 */ { MAD_F(0x0448d967) /* 0.267785456 */, 19 }, - /* 7254 */ { MAD_F(0x04490d05) /* 0.267834685 */, 19 }, - /* 7255 */ { MAD_F(0x044940a5) /* 0.267883915 */, 19 }, - /* 7256 */ { MAD_F(0x04497445) /* 0.267933149 */, 19 }, - /* 7257 */ { MAD_F(0x0449a7e5) /* 0.267982384 */, 19 }, - /* 7258 */ { MAD_F(0x0449db86) /* 0.268031622 */, 19 }, - /* 7259 */ { MAD_F(0x044a0f28) /* 0.268080862 */, 19 }, - /* 7260 */ { MAD_F(0x044a42ca) /* 0.268130104 */, 19 }, - /* 7261 */ { MAD_F(0x044a766d) /* 0.268179349 */, 19 }, - /* 7262 */ { MAD_F(0x044aaa11) /* 0.268228595 */, 19 }, - /* 7263 */ { MAD_F(0x044addb5) /* 0.268277844 */, 19 }, - - /* 7264 */ { MAD_F(0x044b115a) /* 0.268327096 */, 19 }, - /* 7265 */ { MAD_F(0x044b44ff) /* 0.268376349 */, 19 }, - /* 7266 */ { MAD_F(0x044b78a5) /* 0.268425605 */, 19 }, - /* 7267 */ { MAD_F(0x044bac4c) /* 0.268474863 */, 19 }, - /* 7268 */ { MAD_F(0x044bdff3) /* 0.268524123 */, 19 }, - /* 7269 */ { MAD_F(0x044c139b) /* 0.268573386 */, 19 }, - /* 7270 */ { MAD_F(0x044c4743) /* 0.268622651 */, 19 }, - /* 7271 */ { MAD_F(0x044c7aec) /* 0.268671918 */, 19 }, - /* 7272 */ { MAD_F(0x044cae96) /* 0.268721187 */, 19 }, - /* 7273 */ { MAD_F(0x044ce240) /* 0.268770459 */, 19 }, - /* 7274 */ { MAD_F(0x044d15eb) /* 0.268819733 */, 19 }, - /* 7275 */ { MAD_F(0x044d4997) /* 0.268869009 */, 19 }, - /* 7276 */ { MAD_F(0x044d7d43) /* 0.268918287 */, 19 }, - /* 7277 */ { MAD_F(0x044db0ef) /* 0.268967568 */, 19 }, - /* 7278 */ { MAD_F(0x044de49d) /* 0.269016851 */, 19 }, - /* 7279 */ { MAD_F(0x044e184b) /* 0.269066136 */, 19 }, - - /* 7280 */ { MAD_F(0x044e4bf9) /* 0.269115423 */, 19 }, - /* 7281 */ { MAD_F(0x044e7fa8) /* 0.269164713 */, 19 }, - /* 7282 */ { MAD_F(0x044eb358) /* 0.269214005 */, 19 }, - /* 7283 */ { MAD_F(0x044ee708) /* 0.269263299 */, 19 }, - /* 7284 */ { MAD_F(0x044f1ab9) /* 0.269312595 */, 19 }, - /* 7285 */ { MAD_F(0x044f4e6b) /* 0.269361894 */, 19 }, - /* 7286 */ { MAD_F(0x044f821d) /* 0.269411195 */, 19 }, - /* 7287 */ { MAD_F(0x044fb5cf) /* 0.269460498 */, 19 }, - /* 7288 */ { MAD_F(0x044fe983) /* 0.269509804 */, 19 }, - /* 7289 */ { MAD_F(0x04501d37) /* 0.269559111 */, 19 }, - /* 7290 */ { MAD_F(0x045050eb) /* 0.269608421 */, 19 }, - /* 7291 */ { MAD_F(0x045084a0) /* 0.269657734 */, 19 }, - /* 7292 */ { MAD_F(0x0450b856) /* 0.269707048 */, 19 }, - /* 7293 */ { MAD_F(0x0450ec0d) /* 0.269756365 */, 19 }, - /* 7294 */ { MAD_F(0x04511fc4) /* 0.269805684 */, 19 }, - /* 7295 */ { MAD_F(0x0451537b) /* 0.269855005 */, 19 }, - - /* 7296 */ { MAD_F(0x04518733) /* 0.269904329 */, 19 }, - /* 7297 */ { MAD_F(0x0451baec) /* 0.269953654 */, 19 }, - /* 7298 */ { MAD_F(0x0451eea5) /* 0.270002982 */, 19 }, - /* 7299 */ { MAD_F(0x0452225f) /* 0.270052313 */, 19 }, - /* 7300 */ { MAD_F(0x0452561a) /* 0.270101645 */, 19 }, - /* 7301 */ { MAD_F(0x045289d5) /* 0.270150980 */, 19 }, - /* 7302 */ { MAD_F(0x0452bd91) /* 0.270200317 */, 19 }, - /* 7303 */ { MAD_F(0x0452f14d) /* 0.270249656 */, 19 }, - /* 7304 */ { MAD_F(0x0453250a) /* 0.270298998 */, 19 }, - /* 7305 */ { MAD_F(0x045358c8) /* 0.270348341 */, 19 }, - /* 7306 */ { MAD_F(0x04538c86) /* 0.270397687 */, 19 }, - /* 7307 */ { MAD_F(0x0453c045) /* 0.270447036 */, 19 }, - /* 7308 */ { MAD_F(0x0453f405) /* 0.270496386 */, 19 }, - /* 7309 */ { MAD_F(0x045427c5) /* 0.270545739 */, 19 }, - /* 7310 */ { MAD_F(0x04545b85) /* 0.270595094 */, 19 }, - /* 7311 */ { MAD_F(0x04548f46) /* 0.270644451 */, 19 }, - - /* 7312 */ { MAD_F(0x0454c308) /* 0.270693811 */, 19 }, - /* 7313 */ { MAD_F(0x0454f6cb) /* 0.270743173 */, 19 }, - /* 7314 */ { MAD_F(0x04552a8e) /* 0.270792537 */, 19 }, - /* 7315 */ { MAD_F(0x04555e51) /* 0.270841903 */, 19 }, - /* 7316 */ { MAD_F(0x04559216) /* 0.270891271 */, 19 }, - /* 7317 */ { MAD_F(0x0455c5db) /* 0.270940642 */, 19 }, - /* 7318 */ { MAD_F(0x0455f9a0) /* 0.270990015 */, 19 }, - /* 7319 */ { MAD_F(0x04562d66) /* 0.271039390 */, 19 }, - /* 7320 */ { MAD_F(0x0456612d) /* 0.271088768 */, 19 }, - /* 7321 */ { MAD_F(0x045694f4) /* 0.271138148 */, 19 }, - /* 7322 */ { MAD_F(0x0456c8bc) /* 0.271187530 */, 19 }, - /* 7323 */ { MAD_F(0x0456fc84) /* 0.271236914 */, 19 }, - /* 7324 */ { MAD_F(0x0457304e) /* 0.271286301 */, 19 }, - /* 7325 */ { MAD_F(0x04576417) /* 0.271335689 */, 19 }, - /* 7326 */ { MAD_F(0x045797e2) /* 0.271385080 */, 19 }, - /* 7327 */ { MAD_F(0x0457cbac) /* 0.271434474 */, 19 }, - - /* 7328 */ { MAD_F(0x0457ff78) /* 0.271483869 */, 19 }, - /* 7329 */ { MAD_F(0x04583344) /* 0.271533267 */, 19 }, - /* 7330 */ { MAD_F(0x04586711) /* 0.271582667 */, 19 }, - /* 7331 */ { MAD_F(0x04589ade) /* 0.271632069 */, 19 }, - /* 7332 */ { MAD_F(0x0458ceac) /* 0.271681474 */, 19 }, - /* 7333 */ { MAD_F(0x0459027b) /* 0.271730880 */, 19 }, - /* 7334 */ { MAD_F(0x0459364a) /* 0.271780289 */, 19 }, - /* 7335 */ { MAD_F(0x04596a19) /* 0.271829701 */, 19 }, - /* 7336 */ { MAD_F(0x04599dea) /* 0.271879114 */, 19 }, - /* 7337 */ { MAD_F(0x0459d1bb) /* 0.271928530 */, 19 }, - /* 7338 */ { MAD_F(0x045a058c) /* 0.271977948 */, 19 }, - /* 7339 */ { MAD_F(0x045a395e) /* 0.272027368 */, 19 }, - /* 7340 */ { MAD_F(0x045a6d31) /* 0.272076790 */, 19 }, - /* 7341 */ { MAD_F(0x045aa104) /* 0.272126215 */, 19 }, - /* 7342 */ { MAD_F(0x045ad4d8) /* 0.272175642 */, 19 }, - /* 7343 */ { MAD_F(0x045b08ad) /* 0.272225071 */, 19 }, - - /* 7344 */ { MAD_F(0x045b3c82) /* 0.272274503 */, 19 }, - /* 7345 */ { MAD_F(0x045b7058) /* 0.272323936 */, 19 }, - /* 7346 */ { MAD_F(0x045ba42e) /* 0.272373372 */, 19 }, - /* 7347 */ { MAD_F(0x045bd805) /* 0.272422810 */, 19 }, - /* 7348 */ { MAD_F(0x045c0bdd) /* 0.272472251 */, 19 }, - /* 7349 */ { MAD_F(0x045c3fb5) /* 0.272521693 */, 19 }, - /* 7350 */ { MAD_F(0x045c738e) /* 0.272571138 */, 19 }, - /* 7351 */ { MAD_F(0x045ca767) /* 0.272620585 */, 19 }, - /* 7352 */ { MAD_F(0x045cdb41) /* 0.272670035 */, 19 }, - /* 7353 */ { MAD_F(0x045d0f1b) /* 0.272719486 */, 19 }, - /* 7354 */ { MAD_F(0x045d42f7) /* 0.272768940 */, 19 }, - /* 7355 */ { MAD_F(0x045d76d2) /* 0.272818396 */, 19 }, - /* 7356 */ { MAD_F(0x045daaaf) /* 0.272867855 */, 19 }, - /* 7357 */ { MAD_F(0x045dde8c) /* 0.272917315 */, 19 }, - /* 7358 */ { MAD_F(0x045e1269) /* 0.272966778 */, 19 }, - /* 7359 */ { MAD_F(0x045e4647) /* 0.273016243 */, 19 }, - - /* 7360 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 19 }, - /* 7361 */ { MAD_F(0x045eae06) /* 0.273115180 */, 19 }, - /* 7362 */ { MAD_F(0x045ee1e6) /* 0.273164652 */, 19 }, - /* 7363 */ { MAD_F(0x045f15c6) /* 0.273214126 */, 19 }, - /* 7364 */ { MAD_F(0x045f49a7) /* 0.273263602 */, 19 }, - /* 7365 */ { MAD_F(0x045f7d89) /* 0.273313081 */, 19 }, - /* 7366 */ { MAD_F(0x045fb16c) /* 0.273362561 */, 19 }, - /* 7367 */ { MAD_F(0x045fe54f) /* 0.273412044 */, 19 }, - /* 7368 */ { MAD_F(0x04601932) /* 0.273461530 */, 19 }, - /* 7369 */ { MAD_F(0x04604d16) /* 0.273511017 */, 19 }, - /* 7370 */ { MAD_F(0x046080fb) /* 0.273560507 */, 19 }, - /* 7371 */ { MAD_F(0x0460b4e1) /* 0.273609999 */, 19 }, - /* 7372 */ { MAD_F(0x0460e8c7) /* 0.273659493 */, 19 }, - /* 7373 */ { MAD_F(0x04611cad) /* 0.273708989 */, 19 }, - /* 7374 */ { MAD_F(0x04615094) /* 0.273758488 */, 19 }, - /* 7375 */ { MAD_F(0x0461847c) /* 0.273807989 */, 19 }, - - /* 7376 */ { MAD_F(0x0461b864) /* 0.273857492 */, 19 }, - /* 7377 */ { MAD_F(0x0461ec4d) /* 0.273906997 */, 19 }, - /* 7378 */ { MAD_F(0x04622037) /* 0.273956505 */, 19 }, - /* 7379 */ { MAD_F(0x04625421) /* 0.274006015 */, 19 }, - /* 7380 */ { MAD_F(0x0462880c) /* 0.274055527 */, 19 }, - /* 7381 */ { MAD_F(0x0462bbf7) /* 0.274105041 */, 19 }, - /* 7382 */ { MAD_F(0x0462efe3) /* 0.274154558 */, 19 }, - /* 7383 */ { MAD_F(0x046323d0) /* 0.274204076 */, 19 }, - /* 7384 */ { MAD_F(0x046357bd) /* 0.274253597 */, 19 }, - /* 7385 */ { MAD_F(0x04638bab) /* 0.274303121 */, 19 }, - /* 7386 */ { MAD_F(0x0463bf99) /* 0.274352646 */, 19 }, - /* 7387 */ { MAD_F(0x0463f388) /* 0.274402174 */, 19 }, - /* 7388 */ { MAD_F(0x04642778) /* 0.274451704 */, 19 }, - /* 7389 */ { MAD_F(0x04645b68) /* 0.274501236 */, 19 }, - /* 7390 */ { MAD_F(0x04648f59) /* 0.274550771 */, 19 }, - /* 7391 */ { MAD_F(0x0464c34a) /* 0.274600307 */, 19 }, - - /* 7392 */ { MAD_F(0x0464f73c) /* 0.274649846 */, 19 }, - /* 7393 */ { MAD_F(0x04652b2f) /* 0.274699387 */, 19 }, - /* 7394 */ { MAD_F(0x04655f22) /* 0.274748931 */, 19 }, - /* 7395 */ { MAD_F(0x04659316) /* 0.274798476 */, 19 }, - /* 7396 */ { MAD_F(0x0465c70a) /* 0.274848024 */, 19 }, - /* 7397 */ { MAD_F(0x0465faff) /* 0.274897574 */, 19 }, - /* 7398 */ { MAD_F(0x04662ef5) /* 0.274947126 */, 19 }, - /* 7399 */ { MAD_F(0x046662eb) /* 0.274996681 */, 19 }, - /* 7400 */ { MAD_F(0x046696e2) /* 0.275046238 */, 19 }, - /* 7401 */ { MAD_F(0x0466cad9) /* 0.275095797 */, 19 }, - /* 7402 */ { MAD_F(0x0466fed1) /* 0.275145358 */, 19 }, - /* 7403 */ { MAD_F(0x046732ca) /* 0.275194921 */, 19 }, - /* 7404 */ { MAD_F(0x046766c3) /* 0.275244487 */, 19 }, - /* 7405 */ { MAD_F(0x04679abd) /* 0.275294055 */, 19 }, - /* 7406 */ { MAD_F(0x0467ceb7) /* 0.275343625 */, 19 }, - /* 7407 */ { MAD_F(0x046802b2) /* 0.275393198 */, 19 }, - - /* 7408 */ { MAD_F(0x046836ae) /* 0.275442772 */, 19 }, - /* 7409 */ { MAD_F(0x04686aaa) /* 0.275492349 */, 19 }, - /* 7410 */ { MAD_F(0x04689ea7) /* 0.275541928 */, 19 }, - /* 7411 */ { MAD_F(0x0468d2a4) /* 0.275591509 */, 19 }, - /* 7412 */ { MAD_F(0x046906a2) /* 0.275641093 */, 19 }, - /* 7413 */ { MAD_F(0x04693aa1) /* 0.275690679 */, 19 }, - /* 7414 */ { MAD_F(0x04696ea0) /* 0.275740267 */, 19 }, - /* 7415 */ { MAD_F(0x0469a2a0) /* 0.275789857 */, 19 }, - /* 7416 */ { MAD_F(0x0469d6a0) /* 0.275839449 */, 19 }, - /* 7417 */ { MAD_F(0x046a0aa1) /* 0.275889044 */, 19 }, - /* 7418 */ { MAD_F(0x046a3ea3) /* 0.275938641 */, 19 }, - /* 7419 */ { MAD_F(0x046a72a5) /* 0.275988240 */, 19 }, - /* 7420 */ { MAD_F(0x046aa6a8) /* 0.276037842 */, 19 }, - /* 7421 */ { MAD_F(0x046adaab) /* 0.276087445 */, 19 }, - /* 7422 */ { MAD_F(0x046b0eaf) /* 0.276137051 */, 19 }, - /* 7423 */ { MAD_F(0x046b42b3) /* 0.276186659 */, 19 }, - - /* 7424 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 19 }, - /* 7425 */ { MAD_F(0x046baabe) /* 0.276285882 */, 19 }, - /* 7426 */ { MAD_F(0x046bdec5) /* 0.276335497 */, 19 }, - /* 7427 */ { MAD_F(0x046c12cc) /* 0.276385113 */, 19 }, - /* 7428 */ { MAD_F(0x046c46d3) /* 0.276434733 */, 19 }, - /* 7429 */ { MAD_F(0x046c7adb) /* 0.276484354 */, 19 }, - /* 7430 */ { MAD_F(0x046caee4) /* 0.276533978 */, 19 }, - /* 7431 */ { MAD_F(0x046ce2ee) /* 0.276583604 */, 19 }, - /* 7432 */ { MAD_F(0x046d16f7) /* 0.276633232 */, 19 }, - /* 7433 */ { MAD_F(0x046d4b02) /* 0.276682862 */, 19 }, - /* 7434 */ { MAD_F(0x046d7f0d) /* 0.276732495 */, 19 }, - /* 7435 */ { MAD_F(0x046db319) /* 0.276782129 */, 19 }, - /* 7436 */ { MAD_F(0x046de725) /* 0.276831766 */, 19 }, - /* 7437 */ { MAD_F(0x046e1b32) /* 0.276881406 */, 19 }, - /* 7438 */ { MAD_F(0x046e4f40) /* 0.276931047 */, 19 }, - /* 7439 */ { MAD_F(0x046e834e) /* 0.276980691 */, 19 }, - - /* 7440 */ { MAD_F(0x046eb75c) /* 0.277030337 */, 19 }, - /* 7441 */ { MAD_F(0x046eeb6c) /* 0.277079985 */, 19 }, - /* 7442 */ { MAD_F(0x046f1f7c) /* 0.277129635 */, 19 }, - /* 7443 */ { MAD_F(0x046f538c) /* 0.277179288 */, 19 }, - /* 7444 */ { MAD_F(0x046f879d) /* 0.277228942 */, 19 }, - /* 7445 */ { MAD_F(0x046fbbaf) /* 0.277278600 */, 19 }, - /* 7446 */ { MAD_F(0x046fefc1) /* 0.277328259 */, 19 }, - /* 7447 */ { MAD_F(0x047023d4) /* 0.277377920 */, 19 }, - /* 7448 */ { MAD_F(0x047057e8) /* 0.277427584 */, 19 }, - /* 7449 */ { MAD_F(0x04708bfc) /* 0.277477250 */, 19 }, - /* 7450 */ { MAD_F(0x0470c011) /* 0.277526918 */, 19 }, - /* 7451 */ { MAD_F(0x0470f426) /* 0.277576588 */, 19 }, - /* 7452 */ { MAD_F(0x0471283c) /* 0.277626261 */, 19 }, - /* 7453 */ { MAD_F(0x04715c52) /* 0.277675936 */, 19 }, - /* 7454 */ { MAD_F(0x04719069) /* 0.277725613 */, 19 }, - /* 7455 */ { MAD_F(0x0471c481) /* 0.277775292 */, 19 }, - - /* 7456 */ { MAD_F(0x0471f899) /* 0.277824973 */, 19 }, - /* 7457 */ { MAD_F(0x04722cb2) /* 0.277874657 */, 19 }, - /* 7458 */ { MAD_F(0x047260cc) /* 0.277924343 */, 19 }, - /* 7459 */ { MAD_F(0x047294e6) /* 0.277974031 */, 19 }, - /* 7460 */ { MAD_F(0x0472c900) /* 0.278023722 */, 19 }, - /* 7461 */ { MAD_F(0x0472fd1b) /* 0.278073414 */, 19 }, - /* 7462 */ { MAD_F(0x04733137) /* 0.278123109 */, 19 }, - /* 7463 */ { MAD_F(0x04736554) /* 0.278172806 */, 19 }, - /* 7464 */ { MAD_F(0x04739971) /* 0.278222505 */, 19 }, - /* 7465 */ { MAD_F(0x0473cd8e) /* 0.278272207 */, 19 }, - /* 7466 */ { MAD_F(0x047401ad) /* 0.278321910 */, 19 }, - /* 7467 */ { MAD_F(0x047435cb) /* 0.278371616 */, 19 }, - /* 7468 */ { MAD_F(0x047469eb) /* 0.278421324 */, 19 }, - /* 7469 */ { MAD_F(0x04749e0b) /* 0.278471035 */, 19 }, - /* 7470 */ { MAD_F(0x0474d22c) /* 0.278520747 */, 19 }, - /* 7471 */ { MAD_F(0x0475064d) /* 0.278570462 */, 19 }, - - /* 7472 */ { MAD_F(0x04753a6f) /* 0.278620179 */, 19 }, - /* 7473 */ { MAD_F(0x04756e91) /* 0.278669898 */, 19 }, - /* 7474 */ { MAD_F(0x0475a2b4) /* 0.278719619 */, 19 }, - /* 7475 */ { MAD_F(0x0475d6d7) /* 0.278769343 */, 19 }, - /* 7476 */ { MAD_F(0x04760afc) /* 0.278819069 */, 19 }, - /* 7477 */ { MAD_F(0x04763f20) /* 0.278868797 */, 19 }, - /* 7478 */ { MAD_F(0x04767346) /* 0.278918527 */, 19 }, - /* 7479 */ { MAD_F(0x0476a76c) /* 0.278968260 */, 19 }, - /* 7480 */ { MAD_F(0x0476db92) /* 0.279017995 */, 19 }, - /* 7481 */ { MAD_F(0x04770fba) /* 0.279067731 */, 19 }, - /* 7482 */ { MAD_F(0x047743e1) /* 0.279117471 */, 19 }, - /* 7483 */ { MAD_F(0x0477780a) /* 0.279167212 */, 19 }, - /* 7484 */ { MAD_F(0x0477ac33) /* 0.279216956 */, 19 }, - /* 7485 */ { MAD_F(0x0477e05c) /* 0.279266701 */, 19 }, - /* 7486 */ { MAD_F(0x04781486) /* 0.279316449 */, 19 }, - /* 7487 */ { MAD_F(0x047848b1) /* 0.279366200 */, 19 }, - - /* 7488 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 19 }, - /* 7489 */ { MAD_F(0x0478b108) /* 0.279465707 */, 19 }, - /* 7490 */ { MAD_F(0x0478e535) /* 0.279515464 */, 19 }, - /* 7491 */ { MAD_F(0x04791962) /* 0.279565223 */, 19 }, - /* 7492 */ { MAD_F(0x04794d8f) /* 0.279614984 */, 19 }, - /* 7493 */ { MAD_F(0x047981be) /* 0.279664748 */, 19 }, - /* 7494 */ { MAD_F(0x0479b5ed) /* 0.279714513 */, 19 }, - /* 7495 */ { MAD_F(0x0479ea1c) /* 0.279764281 */, 19 }, - /* 7496 */ { MAD_F(0x047a1e4c) /* 0.279814051 */, 19 }, - /* 7497 */ { MAD_F(0x047a527d) /* 0.279863824 */, 19 }, - /* 7498 */ { MAD_F(0x047a86ae) /* 0.279913598 */, 19 }, - /* 7499 */ { MAD_F(0x047abae0) /* 0.279963375 */, 19 }, - /* 7500 */ { MAD_F(0x047aef12) /* 0.280013154 */, 19 }, - /* 7501 */ { MAD_F(0x047b2346) /* 0.280062935 */, 19 }, - /* 7502 */ { MAD_F(0x047b5779) /* 0.280112719 */, 19 }, - /* 7503 */ { MAD_F(0x047b8bad) /* 0.280162504 */, 19 }, - - /* 7504 */ { MAD_F(0x047bbfe2) /* 0.280212292 */, 19 }, - /* 7505 */ { MAD_F(0x047bf418) /* 0.280262082 */, 19 }, - /* 7506 */ { MAD_F(0x047c284e) /* 0.280311875 */, 19 }, - /* 7507 */ { MAD_F(0x047c5c84) /* 0.280361669 */, 19 }, - /* 7508 */ { MAD_F(0x047c90bb) /* 0.280411466 */, 19 }, - /* 7509 */ { MAD_F(0x047cc4f3) /* 0.280461265 */, 19 }, - /* 7510 */ { MAD_F(0x047cf92c) /* 0.280511066 */, 19 }, - /* 7511 */ { MAD_F(0x047d2d65) /* 0.280560869 */, 19 }, - /* 7512 */ { MAD_F(0x047d619e) /* 0.280610675 */, 19 }, - /* 7513 */ { MAD_F(0x047d95d8) /* 0.280660483 */, 19 }, - /* 7514 */ { MAD_F(0x047dca13) /* 0.280710292 */, 19 }, - /* 7515 */ { MAD_F(0x047dfe4e) /* 0.280760105 */, 19 }, - /* 7516 */ { MAD_F(0x047e328a) /* 0.280809919 */, 19 }, - /* 7517 */ { MAD_F(0x047e66c7) /* 0.280859736 */, 19 }, - /* 7518 */ { MAD_F(0x047e9b04) /* 0.280909554 */, 19 }, - /* 7519 */ { MAD_F(0x047ecf42) /* 0.280959375 */, 19 }, - - /* 7520 */ { MAD_F(0x047f0380) /* 0.281009199 */, 19 }, - /* 7521 */ { MAD_F(0x047f37bf) /* 0.281059024 */, 19 }, - /* 7522 */ { MAD_F(0x047f6bff) /* 0.281108852 */, 19 }, - /* 7523 */ { MAD_F(0x047fa03f) /* 0.281158682 */, 19 }, - /* 7524 */ { MAD_F(0x047fd47f) /* 0.281208514 */, 19 }, - /* 7525 */ { MAD_F(0x048008c1) /* 0.281258348 */, 19 }, - /* 7526 */ { MAD_F(0x04803d02) /* 0.281308184 */, 19 }, - /* 7527 */ { MAD_F(0x04807145) /* 0.281358023 */, 19 }, - /* 7528 */ { MAD_F(0x0480a588) /* 0.281407864 */, 19 }, - /* 7529 */ { MAD_F(0x0480d9cc) /* 0.281457707 */, 19 }, - /* 7530 */ { MAD_F(0x04810e10) /* 0.281507552 */, 19 }, - /* 7531 */ { MAD_F(0x04814255) /* 0.281557400 */, 19 }, - /* 7532 */ { MAD_F(0x0481769a) /* 0.281607250 */, 19 }, - /* 7533 */ { MAD_F(0x0481aae0) /* 0.281657101 */, 19 }, - /* 7534 */ { MAD_F(0x0481df27) /* 0.281706956 */, 19 }, - /* 7535 */ { MAD_F(0x0482136e) /* 0.281756812 */, 19 }, - - /* 7536 */ { MAD_F(0x048247b6) /* 0.281806670 */, 19 }, - /* 7537 */ { MAD_F(0x04827bfe) /* 0.281856531 */, 19 }, - /* 7538 */ { MAD_F(0x0482b047) /* 0.281906394 */, 19 }, - /* 7539 */ { MAD_F(0x0482e491) /* 0.281956259 */, 19 }, - /* 7540 */ { MAD_F(0x048318db) /* 0.282006127 */, 19 }, - /* 7541 */ { MAD_F(0x04834d26) /* 0.282055996 */, 19 }, - /* 7542 */ { MAD_F(0x04838171) /* 0.282105868 */, 19 }, - /* 7543 */ { MAD_F(0x0483b5bd) /* 0.282155742 */, 19 }, - /* 7544 */ { MAD_F(0x0483ea0a) /* 0.282205618 */, 19 }, - /* 7545 */ { MAD_F(0x04841e57) /* 0.282255496 */, 19 }, - /* 7546 */ { MAD_F(0x048452a4) /* 0.282305377 */, 19 }, - /* 7547 */ { MAD_F(0x048486f3) /* 0.282355260 */, 19 }, - /* 7548 */ { MAD_F(0x0484bb42) /* 0.282405145 */, 19 }, - /* 7549 */ { MAD_F(0x0484ef91) /* 0.282455032 */, 19 }, - /* 7550 */ { MAD_F(0x048523e1) /* 0.282504921 */, 19 }, - /* 7551 */ { MAD_F(0x04855832) /* 0.282554813 */, 19 }, - - /* 7552 */ { MAD_F(0x04858c83) /* 0.282604707 */, 19 }, - /* 7553 */ { MAD_F(0x0485c0d5) /* 0.282654603 */, 19 }, - /* 7554 */ { MAD_F(0x0485f527) /* 0.282704501 */, 19 }, - /* 7555 */ { MAD_F(0x0486297a) /* 0.282754401 */, 19 }, - /* 7556 */ { MAD_F(0x04865dce) /* 0.282804304 */, 19 }, - /* 7557 */ { MAD_F(0x04869222) /* 0.282854209 */, 19 }, - /* 7558 */ { MAD_F(0x0486c677) /* 0.282904116 */, 19 }, - /* 7559 */ { MAD_F(0x0486facc) /* 0.282954025 */, 19 }, - /* 7560 */ { MAD_F(0x04872f22) /* 0.283003936 */, 19 }, - /* 7561 */ { MAD_F(0x04876379) /* 0.283053850 */, 19 }, - /* 7562 */ { MAD_F(0x048797d0) /* 0.283103766 */, 19 }, - /* 7563 */ { MAD_F(0x0487cc28) /* 0.283153684 */, 19 }, - /* 7564 */ { MAD_F(0x04880080) /* 0.283203604 */, 19 }, - /* 7565 */ { MAD_F(0x048834d9) /* 0.283253527 */, 19 }, - /* 7566 */ { MAD_F(0x04886933) /* 0.283303451 */, 19 }, - /* 7567 */ { MAD_F(0x04889d8d) /* 0.283353378 */, 19 }, - - /* 7568 */ { MAD_F(0x0488d1e8) /* 0.283403307 */, 19 }, - /* 7569 */ { MAD_F(0x04890643) /* 0.283453238 */, 19 }, - /* 7570 */ { MAD_F(0x04893a9f) /* 0.283503172 */, 19 }, - /* 7571 */ { MAD_F(0x04896efb) /* 0.283553107 */, 19 }, - /* 7572 */ { MAD_F(0x0489a358) /* 0.283603045 */, 19 }, - /* 7573 */ { MAD_F(0x0489d7b6) /* 0.283652985 */, 19 }, - /* 7574 */ { MAD_F(0x048a0c14) /* 0.283702927 */, 19 }, - /* 7575 */ { MAD_F(0x048a4073) /* 0.283752872 */, 19 }, - /* 7576 */ { MAD_F(0x048a74d3) /* 0.283802818 */, 19 }, - /* 7577 */ { MAD_F(0x048aa933) /* 0.283852767 */, 19 }, - /* 7578 */ { MAD_F(0x048add93) /* 0.283902718 */, 19 }, - /* 7579 */ { MAD_F(0x048b11f5) /* 0.283952671 */, 19 }, - /* 7580 */ { MAD_F(0x048b4656) /* 0.284002627 */, 19 }, - /* 7581 */ { MAD_F(0x048b7ab9) /* 0.284052584 */, 19 }, - /* 7582 */ { MAD_F(0x048baf1c) /* 0.284102544 */, 19 }, - /* 7583 */ { MAD_F(0x048be37f) /* 0.284152506 */, 19 }, - - /* 7584 */ { MAD_F(0x048c17e3) /* 0.284202470 */, 19 }, - /* 7585 */ { MAD_F(0x048c4c48) /* 0.284252436 */, 19 }, - /* 7586 */ { MAD_F(0x048c80ad) /* 0.284302405 */, 19 }, - /* 7587 */ { MAD_F(0x048cb513) /* 0.284352376 */, 19 }, - /* 7588 */ { MAD_F(0x048ce97a) /* 0.284402349 */, 19 }, - /* 7589 */ { MAD_F(0x048d1de1) /* 0.284452324 */, 19 }, - /* 7590 */ { MAD_F(0x048d5249) /* 0.284502301 */, 19 }, - /* 7591 */ { MAD_F(0x048d86b1) /* 0.284552281 */, 19 }, - /* 7592 */ { MAD_F(0x048dbb1a) /* 0.284602263 */, 19 }, - /* 7593 */ { MAD_F(0x048def83) /* 0.284652246 */, 19 }, - /* 7594 */ { MAD_F(0x048e23ed) /* 0.284702233 */, 19 }, - /* 7595 */ { MAD_F(0x048e5858) /* 0.284752221 */, 19 }, - /* 7596 */ { MAD_F(0x048e8cc3) /* 0.284802211 */, 19 }, - /* 7597 */ { MAD_F(0x048ec12f) /* 0.284852204 */, 19 }, - /* 7598 */ { MAD_F(0x048ef59b) /* 0.284902199 */, 19 }, - /* 7599 */ { MAD_F(0x048f2a08) /* 0.284952196 */, 19 }, - - /* 7600 */ { MAD_F(0x048f5e76) /* 0.285002195 */, 19 }, - /* 7601 */ { MAD_F(0x048f92e4) /* 0.285052197 */, 19 }, - /* 7602 */ { MAD_F(0x048fc753) /* 0.285102201 */, 19 }, - /* 7603 */ { MAD_F(0x048ffbc2) /* 0.285152206 */, 19 }, - /* 7604 */ { MAD_F(0x04903032) /* 0.285202214 */, 19 }, - /* 7605 */ { MAD_F(0x049064a3) /* 0.285252225 */, 19 }, - /* 7606 */ { MAD_F(0x04909914) /* 0.285302237 */, 19 }, - /* 7607 */ { MAD_F(0x0490cd86) /* 0.285352252 */, 19 }, - /* 7608 */ { MAD_F(0x049101f8) /* 0.285402269 */, 19 }, - /* 7609 */ { MAD_F(0x0491366b) /* 0.285452288 */, 19 }, - /* 7610 */ { MAD_F(0x04916ade) /* 0.285502309 */, 19 }, - /* 7611 */ { MAD_F(0x04919f52) /* 0.285552332 */, 19 }, - /* 7612 */ { MAD_F(0x0491d3c7) /* 0.285602358 */, 19 }, - /* 7613 */ { MAD_F(0x0492083c) /* 0.285652386 */, 19 }, - /* 7614 */ { MAD_F(0x04923cb2) /* 0.285702416 */, 19 }, - /* 7615 */ { MAD_F(0x04927128) /* 0.285752448 */, 19 }, - - /* 7616 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 19 }, - /* 7617 */ { MAD_F(0x0492da17) /* 0.285852519 */, 19 }, - /* 7618 */ { MAD_F(0x04930e8f) /* 0.285902557 */, 19 }, - /* 7619 */ { MAD_F(0x04934308) /* 0.285952598 */, 19 }, - /* 7620 */ { MAD_F(0x04937781) /* 0.286002641 */, 19 }, - /* 7621 */ { MAD_F(0x0493abfb) /* 0.286052687 */, 19 }, - /* 7622 */ { MAD_F(0x0493e076) /* 0.286102734 */, 19 }, - /* 7623 */ { MAD_F(0x049414f1) /* 0.286152784 */, 19 }, - /* 7624 */ { MAD_F(0x0494496c) /* 0.286202836 */, 19 }, - /* 7625 */ { MAD_F(0x04947de9) /* 0.286252890 */, 19 }, - /* 7626 */ { MAD_F(0x0494b266) /* 0.286302946 */, 19 }, - /* 7627 */ { MAD_F(0x0494e6e3) /* 0.286353005 */, 19 }, - /* 7628 */ { MAD_F(0x04951b61) /* 0.286403065 */, 19 }, - /* 7629 */ { MAD_F(0x04954fe0) /* 0.286453128 */, 19 }, - /* 7630 */ { MAD_F(0x0495845f) /* 0.286503193 */, 19 }, - /* 7631 */ { MAD_F(0x0495b8df) /* 0.286553260 */, 19 }, - - /* 7632 */ { MAD_F(0x0495ed5f) /* 0.286603329 */, 19 }, - /* 7633 */ { MAD_F(0x049621e0) /* 0.286653401 */, 19 }, - /* 7634 */ { MAD_F(0x04965662) /* 0.286703475 */, 19 }, - /* 7635 */ { MAD_F(0x04968ae4) /* 0.286753551 */, 19 }, - /* 7636 */ { MAD_F(0x0496bf67) /* 0.286803629 */, 19 }, - /* 7637 */ { MAD_F(0x0496f3ea) /* 0.286853709 */, 19 }, - /* 7638 */ { MAD_F(0x0497286e) /* 0.286903792 */, 19 }, - /* 7639 */ { MAD_F(0x04975cf2) /* 0.286953876 */, 19 }, - /* 7640 */ { MAD_F(0x04979177) /* 0.287003963 */, 19 }, - /* 7641 */ { MAD_F(0x0497c5fd) /* 0.287054052 */, 19 }, - /* 7642 */ { MAD_F(0x0497fa83) /* 0.287104143 */, 19 }, - /* 7643 */ { MAD_F(0x04982f0a) /* 0.287154237 */, 19 }, - /* 7644 */ { MAD_F(0x04986392) /* 0.287204332 */, 19 }, - /* 7645 */ { MAD_F(0x0498981a) /* 0.287254430 */, 19 }, - /* 7646 */ { MAD_F(0x0498cca2) /* 0.287304530 */, 19 }, - /* 7647 */ { MAD_F(0x0499012c) /* 0.287354632 */, 19 }, - - /* 7648 */ { MAD_F(0x049935b5) /* 0.287404737 */, 19 }, - /* 7649 */ { MAD_F(0x04996a40) /* 0.287454843 */, 19 }, - /* 7650 */ { MAD_F(0x04999ecb) /* 0.287504952 */, 19 }, - /* 7651 */ { MAD_F(0x0499d356) /* 0.287555063 */, 19 }, - /* 7652 */ { MAD_F(0x049a07e2) /* 0.287605176 */, 19 }, - /* 7653 */ { MAD_F(0x049a3c6f) /* 0.287655291 */, 19 }, - /* 7654 */ { MAD_F(0x049a70fc) /* 0.287705409 */, 19 }, - /* 7655 */ { MAD_F(0x049aa58a) /* 0.287755528 */, 19 }, - /* 7656 */ { MAD_F(0x049ada19) /* 0.287805650 */, 19 }, - /* 7657 */ { MAD_F(0x049b0ea8) /* 0.287855774 */, 19 }, - /* 7658 */ { MAD_F(0x049b4337) /* 0.287905900 */, 19 }, - /* 7659 */ { MAD_F(0x049b77c8) /* 0.287956028 */, 19 }, - /* 7660 */ { MAD_F(0x049bac58) /* 0.288006159 */, 19 }, - /* 7661 */ { MAD_F(0x049be0ea) /* 0.288056292 */, 19 }, - /* 7662 */ { MAD_F(0x049c157c) /* 0.288106427 */, 19 }, - /* 7663 */ { MAD_F(0x049c4a0e) /* 0.288156564 */, 19 }, - - /* 7664 */ { MAD_F(0x049c7ea1) /* 0.288206703 */, 19 }, - /* 7665 */ { MAD_F(0x049cb335) /* 0.288256844 */, 19 }, - /* 7666 */ { MAD_F(0x049ce7ca) /* 0.288306988 */, 19 }, - /* 7667 */ { MAD_F(0x049d1c5e) /* 0.288357134 */, 19 }, - /* 7668 */ { MAD_F(0x049d50f4) /* 0.288407282 */, 19 }, - /* 7669 */ { MAD_F(0x049d858a) /* 0.288457432 */, 19 }, - /* 7670 */ { MAD_F(0x049dba21) /* 0.288507584 */, 19 }, - /* 7671 */ { MAD_F(0x049deeb8) /* 0.288557739 */, 19 }, - /* 7672 */ { MAD_F(0x049e2350) /* 0.288607895 */, 19 }, - /* 7673 */ { MAD_F(0x049e57e8) /* 0.288658054 */, 19 }, - /* 7674 */ { MAD_F(0x049e8c81) /* 0.288708215 */, 19 }, - /* 7675 */ { MAD_F(0x049ec11b) /* 0.288758379 */, 19 }, - /* 7676 */ { MAD_F(0x049ef5b5) /* 0.288808544 */, 19 }, - /* 7677 */ { MAD_F(0x049f2a50) /* 0.288858712 */, 19 }, - /* 7678 */ { MAD_F(0x049f5eeb) /* 0.288908881 */, 19 }, - /* 7679 */ { MAD_F(0x049f9387) /* 0.288959053 */, 19 }, - - /* 7680 */ { MAD_F(0x049fc824) /* 0.289009227 */, 19 }, - /* 7681 */ { MAD_F(0x049ffcc1) /* 0.289059404 */, 19 }, - /* 7682 */ { MAD_F(0x04a0315e) /* 0.289109582 */, 19 }, - /* 7683 */ { MAD_F(0x04a065fd) /* 0.289159763 */, 19 }, - /* 7684 */ { MAD_F(0x04a09a9b) /* 0.289209946 */, 19 }, - /* 7685 */ { MAD_F(0x04a0cf3b) /* 0.289260131 */, 19 }, - /* 7686 */ { MAD_F(0x04a103db) /* 0.289310318 */, 19 }, - /* 7687 */ { MAD_F(0x04a1387b) /* 0.289360507 */, 19 }, - /* 7688 */ { MAD_F(0x04a16d1d) /* 0.289410699 */, 19 }, - /* 7689 */ { MAD_F(0x04a1a1be) /* 0.289460893 */, 19 }, - /* 7690 */ { MAD_F(0x04a1d661) /* 0.289511088 */, 19 }, - /* 7691 */ { MAD_F(0x04a20b04) /* 0.289561287 */, 19 }, - /* 7692 */ { MAD_F(0x04a23fa7) /* 0.289611487 */, 19 }, - /* 7693 */ { MAD_F(0x04a2744b) /* 0.289661689 */, 19 }, - /* 7694 */ { MAD_F(0x04a2a8f0) /* 0.289711894 */, 19 }, - /* 7695 */ { MAD_F(0x04a2dd95) /* 0.289762101 */, 19 }, - - /* 7696 */ { MAD_F(0x04a3123b) /* 0.289812309 */, 19 }, - /* 7697 */ { MAD_F(0x04a346e2) /* 0.289862521 */, 19 }, - /* 7698 */ { MAD_F(0x04a37b89) /* 0.289912734 */, 19 }, - /* 7699 */ { MAD_F(0x04a3b030) /* 0.289962949 */, 19 }, - /* 7700 */ { MAD_F(0x04a3e4d8) /* 0.290013167 */, 19 }, - /* 7701 */ { MAD_F(0x04a41981) /* 0.290063387 */, 19 }, - /* 7702 */ { MAD_F(0x04a44e2b) /* 0.290113609 */, 19 }, - /* 7703 */ { MAD_F(0x04a482d5) /* 0.290163833 */, 19 }, - /* 7704 */ { MAD_F(0x04a4b77f) /* 0.290214059 */, 19 }, - /* 7705 */ { MAD_F(0x04a4ec2a) /* 0.290264288 */, 19 }, - /* 7706 */ { MAD_F(0x04a520d6) /* 0.290314519 */, 19 }, - /* 7707 */ { MAD_F(0x04a55582) /* 0.290364751 */, 19 }, - /* 7708 */ { MAD_F(0x04a58a2f) /* 0.290414986 */, 19 }, - /* 7709 */ { MAD_F(0x04a5bedd) /* 0.290465224 */, 19 }, - /* 7710 */ { MAD_F(0x04a5f38b) /* 0.290515463 */, 19 }, - /* 7711 */ { MAD_F(0x04a62839) /* 0.290565705 */, 19 }, - - /* 7712 */ { MAD_F(0x04a65ce8) /* 0.290615948 */, 19 }, - /* 7713 */ { MAD_F(0x04a69198) /* 0.290666194 */, 19 }, - /* 7714 */ { MAD_F(0x04a6c648) /* 0.290716442 */, 19 }, - /* 7715 */ { MAD_F(0x04a6faf9) /* 0.290766692 */, 19 }, - /* 7716 */ { MAD_F(0x04a72fab) /* 0.290816945 */, 19 }, - /* 7717 */ { MAD_F(0x04a7645d) /* 0.290867199 */, 19 }, - /* 7718 */ { MAD_F(0x04a79910) /* 0.290917456 */, 19 }, - /* 7719 */ { MAD_F(0x04a7cdc3) /* 0.290967715 */, 19 }, - /* 7720 */ { MAD_F(0x04a80277) /* 0.291017976 */, 19 }, - /* 7721 */ { MAD_F(0x04a8372b) /* 0.291068239 */, 19 }, - /* 7722 */ { MAD_F(0x04a86be0) /* 0.291118505 */, 19 }, - /* 7723 */ { MAD_F(0x04a8a096) /* 0.291168772 */, 19 }, - /* 7724 */ { MAD_F(0x04a8d54c) /* 0.291219042 */, 19 }, - /* 7725 */ { MAD_F(0x04a90a03) /* 0.291269314 */, 19 }, - /* 7726 */ { MAD_F(0x04a93eba) /* 0.291319588 */, 19 }, - /* 7727 */ { MAD_F(0x04a97372) /* 0.291369865 */, 19 }, - - /* 7728 */ { MAD_F(0x04a9a82b) /* 0.291420143 */, 19 }, - /* 7729 */ { MAD_F(0x04a9dce4) /* 0.291470424 */, 19 }, - /* 7730 */ { MAD_F(0x04aa119d) /* 0.291520706 */, 19 }, - /* 7731 */ { MAD_F(0x04aa4658) /* 0.291570991 */, 19 }, - /* 7732 */ { MAD_F(0x04aa7b13) /* 0.291621278 */, 19 }, - /* 7733 */ { MAD_F(0x04aaafce) /* 0.291671568 */, 19 }, - /* 7734 */ { MAD_F(0x04aae48a) /* 0.291721859 */, 19 }, - /* 7735 */ { MAD_F(0x04ab1947) /* 0.291772153 */, 19 }, - /* 7736 */ { MAD_F(0x04ab4e04) /* 0.291822449 */, 19 }, - /* 7737 */ { MAD_F(0x04ab82c2) /* 0.291872747 */, 19 }, - /* 7738 */ { MAD_F(0x04abb780) /* 0.291923047 */, 19 }, - /* 7739 */ { MAD_F(0x04abec3f) /* 0.291973349 */, 19 }, - /* 7740 */ { MAD_F(0x04ac20fe) /* 0.292023653 */, 19 }, - /* 7741 */ { MAD_F(0x04ac55be) /* 0.292073960 */, 19 }, - /* 7742 */ { MAD_F(0x04ac8a7f) /* 0.292124269 */, 19 }, - /* 7743 */ { MAD_F(0x04acbf40) /* 0.292174580 */, 19 }, - - /* 7744 */ { MAD_F(0x04acf402) /* 0.292224893 */, 19 }, - /* 7745 */ { MAD_F(0x04ad28c5) /* 0.292275208 */, 19 }, - /* 7746 */ { MAD_F(0x04ad5d88) /* 0.292325526 */, 19 }, - /* 7747 */ { MAD_F(0x04ad924b) /* 0.292375845 */, 19 }, - /* 7748 */ { MAD_F(0x04adc70f) /* 0.292426167 */, 19 }, - /* 7749 */ { MAD_F(0x04adfbd4) /* 0.292476491 */, 19 }, - /* 7750 */ { MAD_F(0x04ae3099) /* 0.292526817 */, 19 }, - /* 7751 */ { MAD_F(0x04ae655f) /* 0.292577145 */, 19 }, - /* 7752 */ { MAD_F(0x04ae9a26) /* 0.292627476 */, 19 }, - /* 7753 */ { MAD_F(0x04aeceed) /* 0.292677808 */, 19 }, - /* 7754 */ { MAD_F(0x04af03b4) /* 0.292728143 */, 19 }, - /* 7755 */ { MAD_F(0x04af387d) /* 0.292778480 */, 19 }, - /* 7756 */ { MAD_F(0x04af6d45) /* 0.292828819 */, 19 }, - /* 7757 */ { MAD_F(0x04afa20f) /* 0.292879160 */, 19 }, - /* 7758 */ { MAD_F(0x04afd6d9) /* 0.292929504 */, 19 }, - /* 7759 */ { MAD_F(0x04b00ba3) /* 0.292979849 */, 19 }, - - /* 7760 */ { MAD_F(0x04b0406e) /* 0.293030197 */, 19 }, - /* 7761 */ { MAD_F(0x04b0753a) /* 0.293080547 */, 19 }, - /* 7762 */ { MAD_F(0x04b0aa06) /* 0.293130899 */, 19 }, - /* 7763 */ { MAD_F(0x04b0ded3) /* 0.293181253 */, 19 }, - /* 7764 */ { MAD_F(0x04b113a1) /* 0.293231610 */, 19 }, - /* 7765 */ { MAD_F(0x04b1486f) /* 0.293281968 */, 19 }, - /* 7766 */ { MAD_F(0x04b17d3d) /* 0.293332329 */, 19 }, - /* 7767 */ { MAD_F(0x04b1b20c) /* 0.293382692 */, 19 }, - /* 7768 */ { MAD_F(0x04b1e6dc) /* 0.293433057 */, 19 }, - /* 7769 */ { MAD_F(0x04b21bad) /* 0.293483424 */, 19 }, - /* 7770 */ { MAD_F(0x04b2507d) /* 0.293533794 */, 19 }, - /* 7771 */ { MAD_F(0x04b2854f) /* 0.293584165 */, 19 }, - /* 7772 */ { MAD_F(0x04b2ba21) /* 0.293634539 */, 19 }, - /* 7773 */ { MAD_F(0x04b2eef4) /* 0.293684915 */, 19 }, - /* 7774 */ { MAD_F(0x04b323c7) /* 0.293735293 */, 19 }, - /* 7775 */ { MAD_F(0x04b3589b) /* 0.293785673 */, 19 }, - - /* 7776 */ { MAD_F(0x04b38d6f) /* 0.293836055 */, 19 }, - /* 7777 */ { MAD_F(0x04b3c244) /* 0.293886440 */, 19 }, - /* 7778 */ { MAD_F(0x04b3f71a) /* 0.293936826 */, 19 }, - /* 7779 */ { MAD_F(0x04b42bf0) /* 0.293987215 */, 19 }, - /* 7780 */ { MAD_F(0x04b460c7) /* 0.294037606 */, 19 }, - /* 7781 */ { MAD_F(0x04b4959e) /* 0.294087999 */, 19 }, - /* 7782 */ { MAD_F(0x04b4ca76) /* 0.294138395 */, 19 }, - /* 7783 */ { MAD_F(0x04b4ff4e) /* 0.294188792 */, 19 }, - /* 7784 */ { MAD_F(0x04b53427) /* 0.294239192 */, 19 }, - /* 7785 */ { MAD_F(0x04b56901) /* 0.294289593 */, 19 }, - /* 7786 */ { MAD_F(0x04b59ddb) /* 0.294339997 */, 19 }, - /* 7787 */ { MAD_F(0x04b5d2b6) /* 0.294390403 */, 19 }, - /* 7788 */ { MAD_F(0x04b60791) /* 0.294440812 */, 19 }, - /* 7789 */ { MAD_F(0x04b63c6d) /* 0.294491222 */, 19 }, - /* 7790 */ { MAD_F(0x04b6714a) /* 0.294541635 */, 19 }, - /* 7791 */ { MAD_F(0x04b6a627) /* 0.294592049 */, 19 }, - - /* 7792 */ { MAD_F(0x04b6db05) /* 0.294642466 */, 19 }, - /* 7793 */ { MAD_F(0x04b70fe3) /* 0.294692885 */, 19 }, - /* 7794 */ { MAD_F(0x04b744c2) /* 0.294743306 */, 19 }, - /* 7795 */ { MAD_F(0x04b779a1) /* 0.294793730 */, 19 }, - /* 7796 */ { MAD_F(0x04b7ae81) /* 0.294844155 */, 19 }, - /* 7797 */ { MAD_F(0x04b7e362) /* 0.294894583 */, 19 }, - /* 7798 */ { MAD_F(0x04b81843) /* 0.294945013 */, 19 }, - /* 7799 */ { MAD_F(0x04b84d24) /* 0.294995445 */, 19 }, - /* 7800 */ { MAD_F(0x04b88207) /* 0.295045879 */, 19 }, - /* 7801 */ { MAD_F(0x04b8b6ea) /* 0.295096315 */, 19 }, - /* 7802 */ { MAD_F(0x04b8ebcd) /* 0.295146753 */, 19 }, - /* 7803 */ { MAD_F(0x04b920b1) /* 0.295197194 */, 19 }, - /* 7804 */ { MAD_F(0x04b95596) /* 0.295247637 */, 19 }, - /* 7805 */ { MAD_F(0x04b98a7b) /* 0.295298082 */, 19 }, - /* 7806 */ { MAD_F(0x04b9bf61) /* 0.295348529 */, 19 }, - /* 7807 */ { MAD_F(0x04b9f447) /* 0.295398978 */, 19 }, - - /* 7808 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 19 }, - /* 7809 */ { MAD_F(0x04ba5e16) /* 0.295499883 */, 19 }, - /* 7810 */ { MAD_F(0x04ba92fe) /* 0.295550338 */, 19 }, - /* 7811 */ { MAD_F(0x04bac7e6) /* 0.295600796 */, 19 }, - /* 7812 */ { MAD_F(0x04bafcd0) /* 0.295651256 */, 19 }, - /* 7813 */ { MAD_F(0x04bb31b9) /* 0.295701718 */, 19 }, - /* 7814 */ { MAD_F(0x04bb66a4) /* 0.295752183 */, 19 }, - /* 7815 */ { MAD_F(0x04bb9b8f) /* 0.295802649 */, 19 }, - /* 7816 */ { MAD_F(0x04bbd07a) /* 0.295853118 */, 19 }, - /* 7817 */ { MAD_F(0x04bc0566) /* 0.295903588 */, 19 }, - /* 7818 */ { MAD_F(0x04bc3a53) /* 0.295954061 */, 19 }, - /* 7819 */ { MAD_F(0x04bc6f40) /* 0.296004536 */, 19 }, - /* 7820 */ { MAD_F(0x04bca42e) /* 0.296055013 */, 19 }, - /* 7821 */ { MAD_F(0x04bcd91d) /* 0.296105493 */, 19 }, - /* 7822 */ { MAD_F(0x04bd0e0c) /* 0.296155974 */, 19 }, - /* 7823 */ { MAD_F(0x04bd42fb) /* 0.296206458 */, 19 }, - - /* 7824 */ { MAD_F(0x04bd77ec) /* 0.296256944 */, 19 }, - /* 7825 */ { MAD_F(0x04bdacdc) /* 0.296307432 */, 19 }, - /* 7826 */ { MAD_F(0x04bde1ce) /* 0.296357922 */, 19 }, - /* 7827 */ { MAD_F(0x04be16c0) /* 0.296408414 */, 19 }, - /* 7828 */ { MAD_F(0x04be4bb2) /* 0.296458908 */, 19 }, - /* 7829 */ { MAD_F(0x04be80a5) /* 0.296509405 */, 19 }, - /* 7830 */ { MAD_F(0x04beb599) /* 0.296559904 */, 19 }, - /* 7831 */ { MAD_F(0x04beea8d) /* 0.296610404 */, 19 }, - /* 7832 */ { MAD_F(0x04bf1f82) /* 0.296660907 */, 19 }, - /* 7833 */ { MAD_F(0x04bf5477) /* 0.296711413 */, 19 }, - /* 7834 */ { MAD_F(0x04bf896d) /* 0.296761920 */, 19 }, - /* 7835 */ { MAD_F(0x04bfbe64) /* 0.296812429 */, 19 }, - /* 7836 */ { MAD_F(0x04bff35b) /* 0.296862941 */, 19 }, - /* 7837 */ { MAD_F(0x04c02852) /* 0.296913455 */, 19 }, - /* 7838 */ { MAD_F(0x04c05d4b) /* 0.296963971 */, 19 }, - /* 7839 */ { MAD_F(0x04c09243) /* 0.297014489 */, 19 }, - - /* 7840 */ { MAD_F(0x04c0c73d) /* 0.297065009 */, 19 }, - /* 7841 */ { MAD_F(0x04c0fc37) /* 0.297115531 */, 19 }, - /* 7842 */ { MAD_F(0x04c13131) /* 0.297166056 */, 19 }, - /* 7843 */ { MAD_F(0x04c1662d) /* 0.297216582 */, 19 }, - /* 7844 */ { MAD_F(0x04c19b28) /* 0.297267111 */, 19 }, - /* 7845 */ { MAD_F(0x04c1d025) /* 0.297317642 */, 19 }, - /* 7846 */ { MAD_F(0x04c20521) /* 0.297368175 */, 19 }, - /* 7847 */ { MAD_F(0x04c23a1f) /* 0.297418710 */, 19 }, - /* 7848 */ { MAD_F(0x04c26f1d) /* 0.297469248 */, 19 }, - /* 7849 */ { MAD_F(0x04c2a41b) /* 0.297519787 */, 19 }, - /* 7850 */ { MAD_F(0x04c2d91b) /* 0.297570329 */, 19 }, - /* 7851 */ { MAD_F(0x04c30e1a) /* 0.297620873 */, 19 }, - /* 7852 */ { MAD_F(0x04c3431b) /* 0.297671418 */, 19 }, - /* 7853 */ { MAD_F(0x04c3781c) /* 0.297721967 */, 19 }, - /* 7854 */ { MAD_F(0x04c3ad1d) /* 0.297772517 */, 19 }, - /* 7855 */ { MAD_F(0x04c3e21f) /* 0.297823069 */, 19 }, - - /* 7856 */ { MAD_F(0x04c41722) /* 0.297873624 */, 19 }, - /* 7857 */ { MAD_F(0x04c44c25) /* 0.297924180 */, 19 }, - /* 7858 */ { MAD_F(0x04c48129) /* 0.297974739 */, 19 }, - /* 7859 */ { MAD_F(0x04c4b62d) /* 0.298025300 */, 19 }, - /* 7860 */ { MAD_F(0x04c4eb32) /* 0.298075863 */, 19 }, - /* 7861 */ { MAD_F(0x04c52038) /* 0.298126429 */, 19 }, - /* 7862 */ { MAD_F(0x04c5553e) /* 0.298176996 */, 19 }, - /* 7863 */ { MAD_F(0x04c58a44) /* 0.298227565 */, 19 }, - /* 7864 */ { MAD_F(0x04c5bf4c) /* 0.298278137 */, 19 }, - /* 7865 */ { MAD_F(0x04c5f453) /* 0.298328711 */, 19 }, - /* 7866 */ { MAD_F(0x04c6295c) /* 0.298379287 */, 19 }, - /* 7867 */ { MAD_F(0x04c65e65) /* 0.298429865 */, 19 }, - /* 7868 */ { MAD_F(0x04c6936e) /* 0.298480445 */, 19 }, - /* 7869 */ { MAD_F(0x04c6c878) /* 0.298531028 */, 19 }, - /* 7870 */ { MAD_F(0x04c6fd83) /* 0.298581612 */, 19 }, - /* 7871 */ { MAD_F(0x04c7328e) /* 0.298632199 */, 19 }, - - /* 7872 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 19 }, - /* 7873 */ { MAD_F(0x04c79ca7) /* 0.298733379 */, 19 }, - /* 7874 */ { MAD_F(0x04c7d1b4) /* 0.298783972 */, 19 }, - /* 7875 */ { MAD_F(0x04c806c1) /* 0.298834567 */, 19 }, - /* 7876 */ { MAD_F(0x04c83bcf) /* 0.298885165 */, 19 }, - /* 7877 */ { MAD_F(0x04c870de) /* 0.298935764 */, 19 }, - /* 7878 */ { MAD_F(0x04c8a5ed) /* 0.298986366 */, 19 }, - /* 7879 */ { MAD_F(0x04c8dafd) /* 0.299036970 */, 19 }, - /* 7880 */ { MAD_F(0x04c9100d) /* 0.299087576 */, 19 }, - /* 7881 */ { MAD_F(0x04c9451e) /* 0.299138184 */, 19 }, - /* 7882 */ { MAD_F(0x04c97a30) /* 0.299188794 */, 19 }, - /* 7883 */ { MAD_F(0x04c9af42) /* 0.299239406 */, 19 }, - /* 7884 */ { MAD_F(0x04c9e455) /* 0.299290021 */, 19 }, - /* 7885 */ { MAD_F(0x04ca1968) /* 0.299340638 */, 19 }, - /* 7886 */ { MAD_F(0x04ca4e7c) /* 0.299391256 */, 19 }, - /* 7887 */ { MAD_F(0x04ca8391) /* 0.299441877 */, 19 }, - - /* 7888 */ { MAD_F(0x04cab8a6) /* 0.299492500 */, 19 }, - /* 7889 */ { MAD_F(0x04caedbb) /* 0.299543126 */, 19 }, - /* 7890 */ { MAD_F(0x04cb22d1) /* 0.299593753 */, 19 }, - /* 7891 */ { MAD_F(0x04cb57e8) /* 0.299644382 */, 19 }, - /* 7892 */ { MAD_F(0x04cb8d00) /* 0.299695014 */, 19 }, - /* 7893 */ { MAD_F(0x04cbc217) /* 0.299745648 */, 19 }, - /* 7894 */ { MAD_F(0x04cbf730) /* 0.299796284 */, 19 }, - /* 7895 */ { MAD_F(0x04cc2c49) /* 0.299846922 */, 19 }, - /* 7896 */ { MAD_F(0x04cc6163) /* 0.299897562 */, 19 }, - /* 7897 */ { MAD_F(0x04cc967d) /* 0.299948204 */, 19 }, - /* 7898 */ { MAD_F(0x04cccb98) /* 0.299998849 */, 19 }, - /* 7899 */ { MAD_F(0x04cd00b3) /* 0.300049495 */, 19 }, - /* 7900 */ { MAD_F(0x04cd35cf) /* 0.300100144 */, 19 }, - /* 7901 */ { MAD_F(0x04cd6aeb) /* 0.300150795 */, 19 }, - /* 7902 */ { MAD_F(0x04cda008) /* 0.300201448 */, 19 }, - /* 7903 */ { MAD_F(0x04cdd526) /* 0.300252103 */, 19 }, - - /* 7904 */ { MAD_F(0x04ce0a44) /* 0.300302761 */, 19 }, - /* 7905 */ { MAD_F(0x04ce3f63) /* 0.300353420 */, 19 }, - /* 7906 */ { MAD_F(0x04ce7482) /* 0.300404082 */, 19 }, - /* 7907 */ { MAD_F(0x04cea9a2) /* 0.300454745 */, 19 }, - /* 7908 */ { MAD_F(0x04cedec3) /* 0.300505411 */, 19 }, - /* 7909 */ { MAD_F(0x04cf13e4) /* 0.300556079 */, 19 }, - /* 7910 */ { MAD_F(0x04cf4906) /* 0.300606749 */, 19 }, - /* 7911 */ { MAD_F(0x04cf7e28) /* 0.300657421 */, 19 }, - /* 7912 */ { MAD_F(0x04cfb34b) /* 0.300708096 */, 19 }, - /* 7913 */ { MAD_F(0x04cfe86e) /* 0.300758772 */, 19 }, - /* 7914 */ { MAD_F(0x04d01d92) /* 0.300809451 */, 19 }, - /* 7915 */ { MAD_F(0x04d052b6) /* 0.300860132 */, 19 }, - /* 7916 */ { MAD_F(0x04d087db) /* 0.300910815 */, 19 }, - /* 7917 */ { MAD_F(0x04d0bd01) /* 0.300961500 */, 19 }, - /* 7918 */ { MAD_F(0x04d0f227) /* 0.301012187 */, 19 }, - /* 7919 */ { MAD_F(0x04d1274e) /* 0.301062876 */, 19 }, - - /* 7920 */ { MAD_F(0x04d15c76) /* 0.301113568 */, 19 }, - /* 7921 */ { MAD_F(0x04d1919e) /* 0.301164261 */, 19 }, - /* 7922 */ { MAD_F(0x04d1c6c6) /* 0.301214957 */, 19 }, - /* 7923 */ { MAD_F(0x04d1fbef) /* 0.301265655 */, 19 }, - /* 7924 */ { MAD_F(0x04d23119) /* 0.301316355 */, 19 }, - /* 7925 */ { MAD_F(0x04d26643) /* 0.301367057 */, 19 }, - /* 7926 */ { MAD_F(0x04d29b6e) /* 0.301417761 */, 19 }, - /* 7927 */ { MAD_F(0x04d2d099) /* 0.301468468 */, 19 }, - /* 7928 */ { MAD_F(0x04d305c5) /* 0.301519176 */, 19 }, - /* 7929 */ { MAD_F(0x04d33af2) /* 0.301569887 */, 19 }, - /* 7930 */ { MAD_F(0x04d3701f) /* 0.301620599 */, 19 }, - /* 7931 */ { MAD_F(0x04d3a54d) /* 0.301671314 */, 19 }, - /* 7932 */ { MAD_F(0x04d3da7b) /* 0.301722031 */, 19 }, - /* 7933 */ { MAD_F(0x04d40faa) /* 0.301772751 */, 19 }, - /* 7934 */ { MAD_F(0x04d444d9) /* 0.301823472 */, 19 }, - /* 7935 */ { MAD_F(0x04d47a09) /* 0.301874195 */, 19 }, - - /* 7936 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 19 }, - /* 7937 */ { MAD_F(0x04d4e46b) /* 0.301975649 */, 19 }, - /* 7938 */ { MAD_F(0x04d5199c) /* 0.302026378 */, 19 }, - /* 7939 */ { MAD_F(0x04d54ecf) /* 0.302077110 */, 19 }, - /* 7940 */ { MAD_F(0x04d58401) /* 0.302127845 */, 19 }, - /* 7941 */ { MAD_F(0x04d5b935) /* 0.302178581 */, 19 }, - /* 7942 */ { MAD_F(0x04d5ee69) /* 0.302229319 */, 19 }, - /* 7943 */ { MAD_F(0x04d6239d) /* 0.302280060 */, 19 }, - /* 7944 */ { MAD_F(0x04d658d2) /* 0.302330802 */, 19 }, - /* 7945 */ { MAD_F(0x04d68e08) /* 0.302381547 */, 19 }, - /* 7946 */ { MAD_F(0x04d6c33e) /* 0.302432294 */, 19 }, - /* 7947 */ { MAD_F(0x04d6f875) /* 0.302483043 */, 19 }, - /* 7948 */ { MAD_F(0x04d72dad) /* 0.302533794 */, 19 }, - /* 7949 */ { MAD_F(0x04d762e5) /* 0.302584547 */, 19 }, - /* 7950 */ { MAD_F(0x04d7981d) /* 0.302635303 */, 19 }, - /* 7951 */ { MAD_F(0x04d7cd56) /* 0.302686060 */, 19 }, - - /* 7952 */ { MAD_F(0x04d80290) /* 0.302736820 */, 19 }, - /* 7953 */ { MAD_F(0x04d837ca) /* 0.302787581 */, 19 }, - /* 7954 */ { MAD_F(0x04d86d05) /* 0.302838345 */, 19 }, - /* 7955 */ { MAD_F(0x04d8a240) /* 0.302889111 */, 19 }, - /* 7956 */ { MAD_F(0x04d8d77c) /* 0.302939879 */, 19 }, - /* 7957 */ { MAD_F(0x04d90cb9) /* 0.302990650 */, 19 }, - /* 7958 */ { MAD_F(0x04d941f6) /* 0.303041422 */, 19 }, - /* 7959 */ { MAD_F(0x04d97734) /* 0.303092197 */, 19 }, - /* 7960 */ { MAD_F(0x04d9ac72) /* 0.303142973 */, 19 }, - /* 7961 */ { MAD_F(0x04d9e1b1) /* 0.303193752 */, 19 }, - /* 7962 */ { MAD_F(0x04da16f0) /* 0.303244533 */, 19 }, - /* 7963 */ { MAD_F(0x04da4c30) /* 0.303295316 */, 19 }, - /* 7964 */ { MAD_F(0x04da8171) /* 0.303346101 */, 19 }, - /* 7965 */ { MAD_F(0x04dab6b2) /* 0.303396889 */, 19 }, - /* 7966 */ { MAD_F(0x04daebf4) /* 0.303447678 */, 19 }, - /* 7967 */ { MAD_F(0x04db2136) /* 0.303498469 */, 19 }, - - /* 7968 */ { MAD_F(0x04db5679) /* 0.303549263 */, 19 }, - /* 7969 */ { MAD_F(0x04db8bbc) /* 0.303600059 */, 19 }, - /* 7970 */ { MAD_F(0x04dbc100) /* 0.303650857 */, 19 }, - /* 7971 */ { MAD_F(0x04dbf644) /* 0.303701657 */, 19 }, - /* 7972 */ { MAD_F(0x04dc2b8a) /* 0.303752459 */, 19 }, - /* 7973 */ { MAD_F(0x04dc60cf) /* 0.303803263 */, 19 }, - /* 7974 */ { MAD_F(0x04dc9616) /* 0.303854070 */, 19 }, - /* 7975 */ { MAD_F(0x04dccb5c) /* 0.303904878 */, 19 }, - /* 7976 */ { MAD_F(0x04dd00a4) /* 0.303955689 */, 19 }, - /* 7977 */ { MAD_F(0x04dd35ec) /* 0.304006502 */, 19 }, - /* 7978 */ { MAD_F(0x04dd6b34) /* 0.304057317 */, 19 }, - /* 7979 */ { MAD_F(0x04dda07d) /* 0.304108134 */, 19 }, - /* 7980 */ { MAD_F(0x04ddd5c7) /* 0.304158953 */, 19 }, - /* 7981 */ { MAD_F(0x04de0b11) /* 0.304209774 */, 19 }, - /* 7982 */ { MAD_F(0x04de405c) /* 0.304260597 */, 19 }, - /* 7983 */ { MAD_F(0x04de75a7) /* 0.304311423 */, 19 }, - - /* 7984 */ { MAD_F(0x04deaaf3) /* 0.304362251 */, 19 }, - /* 7985 */ { MAD_F(0x04dee040) /* 0.304413080 */, 19 }, - /* 7986 */ { MAD_F(0x04df158d) /* 0.304463912 */, 19 }, - /* 7987 */ { MAD_F(0x04df4adb) /* 0.304514746 */, 19 }, - /* 7988 */ { MAD_F(0x04df8029) /* 0.304565582 */, 19 }, - /* 7989 */ { MAD_F(0x04dfb578) /* 0.304616421 */, 19 }, - /* 7990 */ { MAD_F(0x04dfeac7) /* 0.304667261 */, 19 }, - /* 7991 */ { MAD_F(0x04e02017) /* 0.304718103 */, 19 }, - /* 7992 */ { MAD_F(0x04e05567) /* 0.304768948 */, 19 }, - /* 7993 */ { MAD_F(0x04e08ab8) /* 0.304819795 */, 19 }, - /* 7994 */ { MAD_F(0x04e0c00a) /* 0.304870644 */, 19 }, - /* 7995 */ { MAD_F(0x04e0f55c) /* 0.304921495 */, 19 }, - /* 7996 */ { MAD_F(0x04e12aaf) /* 0.304972348 */, 19 }, - /* 7997 */ { MAD_F(0x04e16002) /* 0.305023203 */, 19 }, - /* 7998 */ { MAD_F(0x04e19556) /* 0.305074060 */, 19 }, - /* 7999 */ { MAD_F(0x04e1caab) /* 0.305124920 */, 19 }, - - /* 8000 */ { MAD_F(0x04e20000) /* 0.305175781 */, 19 }, - /* 8001 */ { MAD_F(0x04e23555) /* 0.305226645 */, 19 }, - /* 8002 */ { MAD_F(0x04e26aac) /* 0.305277511 */, 19 }, - /* 8003 */ { MAD_F(0x04e2a002) /* 0.305328379 */, 19 }, - /* 8004 */ { MAD_F(0x04e2d55a) /* 0.305379249 */, 19 }, - /* 8005 */ { MAD_F(0x04e30ab2) /* 0.305430121 */, 19 }, - /* 8006 */ { MAD_F(0x04e3400a) /* 0.305480995 */, 19 }, - /* 8007 */ { MAD_F(0x04e37563) /* 0.305531872 */, 19 }, - /* 8008 */ { MAD_F(0x04e3aabd) /* 0.305582750 */, 19 }, - /* 8009 */ { MAD_F(0x04e3e017) /* 0.305633631 */, 19 }, - /* 8010 */ { MAD_F(0x04e41572) /* 0.305684513 */, 19 }, - /* 8011 */ { MAD_F(0x04e44acd) /* 0.305735398 */, 19 }, - /* 8012 */ { MAD_F(0x04e48029) /* 0.305786285 */, 19 }, - /* 8013 */ { MAD_F(0x04e4b585) /* 0.305837174 */, 19 }, - /* 8014 */ { MAD_F(0x04e4eae2) /* 0.305888066 */, 19 }, - /* 8015 */ { MAD_F(0x04e52040) /* 0.305938959 */, 19 }, - - /* 8016 */ { MAD_F(0x04e5559e) /* 0.305989854 */, 19 }, - /* 8017 */ { MAD_F(0x04e58afd) /* 0.306040752 */, 19 }, - /* 8018 */ { MAD_F(0x04e5c05c) /* 0.306091652 */, 19 }, - /* 8019 */ { MAD_F(0x04e5f5bc) /* 0.306142554 */, 19 }, - /* 8020 */ { MAD_F(0x04e62b1c) /* 0.306193457 */, 19 }, - /* 8021 */ { MAD_F(0x04e6607d) /* 0.306244364 */, 19 }, - /* 8022 */ { MAD_F(0x04e695df) /* 0.306295272 */, 19 }, - /* 8023 */ { MAD_F(0x04e6cb41) /* 0.306346182 */, 19 }, - /* 8024 */ { MAD_F(0x04e700a3) /* 0.306397094 */, 19 }, - /* 8025 */ { MAD_F(0x04e73607) /* 0.306448009 */, 19 }, - /* 8026 */ { MAD_F(0x04e76b6b) /* 0.306498925 */, 19 }, - /* 8027 */ { MAD_F(0x04e7a0cf) /* 0.306549844 */, 19 }, - /* 8028 */ { MAD_F(0x04e7d634) /* 0.306600765 */, 19 }, - /* 8029 */ { MAD_F(0x04e80b99) /* 0.306651688 */, 19 }, - /* 8030 */ { MAD_F(0x04e84100) /* 0.306702613 */, 19 }, - /* 8031 */ { MAD_F(0x04e87666) /* 0.306753540 */, 19 }, - - /* 8032 */ { MAD_F(0x04e8abcd) /* 0.306804470 */, 19 }, - /* 8033 */ { MAD_F(0x04e8e135) /* 0.306855401 */, 19 }, - /* 8034 */ { MAD_F(0x04e9169e) /* 0.306906334 */, 19 }, - /* 8035 */ { MAD_F(0x04e94c07) /* 0.306957270 */, 19 }, - /* 8036 */ { MAD_F(0x04e98170) /* 0.307008208 */, 19 }, - /* 8037 */ { MAD_F(0x04e9b6da) /* 0.307059148 */, 19 }, - /* 8038 */ { MAD_F(0x04e9ec45) /* 0.307110090 */, 19 }, - /* 8039 */ { MAD_F(0x04ea21b0) /* 0.307161034 */, 19 }, - /* 8040 */ { MAD_F(0x04ea571c) /* 0.307211980 */, 19 }, - /* 8041 */ { MAD_F(0x04ea8c88) /* 0.307262928 */, 19 }, - /* 8042 */ { MAD_F(0x04eac1f5) /* 0.307313879 */, 19 }, - /* 8043 */ { MAD_F(0x04eaf762) /* 0.307364831 */, 19 }, - /* 8044 */ { MAD_F(0x04eb2cd0) /* 0.307415786 */, 19 }, - /* 8045 */ { MAD_F(0x04eb623f) /* 0.307466743 */, 19 }, - /* 8046 */ { MAD_F(0x04eb97ae) /* 0.307517702 */, 19 }, - /* 8047 */ { MAD_F(0x04ebcd1e) /* 0.307568663 */, 19 }, - - /* 8048 */ { MAD_F(0x04ec028e) /* 0.307619626 */, 19 }, - /* 8049 */ { MAD_F(0x04ec37ff) /* 0.307670591 */, 19 }, - /* 8050 */ { MAD_F(0x04ec6d71) /* 0.307721558 */, 19 }, - /* 8051 */ { MAD_F(0x04eca2e3) /* 0.307772528 */, 19 }, - /* 8052 */ { MAD_F(0x04ecd855) /* 0.307823499 */, 19 }, - /* 8053 */ { MAD_F(0x04ed0dc8) /* 0.307874473 */, 19 }, - /* 8054 */ { MAD_F(0x04ed433c) /* 0.307925449 */, 19 }, - /* 8055 */ { MAD_F(0x04ed78b0) /* 0.307976426 */, 19 }, - /* 8056 */ { MAD_F(0x04edae25) /* 0.308027406 */, 19 }, - /* 8057 */ { MAD_F(0x04ede39a) /* 0.308078389 */, 19 }, - /* 8058 */ { MAD_F(0x04ee1910) /* 0.308129373 */, 19 }, - /* 8059 */ { MAD_F(0x04ee4e87) /* 0.308180359 */, 19 }, - /* 8060 */ { MAD_F(0x04ee83fe) /* 0.308231347 */, 19 }, - /* 8061 */ { MAD_F(0x04eeb976) /* 0.308282338 */, 19 }, - /* 8062 */ { MAD_F(0x04eeeeee) /* 0.308333331 */, 19 }, - /* 8063 */ { MAD_F(0x04ef2467) /* 0.308384325 */, 19 }, - - /* 8064 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 19 }, - /* 8065 */ { MAD_F(0x04ef8f5a) /* 0.308486321 */, 19 }, - /* 8066 */ { MAD_F(0x04efc4d5) /* 0.308537322 */, 19 }, - /* 8067 */ { MAD_F(0x04effa50) /* 0.308588325 */, 19 }, - /* 8068 */ { MAD_F(0x04f02fcb) /* 0.308639331 */, 19 }, - /* 8069 */ { MAD_F(0x04f06547) /* 0.308690338 */, 19 }, - /* 8070 */ { MAD_F(0x04f09ac4) /* 0.308741348 */, 19 }, - /* 8071 */ { MAD_F(0x04f0d041) /* 0.308792359 */, 19 }, - /* 8072 */ { MAD_F(0x04f105bf) /* 0.308843373 */, 19 }, - /* 8073 */ { MAD_F(0x04f13b3e) /* 0.308894389 */, 19 }, - /* 8074 */ { MAD_F(0x04f170bd) /* 0.308945407 */, 19 }, - /* 8075 */ { MAD_F(0x04f1a63c) /* 0.308996427 */, 19 }, - /* 8076 */ { MAD_F(0x04f1dbbd) /* 0.309047449 */, 19 }, - /* 8077 */ { MAD_F(0x04f2113d) /* 0.309098473 */, 19 }, - /* 8078 */ { MAD_F(0x04f246bf) /* 0.309149499 */, 19 }, - /* 8079 */ { MAD_F(0x04f27c40) /* 0.309200528 */, 19 }, - - /* 8080 */ { MAD_F(0x04f2b1c3) /* 0.309251558 */, 19 }, - /* 8081 */ { MAD_F(0x04f2e746) /* 0.309302591 */, 19 }, - /* 8082 */ { MAD_F(0x04f31cc9) /* 0.309353626 */, 19 }, - /* 8083 */ { MAD_F(0x04f3524d) /* 0.309404663 */, 19 }, - /* 8084 */ { MAD_F(0x04f387d2) /* 0.309455702 */, 19 }, - /* 8085 */ { MAD_F(0x04f3bd57) /* 0.309506743 */, 19 }, - /* 8086 */ { MAD_F(0x04f3f2dd) /* 0.309557786 */, 19 }, - /* 8087 */ { MAD_F(0x04f42864) /* 0.309608831 */, 19 }, - /* 8088 */ { MAD_F(0x04f45dea) /* 0.309659879 */, 19 }, - /* 8089 */ { MAD_F(0x04f49372) /* 0.309710928 */, 19 }, - /* 8090 */ { MAD_F(0x04f4c8fa) /* 0.309761980 */, 19 }, - /* 8091 */ { MAD_F(0x04f4fe83) /* 0.309813033 */, 19 }, - /* 8092 */ { MAD_F(0x04f5340c) /* 0.309864089 */, 19 }, - /* 8093 */ { MAD_F(0x04f56996) /* 0.309915147 */, 19 }, - /* 8094 */ { MAD_F(0x04f59f20) /* 0.309966207 */, 19 }, - /* 8095 */ { MAD_F(0x04f5d4ab) /* 0.310017269 */, 19 }, - - /* 8096 */ { MAD_F(0x04f60a36) /* 0.310068333 */, 19 }, - /* 8097 */ { MAD_F(0x04f63fc2) /* 0.310119400 */, 19 }, - /* 8098 */ { MAD_F(0x04f6754f) /* 0.310170468 */, 19 }, - /* 8099 */ { MAD_F(0x04f6aadc) /* 0.310221539 */, 19 }, - /* 8100 */ { MAD_F(0x04f6e06a) /* 0.310272611 */, 19 }, - /* 8101 */ { MAD_F(0x04f715f8) /* 0.310323686 */, 19 }, - /* 8102 */ { MAD_F(0x04f74b87) /* 0.310374763 */, 19 }, - /* 8103 */ { MAD_F(0x04f78116) /* 0.310425842 */, 19 }, - /* 8104 */ { MAD_F(0x04f7b6a6) /* 0.310476923 */, 19 }, - /* 8105 */ { MAD_F(0x04f7ec37) /* 0.310528006 */, 19 }, - /* 8106 */ { MAD_F(0x04f821c8) /* 0.310579091 */, 19 }, - /* 8107 */ { MAD_F(0x04f85759) /* 0.310630179 */, 19 }, - /* 8108 */ { MAD_F(0x04f88cec) /* 0.310681268 */, 19 }, - /* 8109 */ { MAD_F(0x04f8c27e) /* 0.310732360 */, 19 }, - /* 8110 */ { MAD_F(0x04f8f812) /* 0.310783453 */, 19 }, - /* 8111 */ { MAD_F(0x04f92da6) /* 0.310834549 */, 19 }, - - /* 8112 */ { MAD_F(0x04f9633a) /* 0.310885647 */, 19 }, - /* 8113 */ { MAD_F(0x04f998cf) /* 0.310936747 */, 19 }, - /* 8114 */ { MAD_F(0x04f9ce65) /* 0.310987849 */, 19 }, - /* 8115 */ { MAD_F(0x04fa03fb) /* 0.311038953 */, 19 }, - /* 8116 */ { MAD_F(0x04fa3992) /* 0.311090059 */, 19 }, - /* 8117 */ { MAD_F(0x04fa6f29) /* 0.311141168 */, 19 }, - /* 8118 */ { MAD_F(0x04faa4c1) /* 0.311192278 */, 19 }, - /* 8119 */ { MAD_F(0x04fada59) /* 0.311243390 */, 19 }, - /* 8120 */ { MAD_F(0x04fb0ff2) /* 0.311294505 */, 19 }, - /* 8121 */ { MAD_F(0x04fb458c) /* 0.311345622 */, 19 }, - /* 8122 */ { MAD_F(0x04fb7b26) /* 0.311396741 */, 19 }, - /* 8123 */ { MAD_F(0x04fbb0c1) /* 0.311447862 */, 19 }, - /* 8124 */ { MAD_F(0x04fbe65c) /* 0.311498985 */, 19 }, - /* 8125 */ { MAD_F(0x04fc1bf8) /* 0.311550110 */, 19 }, - /* 8126 */ { MAD_F(0x04fc5194) /* 0.311601237 */, 19 }, - /* 8127 */ { MAD_F(0x04fc8731) /* 0.311652366 */, 19 }, - - /* 8128 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 19 }, - /* 8129 */ { MAD_F(0x04fcf26c) /* 0.311754631 */, 19 }, - /* 8130 */ { MAD_F(0x04fd280b) /* 0.311805767 */, 19 }, - /* 8131 */ { MAD_F(0x04fd5daa) /* 0.311856905 */, 19 }, - /* 8132 */ { MAD_F(0x04fd934a) /* 0.311908044 */, 19 }, - /* 8133 */ { MAD_F(0x04fdc8ea) /* 0.311959186 */, 19 }, - /* 8134 */ { MAD_F(0x04fdfe8b) /* 0.312010330 */, 19 }, - /* 8135 */ { MAD_F(0x04fe342c) /* 0.312061476 */, 19 }, - /* 8136 */ { MAD_F(0x04fe69ce) /* 0.312112625 */, 19 }, - /* 8137 */ { MAD_F(0x04fe9f71) /* 0.312163775 */, 19 }, - /* 8138 */ { MAD_F(0x04fed514) /* 0.312214927 */, 19 }, - /* 8139 */ { MAD_F(0x04ff0ab8) /* 0.312266082 */, 19 }, - /* 8140 */ { MAD_F(0x04ff405c) /* 0.312317238 */, 19 }, - /* 8141 */ { MAD_F(0x04ff7601) /* 0.312368397 */, 19 }, - /* 8142 */ { MAD_F(0x04ffaba6) /* 0.312419558 */, 19 }, - /* 8143 */ { MAD_F(0x04ffe14c) /* 0.312470720 */, 19 }, - - /* 8144 */ { MAD_F(0x050016f3) /* 0.312521885 */, 19 }, - /* 8145 */ { MAD_F(0x05004c9a) /* 0.312573052 */, 19 }, - /* 8146 */ { MAD_F(0x05008241) /* 0.312624222 */, 19 }, - /* 8147 */ { MAD_F(0x0500b7e9) /* 0.312675393 */, 19 }, - /* 8148 */ { MAD_F(0x0500ed92) /* 0.312726566 */, 19 }, - /* 8149 */ { MAD_F(0x0501233b) /* 0.312777742 */, 19 }, - /* 8150 */ { MAD_F(0x050158e5) /* 0.312828919 */, 19 }, - /* 8151 */ { MAD_F(0x05018e90) /* 0.312880099 */, 19 }, - /* 8152 */ { MAD_F(0x0501c43b) /* 0.312931280 */, 19 }, - /* 8153 */ { MAD_F(0x0501f9e6) /* 0.312982464 */, 19 }, - /* 8154 */ { MAD_F(0x05022f92) /* 0.313033650 */, 19 }, - /* 8155 */ { MAD_F(0x0502653f) /* 0.313084838 */, 19 }, - /* 8156 */ { MAD_F(0x05029aec) /* 0.313136028 */, 19 }, - /* 8157 */ { MAD_F(0x0502d09a) /* 0.313187220 */, 19 }, - /* 8158 */ { MAD_F(0x05030648) /* 0.313238414 */, 19 }, - /* 8159 */ { MAD_F(0x05033bf7) /* 0.313289611 */, 19 }, - - /* 8160 */ { MAD_F(0x050371a7) /* 0.313340809 */, 19 }, - /* 8161 */ { MAD_F(0x0503a757) /* 0.313392010 */, 19 }, - /* 8162 */ { MAD_F(0x0503dd07) /* 0.313443212 */, 19 }, - /* 8163 */ { MAD_F(0x050412b9) /* 0.313494417 */, 19 }, - /* 8164 */ { MAD_F(0x0504486a) /* 0.313545624 */, 19 }, - /* 8165 */ { MAD_F(0x05047e1d) /* 0.313596833 */, 19 }, - /* 8166 */ { MAD_F(0x0504b3cf) /* 0.313648044 */, 19 }, - /* 8167 */ { MAD_F(0x0504e983) /* 0.313699257 */, 19 }, - /* 8168 */ { MAD_F(0x05051f37) /* 0.313750472 */, 19 }, - /* 8169 */ { MAD_F(0x050554eb) /* 0.313801689 */, 19 }, - /* 8170 */ { MAD_F(0x05058aa0) /* 0.313852909 */, 19 }, - /* 8171 */ { MAD_F(0x0505c056) /* 0.313904130 */, 19 }, - /* 8172 */ { MAD_F(0x0505f60c) /* 0.313955354 */, 19 }, - /* 8173 */ { MAD_F(0x05062bc3) /* 0.314006579 */, 19 }, - /* 8174 */ { MAD_F(0x0506617a) /* 0.314057807 */, 19 }, - /* 8175 */ { MAD_F(0x05069732) /* 0.314109037 */, 19 }, - - /* 8176 */ { MAD_F(0x0506cceb) /* 0.314160269 */, 19 }, - /* 8177 */ { MAD_F(0x050702a4) /* 0.314211502 */, 19 }, - /* 8178 */ { MAD_F(0x0507385d) /* 0.314262739 */, 19 }, - /* 8179 */ { MAD_F(0x05076e17) /* 0.314313977 */, 19 }, - /* 8180 */ { MAD_F(0x0507a3d2) /* 0.314365217 */, 19 }, - /* 8181 */ { MAD_F(0x0507d98d) /* 0.314416459 */, 19 }, - /* 8182 */ { MAD_F(0x05080f49) /* 0.314467704 */, 19 }, - /* 8183 */ { MAD_F(0x05084506) /* 0.314518950 */, 19 }, - /* 8184 */ { MAD_F(0x05087ac2) /* 0.314570199 */, 19 }, - /* 8185 */ { MAD_F(0x0508b080) /* 0.314621449 */, 19 }, - /* 8186 */ { MAD_F(0x0508e63e) /* 0.314672702 */, 19 }, - /* 8187 */ { MAD_F(0x05091bfd) /* 0.314723957 */, 19 }, - /* 8188 */ { MAD_F(0x050951bc) /* 0.314775214 */, 19 }, - /* 8189 */ { MAD_F(0x0509877c) /* 0.314826473 */, 19 }, - /* 8190 */ { MAD_F(0x0509bd3c) /* 0.314877734 */, 19 }, - /* 8191 */ { MAD_F(0x0509f2fd) /* 0.314928997 */, 19 }, - - /* 8192 */ { MAD_F(0x050a28be) /* 0.314980262 */, 19 }, - /* 8193 */ { MAD_F(0x050a5e80) /* 0.315031530 */, 19 }, - /* 8194 */ { MAD_F(0x050a9443) /* 0.315082799 */, 19 }, - /* 8195 */ { MAD_F(0x050aca06) /* 0.315134071 */, 19 }, - /* 8196 */ { MAD_F(0x050affc9) /* 0.315185344 */, 19 }, - /* 8197 */ { MAD_F(0x050b358e) /* 0.315236620 */, 19 }, - /* 8198 */ { MAD_F(0x050b6b52) /* 0.315287898 */, 19 }, - /* 8199 */ { MAD_F(0x050ba118) /* 0.315339178 */, 19 }, - /* 8200 */ { MAD_F(0x050bd6de) /* 0.315390460 */, 19 }, - /* 8201 */ { MAD_F(0x050c0ca4) /* 0.315441744 */, 19 }, - /* 8202 */ { MAD_F(0x050c426b) /* 0.315493030 */, 19 }, - /* 8203 */ { MAD_F(0x050c7833) /* 0.315544318 */, 19 }, - /* 8204 */ { MAD_F(0x050cadfb) /* 0.315595608 */, 19 }, - /* 8205 */ { MAD_F(0x050ce3c4) /* 0.315646901 */, 19 }, - /* 8206 */ { MAD_F(0x050d198d) /* 0.315698195 */, 19 } diff --git a/libmad/src/sf_table.dat b/libmad/src/sf_table.dat deleted file mode 100644 index db1484a..0000000 --- a/libmad/src/sf_table.dat +++ /dev/null @@ -1,106 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: sf_table.dat,v 1.7 2004/01/23 09:41:33 rob Exp $ - */ - -/* - * These are the scalefactor values for Layer I and Layer II. - * The values are from Table B.1 of ISO/IEC 11172-3. - * - * There is some error introduced by the 32-bit fixed-point representation; - * the amount of error is shown. For 16-bit PCM output, this shouldn't be - * too much of a problem. - * - * Strictly speaking, Table B.1 has only 63 entries (0-62), thus a strict - * interpretation of ISO/IEC 11172-3 would suggest that a scalefactor index of - * 63 is invalid. However, for better compatibility with current practices, we - * add a 64th entry. - */ - - MAD_F(0x20000000), /* 2.000000000000 => 2.000000000000, e 0.000000000000 */ - MAD_F(0x1965fea5), /* 1.587401051968 => 1.587401051074, e 0.000000000894 */ - MAD_F(0x1428a2fa), /* 1.259921049895 => 1.259921051562, e -0.000000001667 */ - MAD_F(0x10000000), /* 1.000000000000 => 1.000000000000, e 0.000000000000 */ - MAD_F(0x0cb2ff53), /* 0.793700525984 => 0.793700527400, e -0.000000001416 */ - MAD_F(0x0a14517d), /* 0.629960524947 => 0.629960525781, e -0.000000000833 */ - MAD_F(0x08000000), /* 0.500000000000 => 0.500000000000, e 0.000000000000 */ - MAD_F(0x06597fa9), /* 0.396850262992 => 0.396850261837, e 0.000000001155 */ - - MAD_F(0x050a28be), /* 0.314980262474 => 0.314980261028, e 0.000000001446 */ - MAD_F(0x04000000), /* 0.250000000000 => 0.250000000000, e 0.000000000000 */ - MAD_F(0x032cbfd5), /* 0.198425131496 => 0.198425132781, e -0.000000001285 */ - MAD_F(0x0285145f), /* 0.157490131237 => 0.157490130514, e 0.000000000723 */ - MAD_F(0x02000000), /* 0.125000000000 => 0.125000000000, e 0.000000000000 */ - MAD_F(0x01965fea), /* 0.099212565748 => 0.099212564528, e 0.000000001220 */ - MAD_F(0x01428a30), /* 0.078745065618 => 0.078745067120, e -0.000000001501 */ - MAD_F(0x01000000), /* 0.062500000000 => 0.062500000000, e 0.000000000000 */ - - MAD_F(0x00cb2ff5), /* 0.049606282874 => 0.049606282264, e 0.000000000610 */ - MAD_F(0x00a14518), /* 0.039372532809 => 0.039372533560, e -0.000000000751 */ - MAD_F(0x00800000), /* 0.031250000000 => 0.031250000000, e 0.000000000000 */ - MAD_F(0x006597fb), /* 0.024803141437 => 0.024803142995, e -0.000000001558 */ - MAD_F(0x0050a28c), /* 0.019686266405 => 0.019686266780, e -0.000000000375 */ - MAD_F(0x00400000), /* 0.015625000000 => 0.015625000000, e 0.000000000000 */ - MAD_F(0x0032cbfd), /* 0.012401570719 => 0.012401569635, e 0.000000001084 */ - MAD_F(0x00285146), /* 0.009843133202 => 0.009843133390, e -0.000000000188 */ - - MAD_F(0x00200000), /* 0.007812500000 => 0.007812500000, e 0.000000000000 */ - MAD_F(0x001965ff), /* 0.006200785359 => 0.006200786680, e -0.000000001321 */ - MAD_F(0x001428a3), /* 0.004921566601 => 0.004921566695, e -0.000000000094 */ - MAD_F(0x00100000), /* 0.003906250000 => 0.003906250000, e 0.000000000000 */ - MAD_F(0x000cb2ff), /* 0.003100392680 => 0.003100391477, e 0.000000001202 */ - MAD_F(0x000a1451), /* 0.002460783301 => 0.002460781485, e 0.000000001816 */ - MAD_F(0x00080000), /* 0.001953125000 => 0.001953125000, e 0.000000000000 */ - MAD_F(0x00065980), /* 0.001550196340 => 0.001550197601, e -0.000000001262 */ - - MAD_F(0x00050a29), /* 0.001230391650 => 0.001230392605, e -0.000000000955 */ - MAD_F(0x00040000), /* 0.000976562500 => 0.000976562500, e 0.000000000000 */ - MAD_F(0x00032cc0), /* 0.000775098170 => 0.000775098801, e -0.000000000631 */ - MAD_F(0x00028514), /* 0.000615195825 => 0.000615194440, e 0.000000001385 */ - MAD_F(0x00020000), /* 0.000488281250 => 0.000488281250, e 0.000000000000 */ - MAD_F(0x00019660), /* 0.000387549085 => 0.000387549400, e -0.000000000315 */ - MAD_F(0x0001428a), /* 0.000307597913 => 0.000307597220, e 0.000000000693 */ - MAD_F(0x00010000), /* 0.000244140625 => 0.000244140625, e 0.000000000000 */ - - MAD_F(0x0000cb30), /* 0.000193774542 => 0.000193774700, e -0.000000000158 */ - MAD_F(0x0000a145), /* 0.000153798956 => 0.000153798610, e 0.000000000346 */ - MAD_F(0x00008000), /* 0.000122070313 => 0.000122070313, e 0.000000000000 */ - MAD_F(0x00006598), /* 0.000096887271 => 0.000096887350, e -0.000000000079 */ - MAD_F(0x000050a3), /* 0.000076899478 => 0.000076901168, e -0.000000001689 */ - MAD_F(0x00004000), /* 0.000061035156 => 0.000061035156, e 0.000000000000 */ - MAD_F(0x000032cc), /* 0.000048443636 => 0.000048443675, e -0.000000000039 */ - MAD_F(0x00002851), /* 0.000038449739 => 0.000038448721, e 0.000000001018 */ - - MAD_F(0x00002000), /* 0.000030517578 => 0.000030517578, e 0.000000000000 */ - MAD_F(0x00001966), /* 0.000024221818 => 0.000024221838, e -0.000000000020 */ - MAD_F(0x00001429), /* 0.000019224870 => 0.000019226223, e -0.000000001354 */ - MAD_F(0x00001000), /* 0.000015258789 => 0.000015258789, e -0.000000000000 */ - MAD_F(0x00000cb3), /* 0.000012110909 => 0.000012110919, e -0.000000000010 */ - MAD_F(0x00000a14), /* 0.000009612435 => 0.000009611249, e 0.000000001186 */ - MAD_F(0x00000800), /* 0.000007629395 => 0.000007629395, e -0.000000000000 */ - MAD_F(0x00000659), /* 0.000006055454 => 0.000006053597, e 0.000000001858 */ - - MAD_F(0x0000050a), /* 0.000004806217 => 0.000004805624, e 0.000000000593 */ - MAD_F(0x00000400), /* 0.000003814697 => 0.000003814697, e 0.000000000000 */ - MAD_F(0x0000032d), /* 0.000003027727 => 0.000003028661, e -0.000000000934 */ - MAD_F(0x00000285), /* 0.000002403109 => 0.000002402812, e 0.000000000296 */ - MAD_F(0x00000200), /* 0.000001907349 => 0.000001907349, e -0.000000000000 */ - MAD_F(0x00000196), /* 0.000001513864 => 0.000001512468, e 0.000000001396 */ - MAD_F(0x00000143), /* 0.000001201554 => 0.000001203269, e -0.000000001714 */ - MAD_F(0x00000000) /* this compatibility entry is not part of Table B.1 */ diff --git a/libmad/src/stream.c b/libmad/src/stream.c deleted file mode 100644 index 8bb4d6a..0000000 --- a/libmad/src/stream.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: stream.c,v 1.12 2004/02/05 09:02:39 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include - -# include "bit.h" -# include "stream.h" - -/* - * NAME: stream->init() - * DESCRIPTION: initialize stream struct - */ -void mad_stream_init(struct mad_stream *stream) -{ - stream->buffer = 0; - stream->bufend = 0; - stream->skiplen = 0; - - stream->sync = 0; - stream->freerate = 0; - - stream->this_frame = 0; - stream->next_frame = 0; - mad_bit_init(&stream->ptr, 0); - - mad_bit_init(&stream->anc_ptr, 0); - stream->anc_bitlen = 0; - - stream->main_data = 0; - stream->md_len = 0; - - stream->options = 0; - stream->error = MAD_ERROR_NONE; -} - -/* - * NAME: stream->finish() - * DESCRIPTION: deallocate any dynamic memory associated with stream - */ -void mad_stream_finish(struct mad_stream *stream) -{ - if (stream->main_data) { - free(stream->main_data); - stream->main_data = 0; - } - - mad_bit_finish(&stream->anc_ptr); - mad_bit_finish(&stream->ptr); -} - -/* - * NAME: stream->buffer() - * DESCRIPTION: set stream buffer pointers - */ -void mad_stream_buffer(struct mad_stream *stream, - unsigned char const *buffer, unsigned long length) -{ - stream->buffer = buffer; - stream->bufend = buffer + length; - - stream->this_frame = buffer; - stream->next_frame = buffer; - - stream->sync = 1; - - mad_bit_init(&stream->ptr, buffer); -} - -/* - * NAME: stream->skip() - * DESCRIPTION: arrange to skip bytes before the next frame - */ -void mad_stream_skip(struct mad_stream *stream, unsigned long length) -{ - stream->skiplen += length; -} - -/* - * NAME: stream->sync() - * DESCRIPTION: locate the next stream sync word - */ -int mad_stream_sync(struct mad_stream *stream) -{ - register unsigned char const *ptr, *end; - - ptr = mad_bit_nextbyte(&stream->ptr); - end = stream->bufend; - - while (ptr < end - 1 && - !(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) - ++ptr; - - if (end - ptr < MAD_BUFFER_GUARD) - return -1; - - mad_bit_init(&stream->ptr, ptr); - - return 0; -} - -/* - * NAME: stream->errorstr() - * DESCRIPTION: return a string description of the current error condition - */ -char const *mad_stream_errorstr(struct mad_stream const *stream) -{ - switch (stream->error) { - case MAD_ERROR_NONE: return "no error"; - - case MAD_ERROR_BUFLEN: return "input buffer too small (or EOF)"; - case MAD_ERROR_BUFPTR: return "invalid (null) buffer pointer"; - - case MAD_ERROR_NOMEM: return "not enough memory"; - - case MAD_ERROR_LOSTSYNC: return "lost synchronization"; - case MAD_ERROR_BADLAYER: return "reserved header layer value"; - case MAD_ERROR_BADBITRATE: return "forbidden bitrate value"; - case MAD_ERROR_BADSAMPLERATE: return "reserved sample frequency value"; - case MAD_ERROR_BADEMPHASIS: return "reserved emphasis value"; - - case MAD_ERROR_BADCRC: return "CRC check failed"; - case MAD_ERROR_BADBITALLOC: return "forbidden bit allocation value"; - case MAD_ERROR_BADSCALEFACTOR: return "bad scalefactor index"; - case MAD_ERROR_BADMODE: return "bad bitrate/mode combination"; - case MAD_ERROR_BADFRAMELEN: return "bad frame length"; - case MAD_ERROR_BADBIGVALUES: return "bad big_values count"; - case MAD_ERROR_BADBLOCKTYPE: return "reserved block_type"; - case MAD_ERROR_BADSCFSI: return "bad scalefactor selection info"; - case MAD_ERROR_BADDATAPTR: return "bad main_data_begin pointer"; - case MAD_ERROR_BADPART3LEN: return "bad audio data length"; - case MAD_ERROR_BADHUFFTABLE: return "bad Huffman table select"; - case MAD_ERROR_BADHUFFDATA: return "Huffman data overrun"; - case MAD_ERROR_BADSTEREO: return "incompatible block_type for JS"; - } - - return 0; -} diff --git a/libmad/src/stream.h b/libmad/src/stream.h deleted file mode 100644 index 8bff8b4..0000000 --- a/libmad/src/stream.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: stream.h,v 1.20 2004/02/05 09:02:39 rob Exp $ - */ - -# ifndef LIBMAD_STREAM_H -# define LIBMAD_STREAM_H - -# include "bit.h" - -# define MAD_BUFFER_GUARD 8 -# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD) - -enum mad_error { - MAD_ERROR_NONE = 0x0000, /* no error */ - - MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */ - MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */ - - MAD_ERROR_NOMEM = 0x0031, /* not enough memory */ - - MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */ - MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */ - MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */ - MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */ - MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */ - - MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */ - MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */ - MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */ - MAD_ERROR_BADMODE = 0x0222, /* bad bitrate/mode combination */ - MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */ - MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */ - MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */ - MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */ - MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */ - MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */ - MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */ - MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */ - MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */ -}; - -# define MAD_RECOVERABLE(error) ((error) & 0xff00) - -struct mad_stream { - unsigned char const *buffer; /* input bitstream buffer */ - unsigned char const *bufend; /* end of buffer */ - unsigned long skiplen; /* bytes to skip before next frame */ - - int sync; /* stream sync found */ - unsigned long freerate; /* free bitrate (fixed) */ - - unsigned char const *this_frame; /* start of current frame */ - unsigned char const *next_frame; /* start of next frame */ - struct mad_bitptr ptr; /* current processing bit pointer */ - - struct mad_bitptr anc_ptr; /* ancillary bits pointer */ - unsigned int anc_bitlen; /* number of ancillary bits */ - - unsigned char (*main_data)[MAD_BUFFER_MDLEN]; - /* Layer III main_data() */ - unsigned int md_len; /* bytes in main_data */ - - int options; /* decoding options (see below) */ - enum mad_error error; /* error code (see above) */ -}; - -enum { - MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */ - MAD_OPTION_HALFSAMPLERATE = 0x0002 /* generate PCM at 1/2 sample rate */ -# if 0 /* not yet implemented */ - MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */ - MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */ - MAD_OPTION_SINGLECHANNEL = 0x0030 /* combine channels */ -# endif -}; - -void mad_stream_init(struct mad_stream *); -void mad_stream_finish(struct mad_stream *); - -# define mad_stream_options(stream, opts) \ - ((void) ((stream)->options = (opts))) - -void mad_stream_buffer(struct mad_stream *, - unsigned char const *, unsigned long); -void mad_stream_skip(struct mad_stream *, unsigned long); - -int mad_stream_sync(struct mad_stream *); - -char const *mad_stream_errorstr(struct mad_stream const *); - -# endif diff --git a/libmad/src/synth.c b/libmad/src/synth.c deleted file mode 100644 index 0ccb106..0000000 --- a/libmad/src/synth.c +++ /dev/null @@ -1,866 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: synth.c,v 1.25 2004/01/23 09:41:33 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include "fixed.h" -# include "frame.h" -# include "synth.h" - -# ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4146) -# endif - -/* - * NAME: synth->init() - * DESCRIPTION: initialize synth struct - */ -void mad_synth_init(struct mad_synth *synth) -{ - mad_synth_mute(synth); - - synth->phase = 0; - - synth->pcm.samplerate = 0; - synth->pcm.channels = 0; - synth->pcm.length = 0; -} - -/* - * NAME: synth->mute() - * DESCRIPTION: zero all polyphase filterbank values, resetting synthesis - */ -void mad_synth_mute(struct mad_synth *synth) -{ - unsigned int ch, s, v; - - for (ch = 0; ch < 2; ++ch) { - for (s = 0; s < 16; ++s) { - for (v = 0; v < 8; ++v) { - synth->filter[ch][0][0][s][v] = synth->filter[ch][0][1][s][v] = - synth->filter[ch][1][0][s][v] = synth->filter[ch][1][1][s][v] = 0; - } - } - } -} - -/* - * An optional optimization called here the Subband Synthesis Optimization - * (SSO) improves the performance of subband synthesis at the expense of - * accuracy. - * - * The idea is to simplify 32x32->64-bit multiplication to 32x32->32 such - * that extra scaling and rounding are not necessary. This often allows the - * compiler to use faster 32-bit multiply-accumulate instructions instead of - * explicit 64-bit multiply, shift, and add instructions. - * - * SSO works like this: a full 32x32->64-bit multiply of two mad_fixed_t - * values requires the result to be right-shifted 28 bits to be properly - * scaled to the same fixed-point format. Right shifts can be applied at any - * time to either operand or to the result, so the optimization involves - * careful placement of these shifts to minimize the loss of accuracy. - * - * First, a 14-bit shift is applied with rounding at compile-time to the D[] - * table of coefficients for the subband synthesis window. This only loses 2 - * bits of accuracy because the lower 12 bits are always zero. A second - * 12-bit shift occurs after the DCT calculation. This loses 12 bits of - * accuracy. Finally, a third 2-bit shift occurs just before the sample is - * saved in the PCM buffer. 14 + 12 + 2 == 28 bits. - */ - -/* FPM_DEFAULT without OPT_SSO will actually lose accuracy and performance */ - -# if defined(FPM_DEFAULT) && !defined(OPT_SSO) -# define OPT_SSO -# endif - -/* second SSO shift, with rounding */ - -# if defined(OPT_SSO) -# define SHIFT(x) (((x) + (1L << 11)) >> 12) -# else -# define SHIFT(x) (x) -# endif - -/* possible DCT speed optimization */ - -# if defined(OPT_SPEED) && defined(MAD_F_MLX) -# define OPT_DCTO -# define MUL(x, y) \ - ({ mad_fixed64hi_t hi; \ - mad_fixed64lo_t lo; \ - MAD_F_MLX(hi, lo, (x), (y)); \ - hi << (32 - MAD_F_SCALEBITS - 3); \ - }) -# else -# undef OPT_DCTO -# define MUL(x, y) mad_f_mul((x), (y)) -# endif - -/* - * NAME: dct32() - * DESCRIPTION: perform fast in[32]->out[32] DCT - */ -static -void dct32(mad_fixed_t const in[32], unsigned int slot, - mad_fixed_t lo[16][8], mad_fixed_t hi[16][8]) -{ - mad_fixed_t t0, t1, t2, t3, t4, t5, t6, t7; - mad_fixed_t t8, t9, t10, t11, t12, t13, t14, t15; - mad_fixed_t t16, t17, t18, t19, t20, t21, t22, t23; - mad_fixed_t t24, t25, t26, t27, t28, t29, t30, t31; - mad_fixed_t t32, t33, t34, t35, t36, t37, t38, t39; - mad_fixed_t t40, t41, t42, t43, t44, t45, t46, t47; - mad_fixed_t t48, t49, t50, t51, t52, t53, t54, t55; - mad_fixed_t t56, t57, t58, t59, t60, t61, t62, t63; - mad_fixed_t t64, t65, t66, t67, t68, t69, t70, t71; - mad_fixed_t t72, t73, t74, t75, t76, t77, t78, t79; - mad_fixed_t t80, t81, t82, t83, t84, t85, t86, t87; - mad_fixed_t t88, t89, t90, t91, t92, t93, t94, t95; - mad_fixed_t t96, t97, t98, t99, t100, t101, t102, t103; - mad_fixed_t t104, t105, t106, t107, t108, t109, t110, t111; - mad_fixed_t t112, t113, t114, t115, t116, t117, t118, t119; - mad_fixed_t t120, t121, t122, t123, t124, t125, t126, t127; - mad_fixed_t t128, t129, t130, t131, t132, t133, t134, t135; - mad_fixed_t t136, t137, t138, t139, t140, t141, t142, t143; - mad_fixed_t t144, t145, t146, t147, t148, t149, t150, t151; - mad_fixed_t t152, t153, t154, t155, t156, t157, t158, t159; - mad_fixed_t t160, t161, t162, t163, t164, t165, t166, t167; - mad_fixed_t t168, t169, t170, t171, t172, t173, t174, t175; - mad_fixed_t t176; - - /* costab[i] = cos(PI / (2 * 32) * i) */ - -# if defined(OPT_DCTO) -# define costab1 MAD_F(0x7fd8878e) -# define costab2 MAD_F(0x7f62368f) -# define costab3 MAD_F(0x7e9d55fc) -# define costab4 MAD_F(0x7d8a5f40) -# define costab5 MAD_F(0x7c29fbee) -# define costab6 MAD_F(0x7a7d055b) -# define costab7 MAD_F(0x78848414) -# define costab8 MAD_F(0x7641af3d) -# define costab9 MAD_F(0x73b5ebd1) -# define costab10 MAD_F(0x70e2cbc6) -# define costab11 MAD_F(0x6dca0d14) -# define costab12 MAD_F(0x6a6d98a4) -# define costab13 MAD_F(0x66cf8120) -# define costab14 MAD_F(0x62f201ac) -# define costab15 MAD_F(0x5ed77c8a) -# define costab16 MAD_F(0x5a82799a) -# define costab17 MAD_F(0x55f5a4d2) -# define costab18 MAD_F(0x5133cc94) -# define costab19 MAD_F(0x4c3fdff4) -# define costab20 MAD_F(0x471cece7) -# define costab21 MAD_F(0x41ce1e65) -# define costab22 MAD_F(0x3c56ba70) -# define costab23 MAD_F(0x36ba2014) -# define costab24 MAD_F(0x30fbc54d) -# define costab25 MAD_F(0x2b1f34eb) -# define costab26 MAD_F(0x25280c5e) -# define costab27 MAD_F(0x1f19f97b) -# define costab28 MAD_F(0x18f8b83c) -# define costab29 MAD_F(0x12c8106f) -# define costab30 MAD_F(0x0c8bd35e) -# define costab31 MAD_F(0x0647d97c) -# else -# define costab1 MAD_F(0x0ffb10f2) /* 0.998795456 */ -# define costab2 MAD_F(0x0fec46d2) /* 0.995184727 */ -# define costab3 MAD_F(0x0fd3aac0) /* 0.989176510 */ -# define costab4 MAD_F(0x0fb14be8) /* 0.980785280 */ -# define costab5 MAD_F(0x0f853f7e) /* 0.970031253 */ -# define costab6 MAD_F(0x0f4fa0ab) /* 0.956940336 */ -# define costab7 MAD_F(0x0f109082) /* 0.941544065 */ -# define costab8 MAD_F(0x0ec835e8) /* 0.923879533 */ -# define costab9 MAD_F(0x0e76bd7a) /* 0.903989293 */ -# define costab10 MAD_F(0x0e1c5979) /* 0.881921264 */ -# define costab11 MAD_F(0x0db941a3) /* 0.857728610 */ -# define costab12 MAD_F(0x0d4db315) /* 0.831469612 */ -# define costab13 MAD_F(0x0cd9f024) /* 0.803207531 */ -# define costab14 MAD_F(0x0c5e4036) /* 0.773010453 */ -# define costab15 MAD_F(0x0bdaef91) /* 0.740951125 */ -# define costab16 MAD_F(0x0b504f33) /* 0.707106781 */ -# define costab17 MAD_F(0x0abeb49a) /* 0.671558955 */ -# define costab18 MAD_F(0x0a267993) /* 0.634393284 */ -# define costab19 MAD_F(0x0987fbfe) /* 0.595699304 */ -# define costab20 MAD_F(0x08e39d9d) /* 0.555570233 */ -# define costab21 MAD_F(0x0839c3cd) /* 0.514102744 */ -# define costab22 MAD_F(0x078ad74e) /* 0.471396737 */ -# define costab23 MAD_F(0x06d74402) /* 0.427555093 */ -# define costab24 MAD_F(0x061f78aa) /* 0.382683432 */ -# define costab25 MAD_F(0x0563e69d) /* 0.336889853 */ -# define costab26 MAD_F(0x04a5018c) /* 0.290284677 */ -# define costab27 MAD_F(0x03e33f2f) /* 0.242980180 */ -# define costab28 MAD_F(0x031f1708) /* 0.195090322 */ -# define costab29 MAD_F(0x0259020e) /* 0.146730474 */ -# define costab30 MAD_F(0x01917a6c) /* 0.098017140 */ -# define costab31 MAD_F(0x00c8fb30) /* 0.049067674 */ -# endif - - t0 = in[0] + in[31]; t16 = MUL(in[0] - in[31], costab1); - t1 = in[15] + in[16]; t17 = MUL(in[15] - in[16], costab31); - - t41 = t16 + t17; - t59 = MUL(t16 - t17, costab2); - t33 = t0 + t1; - t50 = MUL(t0 - t1, costab2); - - t2 = in[7] + in[24]; t18 = MUL(in[7] - in[24], costab15); - t3 = in[8] + in[23]; t19 = MUL(in[8] - in[23], costab17); - - t42 = t18 + t19; - t60 = MUL(t18 - t19, costab30); - t34 = t2 + t3; - t51 = MUL(t2 - t3, costab30); - - t4 = in[3] + in[28]; t20 = MUL(in[3] - in[28], costab7); - t5 = in[12] + in[19]; t21 = MUL(in[12] - in[19], costab25); - - t43 = t20 + t21; - t61 = MUL(t20 - t21, costab14); - t35 = t4 + t5; - t52 = MUL(t4 - t5, costab14); - - t6 = in[4] + in[27]; t22 = MUL(in[4] - in[27], costab9); - t7 = in[11] + in[20]; t23 = MUL(in[11] - in[20], costab23); - - t44 = t22 + t23; - t62 = MUL(t22 - t23, costab18); - t36 = t6 + t7; - t53 = MUL(t6 - t7, costab18); - - t8 = in[1] + in[30]; t24 = MUL(in[1] - in[30], costab3); - t9 = in[14] + in[17]; t25 = MUL(in[14] - in[17], costab29); - - t45 = t24 + t25; - t63 = MUL(t24 - t25, costab6); - t37 = t8 + t9; - t54 = MUL(t8 - t9, costab6); - - t10 = in[6] + in[25]; t26 = MUL(in[6] - in[25], costab13); - t11 = in[9] + in[22]; t27 = MUL(in[9] - in[22], costab19); - - t46 = t26 + t27; - t64 = MUL(t26 - t27, costab26); - t38 = t10 + t11; - t55 = MUL(t10 - t11, costab26); - - t12 = in[2] + in[29]; t28 = MUL(in[2] - in[29], costab5); - t13 = in[13] + in[18]; t29 = MUL(in[13] - in[18], costab27); - - t47 = t28 + t29; - t65 = MUL(t28 - t29, costab10); - t39 = t12 + t13; - t56 = MUL(t12 - t13, costab10); - - t14 = in[5] + in[26]; t30 = MUL(in[5] - in[26], costab11); - t15 = in[10] + in[21]; t31 = MUL(in[10] - in[21], costab21); - - t48 = t30 + t31; - t66 = MUL(t30 - t31, costab22); - t40 = t14 + t15; - t57 = MUL(t14 - t15, costab22); - - t69 = t33 + t34; t89 = MUL(t33 - t34, costab4); - t70 = t35 + t36; t90 = MUL(t35 - t36, costab28); - t71 = t37 + t38; t91 = MUL(t37 - t38, costab12); - t72 = t39 + t40; t92 = MUL(t39 - t40, costab20); - t73 = t41 + t42; t94 = MUL(t41 - t42, costab4); - t74 = t43 + t44; t95 = MUL(t43 - t44, costab28); - t75 = t45 + t46; t96 = MUL(t45 - t46, costab12); - t76 = t47 + t48; t97 = MUL(t47 - t48, costab20); - - t78 = t50 + t51; t100 = MUL(t50 - t51, costab4); - t79 = t52 + t53; t101 = MUL(t52 - t53, costab28); - t80 = t54 + t55; t102 = MUL(t54 - t55, costab12); - t81 = t56 + t57; t103 = MUL(t56 - t57, costab20); - - t83 = t59 + t60; t106 = MUL(t59 - t60, costab4); - t84 = t61 + t62; t107 = MUL(t61 - t62, costab28); - t85 = t63 + t64; t108 = MUL(t63 - t64, costab12); - t86 = t65 + t66; t109 = MUL(t65 - t66, costab20); - - t113 = t69 + t70; - t114 = t71 + t72; - - /* 0 */ hi[15][slot] = SHIFT(t113 + t114); - /* 16 */ lo[ 0][slot] = SHIFT(MUL(t113 - t114, costab16)); - - t115 = t73 + t74; - t116 = t75 + t76; - - t32 = t115 + t116; - - /* 1 */ hi[14][slot] = SHIFT(t32); - - t118 = t78 + t79; - t119 = t80 + t81; - - t58 = t118 + t119; - - /* 2 */ hi[13][slot] = SHIFT(t58); - - t121 = t83 + t84; - t122 = t85 + t86; - - t67 = t121 + t122; - - t49 = (t67 * 2) - t32; - - /* 3 */ hi[12][slot] = SHIFT(t49); - - t125 = t89 + t90; - t126 = t91 + t92; - - t93 = t125 + t126; - - /* 4 */ hi[11][slot] = SHIFT(t93); - - t128 = t94 + t95; - t129 = t96 + t97; - - t98 = t128 + t129; - - t68 = (t98 * 2) - t49; - - /* 5 */ hi[10][slot] = SHIFT(t68); - - t132 = t100 + t101; - t133 = t102 + t103; - - t104 = t132 + t133; - - t82 = (t104 * 2) - t58; - - /* 6 */ hi[ 9][slot] = SHIFT(t82); - - t136 = t106 + t107; - t137 = t108 + t109; - - t110 = t136 + t137; - - t87 = (t110 * 2) - t67; - - t77 = (t87 * 2) - t68; - - /* 7 */ hi[ 8][slot] = SHIFT(t77); - - t141 = MUL(t69 - t70, costab8); - t142 = MUL(t71 - t72, costab24); - t143 = t141 + t142; - - /* 8 */ hi[ 7][slot] = SHIFT(t143); - /* 24 */ lo[ 8][slot] = - SHIFT((MUL(t141 - t142, costab16) * 2) - t143); - - t144 = MUL(t73 - t74, costab8); - t145 = MUL(t75 - t76, costab24); - t146 = t144 + t145; - - t88 = (t146 * 2) - t77; - - /* 9 */ hi[ 6][slot] = SHIFT(t88); - - t148 = MUL(t78 - t79, costab8); - t149 = MUL(t80 - t81, costab24); - t150 = t148 + t149; - - t105 = (t150 * 2) - t82; - - /* 10 */ hi[ 5][slot] = SHIFT(t105); - - t152 = MUL(t83 - t84, costab8); - t153 = MUL(t85 - t86, costab24); - t154 = t152 + t153; - - t111 = (t154 * 2) - t87; - - t99 = (t111 * 2) - t88; - - /* 11 */ hi[ 4][slot] = SHIFT(t99); - - t157 = MUL(t89 - t90, costab8); - t158 = MUL(t91 - t92, costab24); - t159 = t157 + t158; - - t127 = (t159 * 2) - t93; - - /* 12 */ hi[ 3][slot] = SHIFT(t127); - - t160 = (MUL(t125 - t126, costab16) * 2) - t127; - - /* 20 */ lo[ 4][slot] = SHIFT(t160); - /* 28 */ lo[12][slot] = - SHIFT((((MUL(t157 - t158, costab16) * 2) - t159) * 2) - t160); - - t161 = MUL(t94 - t95, costab8); - t162 = MUL(t96 - t97, costab24); - t163 = t161 + t162; - - t130 = (t163 * 2) - t98; - - t112 = (t130 * 2) - t99; - - /* 13 */ hi[ 2][slot] = SHIFT(t112); - - t164 = (MUL(t128 - t129, costab16) * 2) - t130; - - t166 = MUL(t100 - t101, costab8); - t167 = MUL(t102 - t103, costab24); - t168 = t166 + t167; - - t134 = (t168 * 2) - t104; - - t120 = (t134 * 2) - t105; - - /* 14 */ hi[ 1][slot] = SHIFT(t120); - - t135 = (MUL(t118 - t119, costab16) * 2) - t120; - - /* 18 */ lo[ 2][slot] = SHIFT(t135); - - t169 = (MUL(t132 - t133, costab16) * 2) - t134; - - t151 = (t169 * 2) - t135; - - /* 22 */ lo[ 6][slot] = SHIFT(t151); - - t170 = (((MUL(t148 - t149, costab16) * 2) - t150) * 2) - t151; - - /* 26 */ lo[10][slot] = SHIFT(t170); - /* 30 */ lo[14][slot] = - SHIFT((((((MUL(t166 - t167, costab16) * 2) - - t168) * 2) - t169) * 2) - t170); - - t171 = MUL(t106 - t107, costab8); - t172 = MUL(t108 - t109, costab24); - t173 = t171 + t172; - - t138 = (t173 * 2) - t110; - - t123 = (t138 * 2) - t111; - - t139 = (MUL(t121 - t122, costab16) * 2) - t123; - - t117 = (t123 * 2) - t112; - - /* 15 */ hi[ 0][slot] = SHIFT(t117); - - t124 = (MUL(t115 - t116, costab16) * 2) - t117; - - /* 17 */ lo[ 1][slot] = SHIFT(t124); - - t131 = (t139 * 2) - t124; - - /* 19 */ lo[ 3][slot] = SHIFT(t131); - - t140 = (t164 * 2) - t131; - - /* 21 */ lo[ 5][slot] = SHIFT(t140); - - t174 = (MUL(t136 - t137, costab16) * 2) - t138; - - t155 = (t174 * 2) - t139; - - t147 = (t155 * 2) - t140; - - /* 23 */ lo[ 7][slot] = SHIFT(t147); - - t156 = (((MUL(t144 - t145, costab16) * 2) - t146) * 2) - t147; - - /* 25 */ lo[ 9][slot] = SHIFT(t156); - - t175 = (((MUL(t152 - t153, costab16) * 2) - t154) * 2) - t155; - - t165 = (t175 * 2) - t156; - - /* 27 */ lo[11][slot] = SHIFT(t165); - - t176 = (((((MUL(t161 - t162, costab16) * 2) - - t163) * 2) - t164) * 2) - t165; - - /* 29 */ lo[13][slot] = SHIFT(t176); - /* 31 */ lo[15][slot] = - SHIFT((((((((MUL(t171 - t172, costab16) * 2) - - t173) * 2) - t174) * 2) - t175) * 2) - t176); - - /* - * Totals: - * 80 multiplies - * 80 additions - * 119 subtractions - * 49 shifts (not counting SSO) - */ -} - -# undef MUL -# undef SHIFT - -/* third SSO shift and/or D[] optimization preshift */ - -# if defined(OPT_SSO) -# if MAD_F_FRACBITS != 28 -# error "MAD_F_FRACBITS must be 28 to use OPT_SSO" -# endif -# define ML0(hi, lo, x, y) ((lo) = (x) * (y)) -# define MLA(hi, lo, x, y) ((lo) += (x) * (y)) -# define MLN(hi, lo) ((lo) = -(lo)) -# define MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) -# define SHIFT(x) ((x) >> 2) -# define PRESHIFT(x) ((MAD_F(x) + (1L << 13)) >> 14) -# else -# define ML0(hi, lo, x, y) MAD_F_ML0((hi), (lo), (x), (y)) -# define MLA(hi, lo, x, y) MAD_F_MLA((hi), (lo), (x), (y)) -# define MLN(hi, lo) MAD_F_MLN((hi), (lo)) -# define MLZ(hi, lo) MAD_F_MLZ((hi), (lo)) -# define SHIFT(x) (x) -# if defined(MAD_F_SCALEBITS) -# undef MAD_F_SCALEBITS -# define MAD_F_SCALEBITS (MAD_F_FRACBITS - 12) -# define PRESHIFT(x) (MAD_F(x) >> 12) -# else -# define PRESHIFT(x) MAD_F(x) -# endif -# endif - -static -mad_fixed_t const D[17][32] = { -# include "D.dat" -}; - -# if defined(ASO_SYNTH) -void synth_full(struct mad_synth *, struct mad_frame const *, - unsigned int, unsigned int); -# else -/* - * NAME: synth->full() - * DESCRIPTION: perform full frequency PCM synthesis - */ -static -void synth_full(struct mad_synth *synth, struct mad_frame const *frame, - unsigned int nch, unsigned int ns) -{ - unsigned int phase, ch, s, sb, pe, po; - mad_fixed_t *pcm1, *pcm2, (*filter)[2][2][16][8]; - mad_fixed_t const (*sbsample)[36][32]; - register mad_fixed_t (*fe)[8], (*fx)[8], (*fo)[8]; - register mad_fixed_t const (*Dptr)[32], *ptr; - register mad_fixed64hi_t hi; - register mad_fixed64lo_t lo; - - for (ch = 0; ch < nch; ++ch) { - sbsample = &frame->sbsample[ch]; - filter = &synth->filter[ch]; - phase = synth->phase; - pcm1 = synth->pcm.samples[ch]; - - for (s = 0; s < ns; ++s) { - dct32((*sbsample)[s], phase >> 1, - (*filter)[0][phase & 1], (*filter)[1][phase & 1]); - - pe = phase & ~1; - po = ((phase - 1) & 0xf) | 1; - - /* calculate 32 samples */ - - fe = &(*filter)[0][ phase & 1][0]; - fx = &(*filter)[0][~phase & 1][0]; - fo = &(*filter)[1][~phase & 1][0]; - - Dptr = &D[0]; - - ptr = *Dptr + po; - ML0(hi, lo, (*fx)[0], ptr[ 0]); - MLA(hi, lo, (*fx)[1], ptr[14]); - MLA(hi, lo, (*fx)[2], ptr[12]); - MLA(hi, lo, (*fx)[3], ptr[10]); - MLA(hi, lo, (*fx)[4], ptr[ 8]); - MLA(hi, lo, (*fx)[5], ptr[ 6]); - MLA(hi, lo, (*fx)[6], ptr[ 4]); - MLA(hi, lo, (*fx)[7], ptr[ 2]); - MLN(hi, lo); - - ptr = *Dptr + pe; - MLA(hi, lo, (*fe)[0], ptr[ 0]); - MLA(hi, lo, (*fe)[1], ptr[14]); - MLA(hi, lo, (*fe)[2], ptr[12]); - MLA(hi, lo, (*fe)[3], ptr[10]); - MLA(hi, lo, (*fe)[4], ptr[ 8]); - MLA(hi, lo, (*fe)[5], ptr[ 6]); - MLA(hi, lo, (*fe)[6], ptr[ 4]); - MLA(hi, lo, (*fe)[7], ptr[ 2]); - - *pcm1++ = SHIFT(MLZ(hi, lo)); - - pcm2 = pcm1 + 30; - - for (sb = 1; sb < 16; ++sb) { - ++fe; - ++Dptr; - - /* D[32 - sb][i] == -D[sb][31 - i] */ - - ptr = *Dptr + po; - ML0(hi, lo, (*fo)[0], ptr[ 0]); - MLA(hi, lo, (*fo)[1], ptr[14]); - MLA(hi, lo, (*fo)[2], ptr[12]); - MLA(hi, lo, (*fo)[3], ptr[10]); - MLA(hi, lo, (*fo)[4], ptr[ 8]); - MLA(hi, lo, (*fo)[5], ptr[ 6]); - MLA(hi, lo, (*fo)[6], ptr[ 4]); - MLA(hi, lo, (*fo)[7], ptr[ 2]); - MLN(hi, lo); - - ptr = *Dptr + pe; - MLA(hi, lo, (*fe)[7], ptr[ 2]); - MLA(hi, lo, (*fe)[6], ptr[ 4]); - MLA(hi, lo, (*fe)[5], ptr[ 6]); - MLA(hi, lo, (*fe)[4], ptr[ 8]); - MLA(hi, lo, (*fe)[3], ptr[10]); - MLA(hi, lo, (*fe)[2], ptr[12]); - MLA(hi, lo, (*fe)[1], ptr[14]); - MLA(hi, lo, (*fe)[0], ptr[ 0]); - - *pcm1++ = SHIFT(MLZ(hi, lo)); - - ptr = *Dptr - pe; - ML0(hi, lo, (*fe)[0], ptr[31 - 16]); - MLA(hi, lo, (*fe)[1], ptr[31 - 14]); - MLA(hi, lo, (*fe)[2], ptr[31 - 12]); - MLA(hi, lo, (*fe)[3], ptr[31 - 10]); - MLA(hi, lo, (*fe)[4], ptr[31 - 8]); - MLA(hi, lo, (*fe)[5], ptr[31 - 6]); - MLA(hi, lo, (*fe)[6], ptr[31 - 4]); - MLA(hi, lo, (*fe)[7], ptr[31 - 2]); - - ptr = *Dptr - po; - MLA(hi, lo, (*fo)[7], ptr[31 - 2]); - MLA(hi, lo, (*fo)[6], ptr[31 - 4]); - MLA(hi, lo, (*fo)[5], ptr[31 - 6]); - MLA(hi, lo, (*fo)[4], ptr[31 - 8]); - MLA(hi, lo, (*fo)[3], ptr[31 - 10]); - MLA(hi, lo, (*fo)[2], ptr[31 - 12]); - MLA(hi, lo, (*fo)[1], ptr[31 - 14]); - MLA(hi, lo, (*fo)[0], ptr[31 - 16]); - - *pcm2-- = SHIFT(MLZ(hi, lo)); - - ++fo; - } - - ++Dptr; - - ptr = *Dptr + po; - ML0(hi, lo, (*fo)[0], ptr[ 0]); - MLA(hi, lo, (*fo)[1], ptr[14]); - MLA(hi, lo, (*fo)[2], ptr[12]); - MLA(hi, lo, (*fo)[3], ptr[10]); - MLA(hi, lo, (*fo)[4], ptr[ 8]); - MLA(hi, lo, (*fo)[5], ptr[ 6]); - MLA(hi, lo, (*fo)[6], ptr[ 4]); - MLA(hi, lo, (*fo)[7], ptr[ 2]); - - *pcm1 = SHIFT(-MLZ(hi, lo)); - pcm1 += 16; - - phase = (phase + 1) % 16; - } - } -} -# endif - -/* - * NAME: synth->half() - * DESCRIPTION: perform half frequency PCM synthesis - */ -static -void synth_half(struct mad_synth *synth, struct mad_frame const *frame, - unsigned int nch, unsigned int ns) -{ - unsigned int phase, ch, s, sb, pe, po; - mad_fixed_t *pcm1, *pcm2, (*filter)[2][2][16][8]; - mad_fixed_t const (*sbsample)[36][32]; - register mad_fixed_t (*fe)[8], (*fx)[8], (*fo)[8]; - register mad_fixed_t const (*Dptr)[32], *ptr; - register mad_fixed64hi_t hi; - register mad_fixed64lo_t lo; - - for (ch = 0; ch < nch; ++ch) { - sbsample = &frame->sbsample[ch]; - filter = &synth->filter[ch]; - phase = synth->phase; - pcm1 = synth->pcm.samples[ch]; - - for (s = 0; s < ns; ++s) { - dct32((*sbsample)[s], phase >> 1, - (*filter)[0][phase & 1], (*filter)[1][phase & 1]); - - pe = phase & ~1; - po = ((phase - 1) & 0xf) | 1; - - /* calculate 16 samples */ - - fe = &(*filter)[0][ phase & 1][0]; - fx = &(*filter)[0][~phase & 1][0]; - fo = &(*filter)[1][~phase & 1][0]; - - Dptr = &D[0]; - - ptr = *Dptr + po; - ML0(hi, lo, (*fx)[0], ptr[ 0]); - MLA(hi, lo, (*fx)[1], ptr[14]); - MLA(hi, lo, (*fx)[2], ptr[12]); - MLA(hi, lo, (*fx)[3], ptr[10]); - MLA(hi, lo, (*fx)[4], ptr[ 8]); - MLA(hi, lo, (*fx)[5], ptr[ 6]); - MLA(hi, lo, (*fx)[6], ptr[ 4]); - MLA(hi, lo, (*fx)[7], ptr[ 2]); - MLN(hi, lo); - - ptr = *Dptr + pe; - MLA(hi, lo, (*fe)[0], ptr[ 0]); - MLA(hi, lo, (*fe)[1], ptr[14]); - MLA(hi, lo, (*fe)[2], ptr[12]); - MLA(hi, lo, (*fe)[3], ptr[10]); - MLA(hi, lo, (*fe)[4], ptr[ 8]); - MLA(hi, lo, (*fe)[5], ptr[ 6]); - MLA(hi, lo, (*fe)[6], ptr[ 4]); - MLA(hi, lo, (*fe)[7], ptr[ 2]); - - *pcm1++ = SHIFT(MLZ(hi, lo)); - - pcm2 = pcm1 + 14; - - for (sb = 1; sb < 16; ++sb) { - ++fe; - ++Dptr; - - /* D[32 - sb][i] == -D[sb][31 - i] */ - - if (!(sb & 1)) { - ptr = *Dptr + po; - ML0(hi, lo, (*fo)[0], ptr[ 0]); - MLA(hi, lo, (*fo)[1], ptr[14]); - MLA(hi, lo, (*fo)[2], ptr[12]); - MLA(hi, lo, (*fo)[3], ptr[10]); - MLA(hi, lo, (*fo)[4], ptr[ 8]); - MLA(hi, lo, (*fo)[5], ptr[ 6]); - MLA(hi, lo, (*fo)[6], ptr[ 4]); - MLA(hi, lo, (*fo)[7], ptr[ 2]); - MLN(hi, lo); - - ptr = *Dptr + pe; - MLA(hi, lo, (*fe)[7], ptr[ 2]); - MLA(hi, lo, (*fe)[6], ptr[ 4]); - MLA(hi, lo, (*fe)[5], ptr[ 6]); - MLA(hi, lo, (*fe)[4], ptr[ 8]); - MLA(hi, lo, (*fe)[3], ptr[10]); - MLA(hi, lo, (*fe)[2], ptr[12]); - MLA(hi, lo, (*fe)[1], ptr[14]); - MLA(hi, lo, (*fe)[0], ptr[ 0]); - - *pcm1++ = SHIFT(MLZ(hi, lo)); - - ptr = *Dptr - po; - ML0(hi, lo, (*fo)[7], ptr[31 - 2]); - MLA(hi, lo, (*fo)[6], ptr[31 - 4]); - MLA(hi, lo, (*fo)[5], ptr[31 - 6]); - MLA(hi, lo, (*fo)[4], ptr[31 - 8]); - MLA(hi, lo, (*fo)[3], ptr[31 - 10]); - MLA(hi, lo, (*fo)[2], ptr[31 - 12]); - MLA(hi, lo, (*fo)[1], ptr[31 - 14]); - MLA(hi, lo, (*fo)[0], ptr[31 - 16]); - - ptr = *Dptr - pe; - MLA(hi, lo, (*fe)[0], ptr[31 - 16]); - MLA(hi, lo, (*fe)[1], ptr[31 - 14]); - MLA(hi, lo, (*fe)[2], ptr[31 - 12]); - MLA(hi, lo, (*fe)[3], ptr[31 - 10]); - MLA(hi, lo, (*fe)[4], ptr[31 - 8]); - MLA(hi, lo, (*fe)[5], ptr[31 - 6]); - MLA(hi, lo, (*fe)[6], ptr[31 - 4]); - MLA(hi, lo, (*fe)[7], ptr[31 - 2]); - - *pcm2-- = SHIFT(MLZ(hi, lo)); - } - - ++fo; - } - - ++Dptr; - - ptr = *Dptr + po; - ML0(hi, lo, (*fo)[0], ptr[ 0]); - MLA(hi, lo, (*fo)[1], ptr[14]); - MLA(hi, lo, (*fo)[2], ptr[12]); - MLA(hi, lo, (*fo)[3], ptr[10]); - MLA(hi, lo, (*fo)[4], ptr[ 8]); - MLA(hi, lo, (*fo)[5], ptr[ 6]); - MLA(hi, lo, (*fo)[6], ptr[ 4]); - MLA(hi, lo, (*fo)[7], ptr[ 2]); - - *pcm1 = SHIFT(-MLZ(hi, lo)); - pcm1 += 8; - - phase = (phase + 1) % 16; - } - } -} - -/* - * NAME: synth->frame() - * DESCRIPTION: perform PCM synthesis of frame subband samples - */ -void mad_synth_frame(struct mad_synth *synth, struct mad_frame const *frame) -{ - unsigned int nch, ns; - void (*synth_frame)(struct mad_synth *, struct mad_frame const *, - unsigned int, unsigned int); - - nch = MAD_NCHANNELS(&frame->header); - ns = MAD_NSBSAMPLES(&frame->header); - - synth->pcm.samplerate = frame->header.samplerate; - synth->pcm.channels = nch; - synth->pcm.length = 32 * ns; - - synth_frame = synth_full; - - if (frame->options & MAD_OPTION_HALFSAMPLERATE) { - synth->pcm.samplerate /= 2; - synth->pcm.length /= 2; - - synth_frame = synth_half; - } - - synth_frame(synth, frame, nch, ns); - - synth->phase = (synth->phase + ns) % 16; -} - -# ifdef _MSC_VER -# pragma warning(pop) -# endif diff --git a/libmad/src/synth.h b/libmad/src/synth.h deleted file mode 100644 index 8ae4bc9..0000000 --- a/libmad/src/synth.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: synth.h,v 1.15 2004/01/23 09:41:33 rob Exp $ - */ - -# ifndef LIBMAD_SYNTH_H -# define LIBMAD_SYNTH_H - -# include "fixed.h" -# include "frame.h" - -struct mad_pcm { - unsigned int samplerate; /* sampling frequency (Hz) */ - unsigned short channels; /* number of channels */ - unsigned short length; /* number of samples per channel */ - mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */ -}; - -struct mad_synth { - mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ - /* [ch][eo][peo][s][v] */ - - unsigned int phase; /* current processing phase */ - - struct mad_pcm pcm; /* PCM output */ -}; - -/* single channel PCM selector */ -enum { - MAD_PCM_CHANNEL_SINGLE = 0 -}; - -/* dual channel PCM selector */ -enum { - MAD_PCM_CHANNEL_DUAL_1 = 0, - MAD_PCM_CHANNEL_DUAL_2 = 1 -}; - -/* stereo PCM selector */ -enum { - MAD_PCM_CHANNEL_STEREO_LEFT = 0, - MAD_PCM_CHANNEL_STEREO_RIGHT = 1 -}; - -void mad_synth_init(struct mad_synth *); - -# define mad_synth_finish(synth) /* nothing */ - -void mad_synth_mute(struct mad_synth *); - -void mad_synth_frame(struct mad_synth *, struct mad_frame const *); - -# endif diff --git a/libmad/src/timer.c b/libmad/src/timer.c deleted file mode 100644 index 4b909ab..0000000 --- a/libmad/src/timer.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: timer.c,v 1.18 2004/01/23 09:41:33 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include - -# ifdef HAVE_ASSERT_H -# include -# endif - -# include "timer.h" - -mad_timer_t const mad_timer_zero = { 0, 0 }; - -/* - * NAME: timer->compare() - * DESCRIPTION: indicate relative order of two timers - */ -int mad_timer_compare(mad_timer_t timer1, mad_timer_t timer2) -{ - signed long diff; - - diff = timer1.seconds - timer2.seconds; - if (diff < 0) - return -1; - else if (diff > 0) - return +1; - - diff = timer1.fraction - timer2.fraction; - if (diff < 0) - return -1; - else if (diff > 0) - return +1; - - return 0; -} - -/* - * NAME: timer->negate() - * DESCRIPTION: invert the sign of a timer - */ -void mad_timer_negate(mad_timer_t *timer) -{ - timer->seconds = -timer->seconds; - - if (timer->fraction) { - timer->seconds -= 1; - timer->fraction = MAD_TIMER_RESOLUTION - timer->fraction; - } -} - -/* - * NAME: timer->abs() - * DESCRIPTION: return the absolute value of a timer - */ -mad_timer_t mad_timer_abs(mad_timer_t timer) -{ - if (timer.seconds < 0) - mad_timer_negate(&timer); - - return timer; -} - -/* - * NAME: reduce_timer() - * DESCRIPTION: carry timer fraction into seconds - */ -static -void reduce_timer(mad_timer_t *timer) -{ - timer->seconds += timer->fraction / MAD_TIMER_RESOLUTION; - timer->fraction %= MAD_TIMER_RESOLUTION; -} - -/* - * NAME: gcd() - * DESCRIPTION: compute greatest common denominator - */ -static -unsigned long gcd(unsigned long num1, unsigned long num2) -{ - unsigned long tmp; - - while (num2) { - tmp = num2; - num2 = num1 % num2; - num1 = tmp; - } - - return num1; -} - -/* - * NAME: reduce_rational() - * DESCRIPTION: convert rational expression to lowest terms - */ -static -void reduce_rational(unsigned long *numer, unsigned long *denom) -{ - unsigned long factor; - - factor = gcd(*numer, *denom); - - assert(factor != 0); - - *numer /= factor; - *denom /= factor; -} - -/* - * NAME: scale_rational() - * DESCRIPTION: solve numer/denom == ?/scale avoiding overflowing - */ -static -unsigned long scale_rational(unsigned long numer, unsigned long denom, - unsigned long scale) -{ - reduce_rational(&numer, &denom); - reduce_rational(&scale, &denom); - - assert(denom != 0); - - if (denom < scale) - return numer * (scale / denom) + numer * (scale % denom) / denom; - if (denom < numer) - return scale * (numer / denom) + scale * (numer % denom) / denom; - - return numer * scale / denom; -} - -/* - * NAME: timer->set() - * DESCRIPTION: set timer to specific (positive) value - */ -void mad_timer_set(mad_timer_t *timer, unsigned long seconds, - unsigned long numer, unsigned long denom) -{ - timer->seconds = seconds; - if (numer >= denom && denom > 0) { - timer->seconds += numer / denom; - numer %= denom; - } - - switch (denom) { - case 0: - case 1: - timer->fraction = 0; - break; - - case MAD_TIMER_RESOLUTION: - timer->fraction = numer; - break; - - case 1000: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 1000); - break; - - case 8000: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 8000); - break; - - case 11025: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 11025); - break; - - case 12000: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 12000); - break; - - case 16000: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 16000); - break; - - case 22050: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 22050); - break; - - case 24000: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 24000); - break; - - case 32000: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 32000); - break; - - case 44100: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 44100); - break; - - case 48000: - timer->fraction = numer * (MAD_TIMER_RESOLUTION / 48000); - break; - - default: - timer->fraction = scale_rational(numer, denom, MAD_TIMER_RESOLUTION); - break; - } - - if (timer->fraction >= MAD_TIMER_RESOLUTION) - reduce_timer(timer); -} - -/* - * NAME: timer->add() - * DESCRIPTION: add one timer to another - */ -void mad_timer_add(mad_timer_t *timer, mad_timer_t incr) -{ - timer->seconds += incr.seconds; - timer->fraction += incr.fraction; - - if (timer->fraction >= MAD_TIMER_RESOLUTION) - reduce_timer(timer); -} - -/* - * NAME: timer->multiply() - * DESCRIPTION: multiply a timer by a scalar value - */ -void mad_timer_multiply(mad_timer_t *timer, signed long scalar) -{ - mad_timer_t addend; - unsigned long factor; - - factor = scalar; - if (scalar < 0) { - factor = -scalar; - mad_timer_negate(timer); - } - - addend = *timer; - *timer = mad_timer_zero; - - while (factor) { - if (factor & 1) - mad_timer_add(timer, addend); - - mad_timer_add(&addend, addend); - factor >>= 1; - } -} - -/* - * NAME: timer->count() - * DESCRIPTION: return timer value in selected units - */ -signed long mad_timer_count(mad_timer_t timer, enum mad_units units) -{ - switch (units) { - case MAD_UNITS_HOURS: - return timer.seconds / 60 / 60; - - case MAD_UNITS_MINUTES: - return timer.seconds / 60; - - case MAD_UNITS_SECONDS: - return timer.seconds; - - case MAD_UNITS_DECISECONDS: - case MAD_UNITS_CENTISECONDS: - case MAD_UNITS_MILLISECONDS: - - case MAD_UNITS_8000_HZ: - case MAD_UNITS_11025_HZ: - case MAD_UNITS_12000_HZ: - case MAD_UNITS_16000_HZ: - case MAD_UNITS_22050_HZ: - case MAD_UNITS_24000_HZ: - case MAD_UNITS_32000_HZ: - case MAD_UNITS_44100_HZ: - case MAD_UNITS_48000_HZ: - - case MAD_UNITS_24_FPS: - case MAD_UNITS_25_FPS: - case MAD_UNITS_30_FPS: - case MAD_UNITS_48_FPS: - case MAD_UNITS_50_FPS: - case MAD_UNITS_60_FPS: - case MAD_UNITS_75_FPS: - return timer.seconds * (signed long) units + - (signed long) scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, - units); - - case MAD_UNITS_23_976_FPS: - case MAD_UNITS_24_975_FPS: - case MAD_UNITS_29_97_FPS: - case MAD_UNITS_47_952_FPS: - case MAD_UNITS_49_95_FPS: - case MAD_UNITS_59_94_FPS: - return (mad_timer_count(timer, -units) + 1) * 1000 / 1001; - } - - /* unsupported units */ - return 0; -} - -/* - * NAME: timer->fraction() - * DESCRIPTION: return fractional part of timer in arbitrary terms - */ -unsigned long mad_timer_fraction(mad_timer_t timer, unsigned long denom) -{ - timer = mad_timer_abs(timer); - - switch (denom) { - case 0: - return timer.fraction ? - MAD_TIMER_RESOLUTION / timer.fraction : MAD_TIMER_RESOLUTION + 1; - - case MAD_TIMER_RESOLUTION: - return timer.fraction; - - default: - return scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, denom); - } -} - -/* - * NAME: timer->string() - * DESCRIPTION: write a string representation of a timer using a template - */ -void mad_timer_string(mad_timer_t timer, - char *dest, char const *format, enum mad_units units, - enum mad_units fracunits, unsigned long subparts) -{ - unsigned long hours, minutes, seconds, sub; - unsigned int frac; - - timer = mad_timer_abs(timer); - - seconds = timer.seconds; - frac = sub = 0; - - switch (fracunits) { - case MAD_UNITS_HOURS: - case MAD_UNITS_MINUTES: - case MAD_UNITS_SECONDS: - break; - - case MAD_UNITS_DECISECONDS: - case MAD_UNITS_CENTISECONDS: - case MAD_UNITS_MILLISECONDS: - - case MAD_UNITS_8000_HZ: - case MAD_UNITS_11025_HZ: - case MAD_UNITS_12000_HZ: - case MAD_UNITS_16000_HZ: - case MAD_UNITS_22050_HZ: - case MAD_UNITS_24000_HZ: - case MAD_UNITS_32000_HZ: - case MAD_UNITS_44100_HZ: - case MAD_UNITS_48000_HZ: - - case MAD_UNITS_24_FPS: - case MAD_UNITS_25_FPS: - case MAD_UNITS_30_FPS: - case MAD_UNITS_48_FPS: - case MAD_UNITS_50_FPS: - case MAD_UNITS_60_FPS: - case MAD_UNITS_75_FPS: - { - unsigned long denom; - - denom = MAD_TIMER_RESOLUTION / fracunits; - - frac = timer.fraction / denom; - sub = scale_rational(timer.fraction % denom, denom, subparts); - } - break; - - case MAD_UNITS_23_976_FPS: - case MAD_UNITS_24_975_FPS: - case MAD_UNITS_29_97_FPS: - case MAD_UNITS_47_952_FPS: - case MAD_UNITS_49_95_FPS: - case MAD_UNITS_59_94_FPS: - /* drop-frame encoding */ - /* N.B. this is only well-defined for MAD_UNITS_29_97_FPS */ - { - unsigned long frame, cycle, d, m; - - frame = mad_timer_count(timer, fracunits); - - cycle = -fracunits * 60 * 10 - (10 - 1) * 2; - - d = frame / cycle; - m = frame % cycle; - frame += (10 - 1) * 2 * d; - if (m > 2) - frame += 2 * ((m - 2) / (cycle / 10)); - - frac = frame % -fracunits; - seconds = frame / -fracunits; - } - break; - } - - switch (units) { - case MAD_UNITS_HOURS: - minutes = seconds / 60; - hours = minutes / 60; - - sprintf(dest, format, - hours, - (unsigned int) (minutes % 60), - (unsigned int) (seconds % 60), - frac, sub); - break; - - case MAD_UNITS_MINUTES: - minutes = seconds / 60; - - sprintf(dest, format, - minutes, - (unsigned int) (seconds % 60), - frac, sub); - break; - - case MAD_UNITS_SECONDS: - sprintf(dest, format, - seconds, - frac, sub); - break; - - case MAD_UNITS_23_976_FPS: - case MAD_UNITS_24_975_FPS: - case MAD_UNITS_29_97_FPS: - case MAD_UNITS_47_952_FPS: - case MAD_UNITS_49_95_FPS: - case MAD_UNITS_59_94_FPS: - if (fracunits < 0) { - /* not yet implemented */ - sub = 0; - } - - /* fall through */ - - case MAD_UNITS_DECISECONDS: - case MAD_UNITS_CENTISECONDS: - case MAD_UNITS_MILLISECONDS: - - case MAD_UNITS_8000_HZ: - case MAD_UNITS_11025_HZ: - case MAD_UNITS_12000_HZ: - case MAD_UNITS_16000_HZ: - case MAD_UNITS_22050_HZ: - case MAD_UNITS_24000_HZ: - case MAD_UNITS_32000_HZ: - case MAD_UNITS_44100_HZ: - case MAD_UNITS_48000_HZ: - - case MAD_UNITS_24_FPS: - case MAD_UNITS_25_FPS: - case MAD_UNITS_30_FPS: - case MAD_UNITS_48_FPS: - case MAD_UNITS_50_FPS: - case MAD_UNITS_60_FPS: - case MAD_UNITS_75_FPS: - sprintf(dest, format, mad_timer_count(timer, units), sub); - break; - } -} diff --git a/libmad/src/timer.h b/libmad/src/timer.h deleted file mode 100644 index eb4542b..0000000 --- a/libmad/src/timer.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: timer.h,v 1.16 2004/01/23 09:41:33 rob Exp $ - */ - -# ifndef LIBMAD_TIMER_H -# define LIBMAD_TIMER_H - -typedef struct { - signed long seconds; /* whole seconds */ - unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */ -} mad_timer_t; - -extern mad_timer_t const mad_timer_zero; - -# define MAD_TIMER_RESOLUTION 352800000UL - -enum mad_units { - MAD_UNITS_HOURS = -2, - MAD_UNITS_MINUTES = -1, - MAD_UNITS_SECONDS = 0, - - /* metric units */ - - MAD_UNITS_DECISECONDS = 10, - MAD_UNITS_CENTISECONDS = 100, - MAD_UNITS_MILLISECONDS = 1000, - - /* audio sample units */ - - MAD_UNITS_8000_HZ = 8000, - MAD_UNITS_11025_HZ = 11025, - MAD_UNITS_12000_HZ = 12000, - - MAD_UNITS_16000_HZ = 16000, - MAD_UNITS_22050_HZ = 22050, - MAD_UNITS_24000_HZ = 24000, - - MAD_UNITS_32000_HZ = 32000, - MAD_UNITS_44100_HZ = 44100, - MAD_UNITS_48000_HZ = 48000, - - /* video frame/field units */ - - MAD_UNITS_24_FPS = 24, - MAD_UNITS_25_FPS = 25, - MAD_UNITS_30_FPS = 30, - MAD_UNITS_48_FPS = 48, - MAD_UNITS_50_FPS = 50, - MAD_UNITS_60_FPS = 60, - - /* CD audio frames */ - - MAD_UNITS_75_FPS = 75, - - /* video drop-frame units */ - - MAD_UNITS_23_976_FPS = -24, - MAD_UNITS_24_975_FPS = -25, - MAD_UNITS_29_97_FPS = -30, - MAD_UNITS_47_952_FPS = -48, - MAD_UNITS_49_95_FPS = -50, - MAD_UNITS_59_94_FPS = -60 -}; - -# define mad_timer_reset(timer) ((void) (*(timer) = mad_timer_zero)) - -int mad_timer_compare(mad_timer_t, mad_timer_t); - -# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero) - -void mad_timer_negate(mad_timer_t *); -mad_timer_t mad_timer_abs(mad_timer_t); - -void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long); -void mad_timer_add(mad_timer_t *, mad_timer_t); -void mad_timer_multiply(mad_timer_t *, signed long); - -signed long mad_timer_count(mad_timer_t, enum mad_units); -unsigned long mad_timer_fraction(mad_timer_t, unsigned long); -void mad_timer_string(mad_timer_t, char *, char const *, - enum mad_units, enum mad_units, unsigned long); - -# endif diff --git a/libmad/src/version.c b/libmad/src/version.c deleted file mode 100644 index e643fa7..0000000 --- a/libmad/src/version.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: version.c,v 1.15 2004/01/23 09:41:33 rob Exp $ - */ - -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include "version.h" - -char const mad_version[] = "MPEG Audio Decoder " MAD_VERSION; -char const mad_copyright[] = "Copyright (C) " MAD_PUBLISHYEAR " " MAD_AUTHOR; -char const mad_author[] = MAD_AUTHOR " <" MAD_EMAIL ">"; - -char const mad_build[] = "" -# if defined(DEBUG) - "DEBUG " -# elif defined(NDEBUG) - "NDEBUG " -# endif - -# if defined(EXPERIMENTAL) - "EXPERIMENTAL " -# endif - -# if defined(FPM_64BIT) - "FPM_64BIT " -# elif defined(FPM_INTEL) - "FPM_INTEL " -# elif defined(FPM_ARM) - "FPM_ARM " -# elif defined(FPM_MIPS) - "FPM_MIPS " -# elif defined(FPM_SPARC) - "FPM_SPARC " -# elif defined(FPM_PPC) - "FPM_PPC " -# elif defined(FPM_DEFAULT) - "FPM_DEFAULT " -# endif - -# if defined(ASO_IMDCT) - "ASO_IMDCT " -# endif -# if defined(ASO_INTERLEAVE1) - "ASO_INTERLEAVE1 " -# endif -# if defined(ASO_INTERLEAVE2) - "ASO_INTERLEAVE2 " -# endif -# if defined(ASO_ZEROCHECK) - "ASO_ZEROCHECK " -# endif - -# if defined(OPT_SPEED) - "OPT_SPEED " -# elif defined(OPT_ACCURACY) - "OPT_ACCURACY " -# endif - -# if defined(OPT_SSO) - "OPT_SSO " -# endif - -# if defined(OPT_DCTO) /* never defined here */ - "OPT_DCTO " -# endif - -# if defined(OPT_STRICT) - "OPT_STRICT " -# endif -; diff --git a/libmad/src/version.h b/libmad/src/version.h deleted file mode 100644 index d215d4c..0000000 --- a/libmad/src/version.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: version.h,v 1.26 2004/01/23 09:41:33 rob Exp $ - */ - -# ifndef LIBMAD_VERSION_H -# define LIBMAD_VERSION_H - -# define MAD_VERSION_MAJOR 0 -# define MAD_VERSION_MINOR 15 -# define MAD_VERSION_PATCH 1 -# define MAD_VERSION_EXTRA " (beta)" - -# define MAD_VERSION_STRINGIZE(str) #str -# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) - -# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \ - MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \ - MAD_VERSION_STRING(MAD_VERSION_PATCH) \ - MAD_VERSION_EXTRA - -# define MAD_PUBLISHYEAR "2000-2004" -# define MAD_AUTHOR "Underbit Technologies, Inc." -# define MAD_EMAIL "info@underbit.com" - -extern char const mad_version[]; -extern char const mad_copyright[]; -extern char const mad_author[]; -extern char const mad_build[]; - -# endif diff --git a/pianobar/resources/pianobar.ico b/pianobar/resources/pianobar.ico new file mode 100644 index 0000000..2ec5aa5 Binary files /dev/null and b/pianobar/resources/pianobar.ico differ diff --git a/pianobar/resources/pianobar.rc b/pianobar/resources/pianobar.rc new file mode 100644 index 0000000..fe31bfa --- /dev/null +++ b/pianobar/resources/pianobar.rc @@ -0,0 +1,36 @@ +#include "../src/src/config.h" + +MAINICON ICON "pianobar.ico" + +1 VERSIONINFO +FILEVERSION 1,0,0,0 +//PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_BUILD,VERSION_REV +FILEFLAGSMASK 0X3FL +FILEFLAGS 0L +FILEOS 0X40004L +FILETYPE 0X1 +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "Ported to Windows by Micha Cicho " + //VALUE "FileVersion", BUILD_VERSION + VALUE "ProductVersion", VERSION +#ifdef _DEBUG + VALUE "OriginalFilename", PACKAGE "-debug.exe" +#else + VALUE "OriginalFilename", PACKAGE ".exe" +#endif + VALUE "FileDescription", "Pandora Radio Client" + VALUE "LegalCopyright", "Copyright (C) 2011-2015, Lars-Dominik Braun " + VALUE "ProductName", "pianobar - Pandora Radio Client" + VALUE "PrivateBuild", "Micha Cicho " + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04B0 + END +END diff --git a/polarssl/polarssl.vcxproj b/polarssl/polarssl.vcxproj deleted file mode 100644 index 8928310..0000000 --- a/polarssl/polarssl.vcxproj +++ /dev/null @@ -1,271 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60} - polarssl - Win32Proj - - - - StaticLibrary - NotSet - true - v110_xp - - - StaticLibrary - NotSet - v110_xp - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)build\temp\lib\ - $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ - $(SolutionDir)build\temp\lib\ - $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ - AllRules.ruleset - - - AllRules.ruleset - - - $(ProjectName)-mt-debug - $(ProjectName)-mt - - - - Disabled - false - $(SolutionDir)compatibility;$(ProjectDir)src\include;%(AdditionalIncludeDirectories) - _WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;BUILDING_CYASSL;NO_HC128;NO_PSK;NO_FILESYSTEM;DEBUG_CYASSL;%(PreprocessorDefinitions) - false - - - Default - MultiThreadedDebug - - - Level3 - OldStyle - - - - - xcopy "$(ProjectDir)src\include\polarssl\aes.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\arc4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\asn1.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\asn1write.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\base64.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\bignum.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\bn_mul.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\camellia.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\certs.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\cipher.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\cipher_wrap.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\config.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\ctr_drbg.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\debug.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\des.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\dhm.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\entropy.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\entropy_poll.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\error.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\gcm.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\havege.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md_wrap.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md2.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md5.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\net.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\openssl.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\padlock.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\pem.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\pkcs11.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\rsa.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\sha1.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\sha2.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\sha4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\ssl.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\timing.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\version.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\x509.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\x509write.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\xtea.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D - - - - - MaxSpeed - AnySuitable - false - false - $(SolutionDir)compatibility;$(ProjectDir)src\include;%(AdditionalIncludeDirectories) - _WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;BUILDING_CYASSL;NO_HC128;NO_PSK;NO_FILESYSTEM;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - - - Level3 - - - - - - - xcopy "$(ProjectDir)src\include\polarssl\aes.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\arc4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\asn1.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\asn1write.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\base64.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\bignum.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\bn_mul.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\camellia.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\certs.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\cipher.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\cipher_wrap.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\config.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\ctr_drbg.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\debug.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\des.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\dhm.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\entropy.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\entropy_poll.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\error.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\gcm.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\havege.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md_wrap.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md2.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\md5.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\net.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\openssl.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\padlock.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\pem.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\pkcs11.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\rsa.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\sha1.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\sha2.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\sha4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\ssl.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\timing.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\version.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\x509.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\x509write.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D -xcopy "$(ProjectDir)src\include\polarssl\xtea.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/polarssl/polarssl.vcxproj.filters b/polarssl/polarssl.vcxproj.filters deleted file mode 100644 index 8c5076d..0000000 --- a/polarssl/polarssl.vcxproj.filters +++ /dev/null @@ -1,258 +0,0 @@ - - - - - {93cd31ac-6f98-4ce9-a880-42c25c8d340d} - - - {6040e80f-2dd1-4f7a-8b5b-53587ddc714d} - - - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - src - - - \ No newline at end of file diff --git a/polarssl/src/LICENSE b/polarssl/src/LICENSE deleted file mode 100644 index d511905..0000000 --- a/polarssl/src/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/polarssl/src/include/polarssl/aes.h b/polarssl/src/include/polarssl/aes.h deleted file mode 100644 index 80fd6d9..0000000 --- a/polarssl/src/include/polarssl/aes.h +++ /dev/null @@ -1,176 +0,0 @@ -/** - * \file aes.h - * - * \brief AES block cipher - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_AES_H -#define POLARSSL_AES_H - -#include - -#define AES_ENCRYPT 1 -#define AES_DECRYPT 0 - -#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ -#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ - -/** - * \brief AES context structure - */ -typedef struct -{ - int nr; /*!< number of rounds */ - unsigned long *rk; /*!< AES round keys */ - unsigned long buf[68]; /*!< unaligned data */ -} -aes_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief AES key schedule (encryption) - * - * \param ctx AES context to be initialized - * \param key encryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH - */ -int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ); - -/** - * \brief AES key schedule (decryption) - * - * \param ctx AES context to be initialized - * \param key decryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH - */ -int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ); - -/** - * \brief AES-ECB block encryption/decryption - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if successful - */ -int aes_crypt_ecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief AES-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH - */ -int aes_crypt_cbc( aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief AES-CFB128 buffer encryption/decryption. - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. - * - * both - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int aes_crypt_cfb128( aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/* - * \brief AES-CTR buffer encryption/decryption - * - * Warning: You have to keep the maximum use of your counter in mind! - * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. - * - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful - */ -int aes_crypt_ctr( aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ); -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int aes_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* aes.h */ diff --git a/polarssl/src/include/polarssl/arc4.h b/polarssl/src/include/polarssl/arc4.h deleted file mode 100644 index 48ad60b..0000000 --- a/polarssl/src/include/polarssl/arc4.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * \file arc4.h - * - * \brief The ARCFOUR stream cipher - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_ARC4_H -#define POLARSSL_ARC4_H - -#include - -/** - * \brief ARC4 context structure - */ -typedef struct -{ - int x; /*!< permutation index */ - int y; /*!< permutation index */ - unsigned char m[256]; /*!< permutation table */ -} -arc4_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief ARC4 key schedule - * - * \param ctx ARC4 context to be initialized - * \param key the secret key - * \param keylen length of the key - */ -void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen ); - -/** - * \brief ARC4 cipher function - * - * \param ctx ARC4 context - * \param length length of the input data - * \param input buffer holding the input data - * \param output buffer for the output data - * - * \return 0 if successful - */ -int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input, - unsigned char *output ); - -/* - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int arc4_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* arc4.h */ diff --git a/polarssl/src/include/polarssl/asn1.h b/polarssl/src/include/polarssl/asn1.h deleted file mode 100644 index 893292d..0000000 --- a/polarssl/src/include/polarssl/asn1.h +++ /dev/null @@ -1,246 +0,0 @@ -/** - * \file asn1.h - * - * \brief Generic ASN.1 parsing - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_ASN1_H -#define POLARSSL_ASN1_H - -#include "config.h" - -#if defined(POLARSSL_BIGNUM_C) -#include "bignum.h" -#endif - -#include - -/** - * \addtogroup asn1_module - * \{ - */ - -/** - * \name ASN1 Error codes - * These error codes are OR'ed to X509 error codes for - * higher error granularity. - * ASN1 is a standard to specify data structures. - * \{ - */ -#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ -#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ -#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ -#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ -#define POLARSSL_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ -#define POLARSSL_ERR_ASN1_MALLOC_FAILED -0x006A /**< Memory allocation failed */ -#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ - -/* \} name */ - -/** - * \name DER constants - * These constants comply with DER encoded the ANS1 type tags. - * DER encoding uses hexadecimal representation. - * An example DER sequence is:\n - * - 0x02 -- tag indicating INTEGER - * - 0x01 -- length in octets - * - 0x05 -- value - * Such sequences are typically read into \c ::x509_buf. - * \{ - */ -#define ASN1_BOOLEAN 0x01 -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_OCTET_STRING 0x04 -#define ASN1_NULL 0x05 -#define ASN1_OID 0x06 -#define ASN1_UTF8_STRING 0x0C -#define ASN1_SEQUENCE 0x10 -#define ASN1_SET 0x11 -#define ASN1_PRINTABLE_STRING 0x13 -#define ASN1_T61_STRING 0x14 -#define ASN1_IA5_STRING 0x16 -#define ASN1_UTC_TIME 0x17 -#define ASN1_GENERALIZED_TIME 0x18 -#define ASN1_UNIVERSAL_STRING 0x1C -#define ASN1_BMP_STRING 0x1E -#define ASN1_PRIMITIVE 0x00 -#define ASN1_CONSTRUCTED 0x20 -#define ASN1_CONTEXT_SPECIFIC 0x80 -/* \} name */ -/* \} addtogroup asn1_module */ - -/** Returns the size of the binary string, without the trailing \\0 */ -#define OID_SIZE(x) (sizeof(x) - 1) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name Functions to parse ASN.1 data structures - * \{ - */ - -/** - * Type-length-value structure that allows for ASN1 using DER. - */ -typedef struct _asn1_buf -{ - int tag; /**< ASN1 type, e.g. ASN1_UTF8_STRING. */ - size_t len; /**< ASN1 length, e.g. in octets. */ - unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ -} -asn1_buf; - -/** - * Container for ASN1 bit strings. - */ -typedef struct _asn1_bitstring -{ - size_t len; /**< ASN1 length, e.g. in octets. */ - unsigned char unused_bits; /**< Number of unused bits at the end of the string */ - unsigned char *p; /**< Raw ASN1 data for the bit string */ -} -asn1_bitstring; - -/** - * Container for a sequence of ASN.1 items - */ -typedef struct _asn1_sequence -{ - asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ - struct _asn1_sequence *next; /**< The next entry in the sequence. */ -} -asn1_sequence; - -/** - * Get the length of an ASN.1 element. - * Updates the pointer to immediately behind the length. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param len The variable that will receive the value - * - * \return 0 if successful, POLARSSL_ERR_ASN1_OUT_OF_DATA on reaching - * end of data, POLARSSL_ERR_ASN1_INVALID_LENGTH if length is - * unparseable. - */ -int asn1_get_len( unsigned char **p, - const unsigned char *end, - size_t *len ); - -/** - * Get the tag and length of the tag. Check for the requested tag. - * Updates the pointer to immediately behind the tag and length. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param len The variable that will receive the length - * \param tag The expected tag - * - * \return 0 if successful, POLARSSL_ERR_ASN1_UNEXPECTED_TAG if tag did - * not match requested tag, or another specific ASN.1 error code. - */ -int asn1_get_tag( unsigned char **p, - const unsigned char *end, - size_t *len, int tag ); - -/** - * Retrieve a boolean ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param val The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int asn1_get_bool( unsigned char **p, - const unsigned char *end, - int *val ); - -/** - * Retrieve an integer ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param val The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int asn1_get_int( unsigned char **p, - const unsigned char *end, - int *val ); - -/** - * Retrieve a bitstring ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param bs The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int asn1_get_bitstring( unsigned char **p, const unsigned char *end, - asn1_bitstring *bs); - -/** - * Parses and splits an ASN.1 "SEQUENCE OF " - * Updated the pointer to immediately behind the full sequence tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param cur First variable in the chain to fill - * \param tag Type of sequence - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int asn1_get_sequence_of( unsigned char **p, - const unsigned char *end, - asn1_sequence *cur, - int tag); - -#if defined(POLARSSL_BIGNUM_C) -/** - * Retrieve a MPI value from an integer ASN.1 tag. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param X The MPI that will receive the value - * - * \return 0 if successful or a specific ASN.1 or MPI error code. - */ -int asn1_get_mpi( unsigned char **p, - const unsigned char *end, - mpi *X ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* asn1.h */ diff --git a/polarssl/src/include/polarssl/asn1write.h b/polarssl/src/include/polarssl/asn1write.h deleted file mode 100644 index 52b9baa..0000000 --- a/polarssl/src/include/polarssl/asn1write.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * \file asn1write.h - * - * \brief ASN.1 buffer writing functionality - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_ASN1_WRITE_H -#define POLARSSL_ASN1_WRITE_H - -#include "asn1.h" - -#define ASN1_CHK_ADD(g, f) if( ( ret = f ) < 0 ) return( ret ); else g += ret - -int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); -int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ); -int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ); -int asn1_write_null( unsigned char **p, unsigned char *start ); -int asn1_write_oid( unsigned char **p, unsigned char *start, char *oid ); -int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, char *algorithm_oid ); -int asn1_write_int( unsigned char **p, unsigned char *start, int val ); -int asn1_write_printable_string( unsigned char **p, unsigned char *start, - char *text ); -int asn1_write_ia5_string( unsigned char **p, unsigned char *start, - char *text ); - -#endif /* POLARSSL_ASN1_WRITE_H */ diff --git a/polarssl/src/include/polarssl/base64.h b/polarssl/src/include/polarssl/base64.h deleted file mode 100644 index 883215d..0000000 --- a/polarssl/src/include/polarssl/base64.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * \file base64.h - * - * \brief RFC 1521 base64 encoding/decoding - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_BASE64_H -#define POLARSSL_BASE64_H - -#include - -#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ -#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Encode a buffer into base64 format - * - * \param dst destination buffer - * \param dlen size of the buffer - * \param src source buffer - * \param slen amount of data to be encoded - * - * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. - * *dlen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with *dlen = 0 to obtain the - * required buffer size in *dlen - */ -int base64_encode( unsigned char *dst, size_t *dlen, - const unsigned char *src, size_t slen ); - -/** - * \brief Decode a base64-formatted buffer - * - * \param dst destination buffer - * \param dlen size of the buffer - * \param src source buffer - * \param slen amount of data to be decoded - * - * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or - * POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not - * correct. *dlen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with *dlen = 0 to obtain the - * required buffer size in *dlen - */ -int base64_decode( unsigned char *dst, size_t *dlen, - const unsigned char *src, size_t slen ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int base64_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* base64.h */ diff --git a/polarssl/src/include/polarssl/bignum.h b/polarssl/src/include/polarssl/bignum.h deleted file mode 100644 index ad03308..0000000 --- a/polarssl/src/include/polarssl/bignum.h +++ /dev/null @@ -1,632 +0,0 @@ -/** - * \file bignum.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_BIGNUM_H -#define POLARSSL_BIGNUM_H - -#include -#include - -#include "config.h" - -#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ -#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ -#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ -#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ -#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ -#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ -#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ -#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */ - -#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup - -/* - * Maximum size MPIs are allowed to grow to in number of limbs. - */ -#define POLARSSL_MPI_MAX_LIMBS 10000 - -/* - * Maximum window size used for modular exponentiation. Default: 6 - * Minimum value: 1. Maximum value: 6. - * - * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used - * for the sliding window calculation. (So 64 by default) - * - * Reduction in size, reduces speed. - */ -#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ - -/* - * Maximum size of MPIs allowed in bits and bytes for user-MPIs. - * ( Default: 512 bytes => 4096 bits ) - * - * Note: Calculations can results temporarily in larger MPIs. So the number - * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher. - */ -#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ -#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ - -/* - * When reading from files with mpi_read_file() the buffer should have space - * for a (short) label, the MPI (in the provided radix), the newline - * characters and the '\0'. - * - * By default we assume at least a 10 char label, a minimum radix of 10 - * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). - */ -#define POLARSSL_MPI_READ_BUFFER_SIZE 1250 - -/* - * Define the base integer type, architecture-wise - */ -#if defined(POLARSSL_HAVE_INT8) -typedef signed char t_sint; -typedef unsigned char t_uint; -typedef unsigned short t_udbl; -#else -#if defined(POLARSSL_HAVE_INT16) -typedef signed short t_sint; -typedef unsigned short t_uint; -typedef unsigned long t_udbl; -#else - typedef signed long t_sint; - typedef unsigned long t_uint; - #if defined(_MSC_VER) && defined(_M_IX86) - typedef unsigned __int64 t_udbl; - #else - #if defined(__GNUC__) && ( \ - defined(__amd64__) || defined(__x86_64__) || \ - defined(__ppc64__) || defined(__powerpc64__) || \ - defined(__ia64__) || defined(__alpha__) || \ - (defined(__sparc__) && defined(__arch64__)) || \ - defined(__s390x__) ) - typedef unsigned int t_udbl __attribute__((mode(TI))); - #define POLARSSL_HAVE_LONGLONG - #else - #if defined(POLARSSL_HAVE_LONGLONG) - typedef unsigned long long t_udbl; - #endif - #endif - #endif -#endif -#endif - -/** - * \brief MPI structure - */ -typedef struct -{ - int s; /*!< integer sign */ - size_t n; /*!< total # of limbs */ - t_uint *p; /*!< pointer to limbs */ -} -mpi; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Initialize one MPI - * - * \param X One MPI to initialize. - */ -void mpi_init( mpi *X ); - -/** - * \brief Unallocate one MPI - * - * \param X One MPI to unallocate. - */ -void mpi_free( mpi *X ); - -/** - * \brief Enlarge to the specified number of limbs - * - * \param X MPI to grow - * \param nblimbs The target number of limbs - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_grow( mpi *X, size_t nblimbs ); - -/** - * \brief Copy the contents of Y into X - * - * \param X Destination MPI - * \param Y Source MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_copy( mpi *X, const mpi *Y ); - -/** - * \brief Swap the contents of X and Y - * - * \param X First MPI value - * \param Y Second MPI value - */ -void mpi_swap( mpi *X, mpi *Y ); - -/** - * \brief Set value from integer - * - * \param X MPI to set - * \param z Value to use - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_lset( mpi *X, t_sint z ); - -/* - * \brief Get a specific bit from X - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * - * \return Either a 0 or a 1 - */ -int mpi_get_bit( mpi *X, size_t pos ); - -/* - * \brief Set a bit of X to a specific value of 0 or 1 - * - * \note Will grow X if necessary to set a bit to 1 in a not yet - * existing limb. Will not grow if bit should be set to 0 - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * \param val The value to set the bit to (0 or 1) - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 - */ -int mpi_set_bit( mpi *X, size_t pos, unsigned char val ); - -/** - * \brief Return the number of least significant bits - * - * \param X MPI to use - */ -size_t mpi_lsb( const mpi *X ); - -/** - * \brief Return the number of most significant bits - * - * \param X MPI to use - */ -size_t mpi_msb( const mpi *X ); - -/** - * \brief Return the total size in bytes - * - * \param X MPI to use - */ -size_t mpi_size( const mpi *X ); - -/** - * \brief Import from an ASCII string - * - * \param X Destination MPI - * \param radix Input numeric base - * \param s Null-terminated string buffer - * - * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code - */ -int mpi_read_string( mpi *X, int radix, const char *s ); - -/** - * \brief Export into an ASCII string - * - * \param X Source MPI - * \param radix Output numeric base - * \param s String buffer - * \param slen String buffer size - * - * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code. - * *slen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with *slen = 0 to obtain the - * minimum required buffer size in *slen. - */ -int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ); - -/** - * \brief Read X from an opened file - * - * \param X Destination MPI - * \param radix Input numeric base - * \param fin Input file handle - * - * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if - * the file read buffer is too small or a - * POLARSSL_ERR_MPI_XXX error code - */ -int mpi_read_file( mpi *X, int radix, FILE *fin ); - -/** - * \brief Write X into an opened file, or stdout if fout is NULL - * - * \param p Prefix, can be NULL - * \param X Source MPI - * \param radix Output numeric base - * \param fout Output file handle (can be NULL) - * - * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code - * - * \note Set fout == NULL to print X on the console. - */ -int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ); - -/** - * \brief Import X from unsigned binary data, big endian - * - * \param X Destination MPI - * \param buf Input buffer - * \param buflen Input buffer size - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ); - -/** - * \brief Export X into unsigned binary data, big endian - * - * \param X Source MPI - * \param buf Output buffer - * \param buflen Output buffer size - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough - */ -int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ); - -/** - * \brief Left-shift: X <<= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_shift_l( mpi *X, size_t count ); - -/** - * \brief Right-shift: X >>= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_shift_r( mpi *X, size_t count ); - -/** - * \brief Compare unsigned values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if |X| is greater than |Y|, - * -1 if |X| is lesser than |Y| or - * 0 if |X| is equal to |Y| - */ -int mpi_cmp_abs( const mpi *X, const mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if X is greater than Y, - * -1 if X is lesser than Y or - * 0 if X is equal to Y - */ -int mpi_cmp_mpi( const mpi *X, const mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param z The integer value to compare to - * - * \return 1 if X is greater than z, - * -1 if X is lesser than z or - * 0 if X is equal to z - */ -int mpi_cmp_int( const mpi *X, t_sint z ); - -/** - * \brief Unsigned addition: X = |A| + |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Unsigned substraction: X = |A| - |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A - */ -int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed addition: X = A + B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed substraction: X = A - B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed addition: X = A + b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to add - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_add_int( mpi *X, const mpi *A, t_sint b ); - -/** - * \brief Signed substraction: X = A - b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to subtract - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_sub_int( mpi *X, const mpi *A, t_sint b ); - -/** - * \brief Baseline multiplication: X = A * B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Baseline multiplication: X = A * b - * Note: b is an unsigned integer type, thus - * Negative values of b are ignored. - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to multiply with - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_mul_int( mpi *X, const mpi *A, t_sint b ); - -/** - * \brief Division by mpi: A = Q * B + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 - * - * \note Either Q or R can be NULL. - */ -int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ); - -/** - * \brief Division by int: A = Q * b + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 - * - * \note Either Q or R can be NULL. - */ -int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ); - -/** - * \brief Modulo: R = A mod B - * - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0 - */ -int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ); - -/** - * \brief Modulo: r = A mod b - * - * \param r Destination t_uint - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0 - */ -int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ); - -/** - * \brief Sliding-window exponentiation: X = A^E mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param E Exponent MPI - * \param N Modular MPI - * \param _RR Speed-up MPI used for recalculations - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even - * - * \note _RR is used to avoid re-computing R*R mod N across - * multiple calls, which speeds up things a bit. It can - * be set to NULL if the extra performance is unneeded. - */ -int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ); - -/** - * \brief Fill an MPI X with size bytes of random - * - * \param X Destination MPI - * \param size Size in bytes - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_fill_random( mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Greatest common divisor: G = gcd(A, B) - * - * \param G Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_gcd( mpi *G, const mpi *A, const mpi *B ); - -/** - * \brief Modular inverse: X = A^-1 mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param N Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil - POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N - */ -int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ); - -/** - * \brief Miller-Rabin primality test - * - * \param X MPI to check - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime - */ -int mpi_is_prime( mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Prime number generation - * - * \param X Destination MPI - * \param nbits Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS ) - * \param dh_flag If 1, then (X-1)/2 will be prime too - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 - */ -int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mpi_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* bignum.h */ diff --git a/polarssl/src/include/polarssl/bn_mul.h b/polarssl/src/include/polarssl/bn_mul.h deleted file mode 100644 index a6a2c65..0000000 --- a/polarssl/src/include/polarssl/bn_mul.h +++ /dev/null @@ -1,742 +0,0 @@ -/** - * \file bn_mul.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * Multiply source vector [s] with b, add result - * to destination vector [d] and set carry c. - * - * Currently supports: - * - * . IA-32 (386+) . AMD64 / EM64T - * . IA-32 (SSE2) . Motorola 68000 - * . PowerPC, 32-bit . MicroBlaze - * . PowerPC, 64-bit . TriCore - * . SPARC v8 . ARM v3+ - * . Alpha . MIPS32 - * . C, longlong . C, generic - */ -#ifndef POLARSSL_BN_MUL_H -#define POLARSSL_BN_MUL_H - -#include "bignum.h" - -#if defined(POLARSSL_HAVE_ASM) - -#if defined(__GNUC__) -#if defined(__i386__) - -#define MULADDC_INIT \ - asm( " \ - movl %%ebx, %0; \ - movl %5, %%esi; \ - movl %6, %%edi; \ - movl %7, %%ecx; \ - movl %8, %%ebx; \ - " - -#define MULADDC_CORE \ - " \ - lodsl; \ - mull %%ebx; \ - addl %%ecx, %%eax; \ - adcl $0, %%edx; \ - addl (%%edi), %%eax; \ - adcl $0, %%edx; \ - movl %%edx, %%ecx; \ - stosl; \ - " - -#if defined(POLARSSL_HAVE_SSE2) - -#define MULADDC_HUIT \ - " \ - movd %%ecx, %%mm1; \ - movd %%ebx, %%mm0; \ - movd (%%edi), %%mm3; \ - paddq %%mm3, %%mm1; \ - movd (%%esi), %%mm2; \ - pmuludq %%mm0, %%mm2; \ - movd 4(%%esi), %%mm4; \ - pmuludq %%mm0, %%mm4; \ - movd 8(%%esi), %%mm6; \ - pmuludq %%mm0, %%mm6; \ - movd 12(%%esi), %%mm7; \ - pmuludq %%mm0, %%mm7; \ - paddq %%mm2, %%mm1; \ - movd 4(%%edi), %%mm3; \ - paddq %%mm4, %%mm3; \ - movd 8(%%edi), %%mm5; \ - paddq %%mm6, %%mm5; \ - movd 12(%%edi), %%mm4; \ - paddq %%mm4, %%mm7; \ - movd %%mm1, (%%edi); \ - movd 16(%%esi), %%mm2; \ - pmuludq %%mm0, %%mm2; \ - psrlq $32, %%mm1; \ - movd 20(%%esi), %%mm4; \ - pmuludq %%mm0, %%mm4; \ - paddq %%mm3, %%mm1; \ - movd 24(%%esi), %%mm6; \ - pmuludq %%mm0, %%mm6; \ - movd %%mm1, 4(%%edi); \ - psrlq $32, %%mm1; \ - movd 28(%%esi), %%mm3; \ - pmuludq %%mm0, %%mm3; \ - paddq %%mm5, %%mm1; \ - movd 16(%%edi), %%mm5; \ - paddq %%mm5, %%mm2; \ - movd %%mm1, 8(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm7, %%mm1; \ - movd 20(%%edi), %%mm5; \ - paddq %%mm5, %%mm4; \ - movd %%mm1, 12(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm2, %%mm1; \ - movd 24(%%edi), %%mm5; \ - paddq %%mm5, %%mm6; \ - movd %%mm1, 16(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm4, %%mm1; \ - movd 28(%%edi), %%mm5; \ - paddq %%mm5, %%mm3; \ - movd %%mm1, 20(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm6, %%mm1; \ - movd %%mm1, 24(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm3, %%mm1; \ - movd %%mm1, 28(%%edi); \ - addl $32, %%edi; \ - addl $32, %%esi; \ - psrlq $32, %%mm1; \ - movd %%mm1, %%ecx; \ - " - -#define MULADDC_STOP \ - " \ - emms; \ - movl %4, %%ebx; \ - movl %%ecx, %1; \ - movl %%edi, %2; \ - movl %%esi, %3; \ - " \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); - -#else - -#define MULADDC_STOP \ - " \ - movl %4, %%ebx; \ - movl %%ecx, %1; \ - movl %%edi, %2; \ - movl %%esi, %3; \ - " \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); -#endif /* SSE2 */ -#endif /* i386 */ - -#if defined(__amd64__) || defined (__x86_64__) - -#define MULADDC_INIT \ - asm( "movq %0, %%rsi " :: "m" (s)); \ - asm( "movq %0, %%rdi " :: "m" (d)); \ - asm( "movq %0, %%rcx " :: "m" (c)); \ - asm( "movq %0, %%rbx " :: "m" (b)); \ - asm( "xorq %r8, %r8 " ); - -#define MULADDC_CORE \ - asm( "movq (%rsi),%rax " ); \ - asm( "mulq %rbx " ); \ - asm( "addq $8, %rsi " ); \ - asm( "addq %rcx, %rax " ); \ - asm( "movq %r8, %rcx " ); \ - asm( "adcq $0, %rdx " ); \ - asm( "nop " ); \ - asm( "addq %rax, (%rdi) " ); \ - asm( "adcq %rdx, %rcx " ); \ - asm( "addq $8, %rdi " ); - -#define MULADDC_STOP \ - asm( "movq %%rcx, %0 " : "=m" (c)); \ - asm( "movq %%rdi, %0 " : "=m" (d)); \ - asm( "movq %%rsi, %0 " : "=m" (s) :: \ - "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" ); - -#endif /* AMD64 */ - -#if defined(__mc68020__) || defined(__mcpu32__) - -#define MULADDC_INIT \ - asm( "movl %0, %%a2 " :: "m" (s)); \ - asm( "movl %0, %%a3 " :: "m" (d)); \ - asm( "movl %0, %%d3 " :: "m" (c)); \ - asm( "movl %0, %%d2 " :: "m" (b)); \ - asm( "moveq #0, %d0 " ); - -#define MULADDC_CORE \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "moveq #0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "addxl %d4, %d3 " ); - -#define MULADDC_STOP \ - asm( "movl %%d3, %0 " : "=m" (c)); \ - asm( "movl %%a3, %0 " : "=m" (d)); \ - asm( "movl %%a2, %0 " : "=m" (s) :: \ - "d0", "d1", "d2", "d3", "d4", "a2", "a3" ); - -#define MULADDC_HUIT \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "addxl %d0, %d3 " ); - -#endif /* MC68000 */ - -#if defined(__powerpc__) || defined(__ppc__) -#if defined(__powerpc64__) || defined(__ppc64__) - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( "ld r3, %0 " :: "m" (s)); \ - asm( "ld r4, %0 " :: "m" (d)); \ - asm( "ld r5, %0 " :: "m" (c)); \ - asm( "ld r6, %0 " :: "m" (b)); \ - asm( "addi r3, r3, -8 " ); \ - asm( "addi r4, r4, -8 " ); \ - asm( "addic r5, r5, 0 " ); - -#define MULADDC_CORE \ - asm( "ldu r7, 8(r3) " ); \ - asm( "mulld r8, r7, r6 " ); \ - asm( "mulhdu r9, r7, r6 " ); \ - asm( "adde r8, r8, r5 " ); \ - asm( "ld r7, 8(r4) " ); \ - asm( "addze r5, r9 " ); \ - asm( "addc r8, r8, r7 " ); \ - asm( "stdu r8, 8(r4) " ); - -#define MULADDC_STOP \ - asm( "addze r5, r5 " ); \ - asm( "addi r4, r4, 8 " ); \ - asm( "addi r3, r3, 8 " ); \ - asm( "std r5, %0 " : "=m" (c)); \ - asm( "std r4, %0 " : "=m" (d)); \ - asm( "std r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#else - -#define MULADDC_INIT \ - asm( "ld %%r3, %0 " :: "m" (s)); \ - asm( "ld %%r4, %0 " :: "m" (d)); \ - asm( "ld %%r5, %0 " :: "m" (c)); \ - asm( "ld %%r6, %0 " :: "m" (b)); \ - asm( "addi %r3, %r3, -8 " ); \ - asm( "addi %r4, %r4, -8 " ); \ - asm( "addic %r5, %r5, 0 " ); - -#define MULADDC_CORE \ - asm( "ldu %r7, 8(%r3) " ); \ - asm( "mulld %r8, %r7, %r6 " ); \ - asm( "mulhdu %r9, %r7, %r6 " ); \ - asm( "adde %r8, %r8, %r5 " ); \ - asm( "ld %r7, 8(%r4) " ); \ - asm( "addze %r5, %r9 " ); \ - asm( "addc %r8, %r8, %r7 " ); \ - asm( "stdu %r8, 8(%r4) " ); - -#define MULADDC_STOP \ - asm( "addze %r5, %r5 " ); \ - asm( "addi %r4, %r4, 8 " ); \ - asm( "addi %r3, %r3, 8 " ); \ - asm( "std %%r5, %0 " : "=m" (c)); \ - asm( "std %%r4, %0 " : "=m" (d)); \ - asm( "std %%r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#endif - -#else /* PPC32 */ - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( "lwz r3, %0 " :: "m" (s)); \ - asm( "lwz r4, %0 " :: "m" (d)); \ - asm( "lwz r5, %0 " :: "m" (c)); \ - asm( "lwz r6, %0 " :: "m" (b)); \ - asm( "addi r3, r3, -4 " ); \ - asm( "addi r4, r4, -4 " ); \ - asm( "addic r5, r5, 0 " ); - -#define MULADDC_CORE \ - asm( "lwzu r7, 4(r3) " ); \ - asm( "mullw r8, r7, r6 " ); \ - asm( "mulhwu r9, r7, r6 " ); \ - asm( "adde r8, r8, r5 " ); \ - asm( "lwz r7, 4(r4) " ); \ - asm( "addze r5, r9 " ); \ - asm( "addc r8, r8, r7 " ); \ - asm( "stwu r8, 4(r4) " ); - -#define MULADDC_STOP \ - asm( "addze r5, r5 " ); \ - asm( "addi r4, r4, 4 " ); \ - asm( "addi r3, r3, 4 " ); \ - asm( "stw r5, %0 " : "=m" (c)); \ - asm( "stw r4, %0 " : "=m" (d)); \ - asm( "stw r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#else - -#define MULADDC_INIT \ - asm( "lwz %%r3, %0 " :: "m" (s)); \ - asm( "lwz %%r4, %0 " :: "m" (d)); \ - asm( "lwz %%r5, %0 " :: "m" (c)); \ - asm( "lwz %%r6, %0 " :: "m" (b)); \ - asm( "addi %r3, %r3, -4 " ); \ - asm( "addi %r4, %r4, -4 " ); \ - asm( "addic %r5, %r5, 0 " ); - -#define MULADDC_CORE \ - asm( "lwzu %r7, 4(%r3) " ); \ - asm( "mullw %r8, %r7, %r6 " ); \ - asm( "mulhwu %r9, %r7, %r6 " ); \ - asm( "adde %r8, %r8, %r5 " ); \ - asm( "lwz %r7, 4(%r4) " ); \ - asm( "addze %r5, %r9 " ); \ - asm( "addc %r8, %r8, %r7 " ); \ - asm( "stwu %r8, 4(%r4) " ); - -#define MULADDC_STOP \ - asm( "addze %r5, %r5 " ); \ - asm( "addi %r4, %r4, 4 " ); \ - asm( "addi %r3, %r3, 4 " ); \ - asm( "stw %%r5, %0 " : "=m" (c)); \ - asm( "stw %%r4, %0 " : "=m" (d)); \ - asm( "stw %%r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#endif - -#endif /* PPC32 */ -#endif /* PPC64 */ - -#if defined(__sparc__) - -#define MULADDC_INIT \ - asm( "ld %0, %%o0 " :: "m" (s)); \ - asm( "ld %0, %%o1 " :: "m" (d)); \ - asm( "ld %0, %%o2 " :: "m" (c)); \ - asm( "ld %0, %%o3 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "ld [%o0], %o4 " ); \ - asm( "inc 4, %o0 " ); \ - asm( "ld [%o1], %o5 " ); \ - asm( "umul %o3, %o4, %o4 " ); \ - asm( "addcc %o4, %o2, %o4 " ); \ - asm( "rd %y, %g1 " ); \ - asm( "addx %g1, 0, %g1 " ); \ - asm( "addcc %o4, %o5, %o4 " ); \ - asm( "st %o4, [%o1] " ); \ - asm( "addx %g1, 0, %o2 " ); \ - asm( "inc 4, %o1 " ); - -#define MULADDC_STOP \ - asm( "st %%o2, %0 " : "=m" (c)); \ - asm( "st %%o1, %0 " : "=m" (d)); \ - asm( "st %%o0, %0 " : "=m" (s) :: \ - "g1", "o0", "o1", "o2", "o3", "o4", "o5" ); - -#endif /* SPARCv8 */ - -#if defined(__microblaze__) || defined(microblaze) - -#define MULADDC_INIT \ - asm( "lwi r3, %0 " :: "m" (s)); \ - asm( "lwi r4, %0 " :: "m" (d)); \ - asm( "lwi r5, %0 " :: "m" (c)); \ - asm( "lwi r6, %0 " :: "m" (b)); \ - asm( "andi r7, r6, 0xffff" ); \ - asm( "bsrli r6, r6, 16 " ); - -#define MULADDC_CORE \ - asm( "lhui r8, r3, 0 " ); \ - asm( "addi r3, r3, 2 " ); \ - asm( "lhui r9, r3, 0 " ); \ - asm( "addi r3, r3, 2 " ); \ - asm( "mul r10, r9, r6 " ); \ - asm( "mul r11, r8, r7 " ); \ - asm( "mul r12, r9, r7 " ); \ - asm( "mul r13, r8, r6 " ); \ - asm( "bsrli r8, r10, 16 " ); \ - asm( "bsrli r9, r11, 16 " ); \ - asm( "add r13, r13, r8 " ); \ - asm( "add r13, r13, r9 " ); \ - asm( "bslli r10, r10, 16 " ); \ - asm( "bslli r11, r11, 16 " ); \ - asm( "add r12, r12, r10 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "add r12, r12, r11 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "lwi r10, r4, 0 " ); \ - asm( "add r12, r12, r10 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "add r12, r12, r5 " ); \ - asm( "addc r5, r13, r0 " ); \ - asm( "swi r12, r4, 0 " ); \ - asm( "addi r4, r4, 4 " ); - -#define MULADDC_STOP \ - asm( "swi r5, %0 " : "=m" (c)); \ - asm( "swi r4, %0 " : "=m" (d)); \ - asm( "swi r3, %0 " : "=m" (s) :: \ - "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \ - "r9", "r10", "r11", "r12", "r13" ); - -#endif /* MicroBlaze */ - -#if defined(__tricore__) - -#define MULADDC_INIT \ - asm( "ld.a %%a2, %0 " :: "m" (s)); \ - asm( "ld.a %%a3, %0 " :: "m" (d)); \ - asm( "ld.w %%d4, %0 " :: "m" (c)); \ - asm( "ld.w %%d1, %0 " :: "m" (b)); \ - asm( "xor %d5, %d5 " ); - -#define MULADDC_CORE \ - asm( "ld.w %d0, [%a2+] " ); \ - asm( "madd.u %e2, %e4, %d0, %d1 " ); \ - asm( "ld.w %d0, [%a3] " ); \ - asm( "addx %d2, %d2, %d0 " ); \ - asm( "addc %d3, %d3, 0 " ); \ - asm( "mov %d4, %d3 " ); \ - asm( "st.w [%a3+], %d2 " ); - -#define MULADDC_STOP \ - asm( "st.w %0, %%d4 " : "=m" (c)); \ - asm( "st.a %0, %%a3 " : "=m" (d)); \ - asm( "st.a %0, %%a2 " : "=m" (s) :: \ - "d0", "d1", "e2", "d4", "a2", "a3" ); - -#endif /* TriCore */ - -#if defined(__arm__) - -#if !defined(__thumb__) - -#define MULADDC_INIT \ - asm( "ldr r0, %0 " :: "m" (s)); \ - asm( "ldr r1, %0 " :: "m" (d)); \ - asm( "ldr r2, %0 " :: "m" (c)); \ - asm( "ldr r3, %0 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "ldr r4, [r0], #4 " ); \ - asm( "mov r5, #0 " ); \ - asm( "ldr r6, [r1] " ); \ - asm( "umlal r2, r5, r3, r4 " ); \ - asm( "adds r7, r6, r2 " ); \ - asm( "adc r2, r5, #0 " ); \ - asm( "str r7, [r1], #4 " ); - -#define MULADDC_STOP \ - asm( "str r2, %0 " : "=m" (c)); \ - asm( "str r1, %0 " : "=m" (d)); \ - asm( "str r0, %0 " : "=m" (s) :: \ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" ); - -#endif /* Thumb */ - -#endif /* ARMv3 */ - -#if defined(__alpha__) - -#define MULADDC_INIT \ - asm( "ldq $1, %0 " :: "m" (s)); \ - asm( "ldq $2, %0 " :: "m" (d)); \ - asm( "ldq $3, %0 " :: "m" (c)); \ - asm( "ldq $4, %0 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "ldq $6, 0($1) " ); \ - asm( "addq $1, 8, $1 " ); \ - asm( "mulq $6, $4, $7 " ); \ - asm( "umulh $6, $4, $6 " ); \ - asm( "addq $7, $3, $7 " ); \ - asm( "cmpult $7, $3, $3 " ); \ - asm( "ldq $5, 0($2) " ); \ - asm( "addq $7, $5, $7 " ); \ - asm( "cmpult $7, $5, $5 " ); \ - asm( "stq $7, 0($2) " ); \ - asm( "addq $2, 8, $2 " ); \ - asm( "addq $6, $3, $3 " ); \ - asm( "addq $5, $3, $3 " ); - -#define MULADDC_STOP \ - asm( "stq $3, %0 " : "=m" (c)); \ - asm( "stq $2, %0 " : "=m" (d)); \ - asm( "stq $1, %0 " : "=m" (s) :: \ - "$1", "$2", "$3", "$4", "$5", "$6", "$7" ); - -#endif /* Alpha */ - -#if defined(__mips__) - -#define MULADDC_INIT \ - asm( "lw $10, %0 " :: "m" (s)); \ - asm( "lw $11, %0 " :: "m" (d)); \ - asm( "lw $12, %0 " :: "m" (c)); \ - asm( "lw $13, %0 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "lw $14, 0($10) " ); \ - asm( "multu $13, $14 " ); \ - asm( "addi $10, $10, 4 " ); \ - asm( "mflo $14 " ); \ - asm( "mfhi $9 " ); \ - asm( "addu $14, $12, $14 " ); \ - asm( "lw $15, 0($11) " ); \ - asm( "sltu $12, $14, $12 " ); \ - asm( "addu $15, $14, $15 " ); \ - asm( "sltu $14, $15, $14 " ); \ - asm( "addu $12, $12, $9 " ); \ - asm( "sw $15, 0($11) " ); \ - asm( "addu $12, $12, $14 " ); \ - asm( "addi $11, $11, 4 " ); - -#define MULADDC_STOP \ - asm( "sw $12, %0 " : "=m" (c)); \ - asm( "sw $11, %0 " : "=m" (d)); \ - asm( "sw $10, %0 " : "=m" (s) :: \ - "$9", "$10", "$11", "$12", "$13", "$14", "$15" ); - -#endif /* MIPS */ -#endif /* GNUC */ - -#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) - -#define MULADDC_INIT \ - __asm mov esi, s \ - __asm mov edi, d \ - __asm mov ecx, c \ - __asm mov ebx, b - -#define MULADDC_CORE \ - __asm lodsd \ - __asm mul ebx \ - __asm add eax, ecx \ - __asm adc edx, 0 \ - __asm add eax, [edi] \ - __asm adc edx, 0 \ - __asm mov ecx, edx \ - __asm stosd - -#if defined(POLARSSL_HAVE_SSE2) - -#define EMIT __asm _emit - -#define MULADDC_HUIT \ - EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ - EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ - EMIT 0x0F EMIT 0x6E EMIT 0x1F \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x16 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ - EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ - EMIT 0x0F EMIT 0x7E EMIT 0x0F \ - EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ - EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ - EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x7E EMIT 0xC9 - -#define MULADDC_STOP \ - EMIT 0x0F EMIT 0x77 \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#else - -#define MULADDC_STOP \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#endif /* SSE2 */ -#endif /* MSVC */ - -#endif /* POLARSSL_HAVE_ASM */ - -#if !defined(MULADDC_CORE) -#if defined(POLARSSL_HAVE_LONGLONG) - -#define MULADDC_INIT \ -{ \ - t_udbl r; \ - t_uint r0, r1; - -#define MULADDC_CORE \ - r = *(s++) * (t_udbl) b; \ - r0 = r; \ - r1 = r >> biL; \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#else -#define MULADDC_INIT \ -{ \ - t_uint s0, s1, b0, b1; \ - t_uint r0, r1, rx, ry; \ - b0 = ( b << biH ) >> biH; \ - b1 = ( b >> biH ); - -#define MULADDC_CORE \ - s0 = ( *s << biH ) >> biH; \ - s1 = ( *s >> biH ); s++; \ - rx = s0 * b1; r0 = s0 * b0; \ - ry = s1 * b0; r1 = s1 * b1; \ - r1 += ( rx >> biH ); \ - r1 += ( ry >> biH ); \ - rx <<= biH; ry <<= biH; \ - r0 += rx; r1 += (r0 < rx); \ - r0 += ry; r1 += (r0 < ry); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#endif /* C (generic) */ -#endif /* C (longlong) */ - -#endif /* bn_mul.h */ diff --git a/polarssl/src/include/polarssl/camellia.h b/polarssl/src/include/polarssl/camellia.h deleted file mode 100644 index b2b1294..0000000 --- a/polarssl/src/include/polarssl/camellia.h +++ /dev/null @@ -1,182 +0,0 @@ -/** - * \file camellia.h - * - * \brief Camellia block cipher - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_CAMELLIA_H -#define POLARSSL_CAMELLIA_H - -#include - -#ifdef _MSC_VER -#include -typedef UINT32 uint32_t; -#else -#include -#endif - -#define CAMELLIA_ENCRYPT 1 -#define CAMELLIA_DECRYPT 0 - -#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ -#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ - -/** - * \brief CAMELLIA context structure - */ -typedef struct -{ - int nr; /*!< number of rounds */ - uint32_t rk[68]; /*!< CAMELLIA round keys */ -} -camellia_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief CAMELLIA key schedule (encryption) - * - * \param ctx CAMELLIA context to be initialized - * \param key encryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH - */ -int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize ); - -/** - * \brief CAMELLIA key schedule (decryption) - * - * \param ctx CAMELLIA context to be initialized - * \param key decryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH - */ -int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize ); - -/** - * \brief CAMELLIA-ECB block encryption/decryption - * - * \param ctx CAMELLIA context - * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if successful - */ -int camellia_crypt_ecb( camellia_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief CAMELLIA-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) - * - * \param ctx CAMELLIA context - * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH - */ -int camellia_crypt_cbc( camellia_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief CAMELLIA-CFB128 buffer encryption/decryption - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. - * - * \param ctx CAMELLIA context - * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH - */ -int camellia_crypt_cfb128( camellia_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/* - * \brief CAMELLIA-CTR buffer encryption/decryption - * - * Warning: You have to keep the maximum use of your counter in mind! - * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIA_DECRYPT. - * - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful - */ -int camellia_crypt_ctr( camellia_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int camellia_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* camellia.h */ diff --git a/polarssl/src/include/polarssl/certs.h b/polarssl/src/include/polarssl/certs.h deleted file mode 100644 index 5399e32..0000000 --- a/polarssl/src/include/polarssl/certs.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * \file certs.h - * - * \brief Sample certificates and DHM parameters for testing - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_CERTS_H -#define POLARSSL_CERTS_H - -#ifdef __cplusplus -extern "C" { -#endif - -extern const char test_ca_crt[]; -extern const char test_ca_key[]; -extern const char test_ca_pwd[]; -extern const char test_srv_crt[]; -extern const char test_srv_key[]; -extern const char test_cli_crt[]; -extern const char test_cli_key[]; -extern const char test_dhm_params[]; - -#ifdef __cplusplus -} -#endif - -#endif /* certs.h */ diff --git a/polarssl/src/include/polarssl/cipher.h b/polarssl/src/include/polarssl/cipher.h deleted file mode 100644 index 9605066..0000000 --- a/polarssl/src/include/polarssl/cipher.h +++ /dev/null @@ -1,459 +0,0 @@ -/** - * \file cipher.h - * - * \brief Generic cipher wrapper. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef POLARSSL_CIPHER_H -#define POLARSSL_CIPHER_H - -#include - -#if defined(_MSC_VER) && !defined(inline) -#define inline _inline -#else -#if defined(__ARMCC_VERSION) && !defined(inline) -#define inline __inline -#endif /* __ARMCC_VERSION */ -#endif /*_MSC_VER */ - -#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ -#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */ -#define POLARSSL_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ -#define POLARSSL_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ -#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ - -typedef enum { - POLARSSL_CIPHER_ID_NONE = 0, - POLARSSL_CIPHER_ID_NULL, - POLARSSL_CIPHER_ID_AES, - POLARSSL_CIPHER_ID_DES, - POLARSSL_CIPHER_ID_3DES, - POLARSSL_CIPHER_ID_CAMELLIA, -} cipher_id_t; - -typedef enum { - POLARSSL_CIPHER_NONE = 0, - POLARSSL_CIPHER_NULL, - POLARSSL_CIPHER_AES_128_CBC, - POLARSSL_CIPHER_AES_192_CBC, - POLARSSL_CIPHER_AES_256_CBC, - POLARSSL_CIPHER_AES_128_CFB128, - POLARSSL_CIPHER_AES_192_CFB128, - POLARSSL_CIPHER_AES_256_CFB128, - POLARSSL_CIPHER_AES_128_CTR, - POLARSSL_CIPHER_AES_192_CTR, - POLARSSL_CIPHER_AES_256_CTR, - POLARSSL_CIPHER_CAMELLIA_128_CBC, - POLARSSL_CIPHER_CAMELLIA_192_CBC, - POLARSSL_CIPHER_CAMELLIA_256_CBC, - POLARSSL_CIPHER_CAMELLIA_128_CFB128, - POLARSSL_CIPHER_CAMELLIA_192_CFB128, - POLARSSL_CIPHER_CAMELLIA_256_CFB128, - POLARSSL_CIPHER_CAMELLIA_128_CTR, - POLARSSL_CIPHER_CAMELLIA_192_CTR, - POLARSSL_CIPHER_CAMELLIA_256_CTR, - POLARSSL_CIPHER_DES_CBC, - POLARSSL_CIPHER_DES_EDE_CBC, - POLARSSL_CIPHER_DES_EDE3_CBC -} cipher_type_t; - -typedef enum { - POLARSSL_MODE_NONE = 0, - POLARSSL_MODE_NULL, - POLARSSL_MODE_CBC, - POLARSSL_MODE_CFB128, - POLARSSL_MODE_OFB, - POLARSSL_MODE_CTR, -} cipher_mode_t; - -typedef enum { - POLARSSL_OPERATION_NONE = -1, - POLARSSL_DECRYPT = 0, - POLARSSL_ENCRYPT, -} operation_t; - -enum { - /** Undefined key length */ - POLARSSL_KEY_LENGTH_NONE = 0, - /** Key length, in bits (including parity), for DES keys */ - POLARSSL_KEY_LENGTH_DES = 64, - /** Key length, in bits (including parity), for DES in two key EDE */ - POLARSSL_KEY_LENGTH_DES_EDE = 128, - /** Key length, in bits (including parity), for DES in three-key EDE */ - POLARSSL_KEY_LENGTH_DES_EDE3 = 192, - /** Maximum length of any IV, in bytes */ - POLARSSL_MAX_IV_LENGTH = 16, -}; - -/** - * Base cipher information. The non-mode specific functions and values. - */ -typedef struct { - - /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */ - cipher_id_t cipher; - - /** Encrypt using CBC */ - int (*cbc_func)( void *ctx, operation_t mode, size_t length, unsigned char *iv, - const unsigned char *input, unsigned char *output ); - - /** Encrypt using CFB128 */ - int (*cfb128_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off, - unsigned char *iv, const unsigned char *input, unsigned char *output ); - - /** Encrypt using CTR */ - int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, - unsigned char *stream_block, const unsigned char *input, unsigned char *output ); - - /** Set key for encryption purposes */ - int (*setkey_enc_func)( void *ctx, const unsigned char *key, unsigned int key_length); - - /** Set key for decryption purposes */ - int (*setkey_dec_func)( void *ctx, const unsigned char *key, unsigned int key_length); - - /** Allocate a new context */ - void * (*ctx_alloc_func)( void ); - - /** Free the given context */ - void (*ctx_free_func)( void *ctx ); - -} cipher_base_t; - -/** - * Cipher information. Allows cipher functions to be called in a generic way. - */ -typedef struct { - /** Full cipher identifier (e.g. POLARSSL_CIPHER_AES_256_CBC) */ - cipher_type_t type; - - /** Cipher mode (e.g. POLARSSL_MODE_CBC) */ - cipher_mode_t mode; - - /** Cipher key length, in bits (default length for variable sized ciphers) - * (Includes parity bits for ciphers like DES) */ - unsigned int key_length; - - /** Name of the cipher */ - const char * name; - - /** IV size, in bytes */ - unsigned int iv_size; - - /** block size, in bytes */ - unsigned int block_size; - - /** Base cipher information and functions */ - const cipher_base_t *base; - -} cipher_info_t; - -/** - * Generic cipher context. - */ -typedef struct { - /** Information about the associated cipher */ - const cipher_info_t *cipher_info; - - /** Key length to use */ - int key_length; - - /** Operation that the context's key has been initialised for */ - operation_t operation; - - /** Buffer for data that hasn't been encrypted yet */ - unsigned char unprocessed_data[POLARSSL_MAX_IV_LENGTH]; - - /** Number of bytes that still need processing */ - size_t unprocessed_len; - - /** Current IV or NONCE_COUNTER for CTR-mode */ - unsigned char iv[POLARSSL_MAX_IV_LENGTH]; - - /** Cipher-specific context */ - void *cipher_ctx; -} cipher_context_t; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Returns the list of ciphers supported by the generic cipher module. - * - * \return a statically allocated array of ciphers, the last entry - * is 0. - */ -const int *cipher_list( void ); - -/** - * \brief Returns the cipher information structure associated - * with the given cipher name. - * - * \param cipher_name Name of the cipher to search for. - * - * \return the cipher information structure associated with the - * given cipher_name, or NULL if not found. - */ -const cipher_info_t *cipher_info_from_string( const char *cipher_name ); - -/** - * \brief Returns the cipher information structure associated - * with the given cipher type. - * - * \param cipher_type Type of the cipher to search for. - * - * \return the cipher information structure associated with the - * given cipher_type, or NULL if not found. - */ -const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type ); - -/** - * \brief Initialises and fills the cipher context structure with - * the appropriate values. - * - * \param ctx context to initialise. May not be NULL. - * \param cipher_info cipher to use. - * - * \return \c 0 on success, - * \c POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, - * \c POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the - * cipher-specific context failed. - */ -int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info ); - -/** - * \brief Free the cipher-specific context of ctx. Freeing ctx - * itself remains the responsibility of the caller. - * - * \param ctx Free the cipher-specific context - * - * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails. - */ -int cipher_free_ctx( cipher_context_t *ctx ); - -/** - * \brief Returns the block size of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return size of the cipher's blocks, or 0 if ctx has not been - * initialised. - */ -static inline unsigned int cipher_get_block_size( const cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - return ctx->cipher_info->block_size; -} - -/** - * \brief Returns the mode of operation for the cipher. - * (e.g. POLARSSL_MODE_CBC) - * - * \param ctx cipher's context. Must have been initialised. - * - * \return mode of operation, or POLARSSL_MODE_NONE if ctx - * has not been initialised. - */ -static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return POLARSSL_MODE_NONE; - - return ctx->cipher_info->mode; -} - -/** - * \brief Returns the size of the cipher's IV. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return size of the cipher's IV, or 0 if ctx has not been - * initialised. - */ -static inline int cipher_get_iv_size( const cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - return ctx->cipher_info->iv_size; -} - -/** - * \brief Returns the type of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return type of the cipher, or POLARSSL_CIPHER_NONE if ctx has - * not been initialised. - */ -static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - return ctx->cipher_info->type; -} - -/** - * \brief Returns the name of the given cipher, as a string. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return name of the cipher, or NULL if ctx was not initialised. - */ -static inline const char *cipher_get_name( const cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - return ctx->cipher_info->name; -} - -/** - * \brief Returns the key length of the cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return cipher's key length, in bits, or - * POLARSSL_KEY_LENGTH_NONE if ctx has not been - * initialised. - */ -static inline int cipher_get_key_size ( const cipher_context_t *ctx ) -{ - if( NULL == ctx ) - return POLARSSL_KEY_LENGTH_NONE; - - return ctx->key_length; -} - -/** - * \brief Returns the operation of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return operation (POLARSSL_ENCRYPT or POLARSSL_DECRYPT), - * or POLARSSL_OPERATION_NONE if ctx has not been - * initialised. - */ -static inline operation_t cipher_get_operation( const cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return POLARSSL_OPERATION_NONE; - - return ctx->operation; -} - -/** - * \brief Set the key to use with the given context. - * - * \param ctx generic cipher context. May not be NULL. Must have been - * initialised using cipher_context_from_type or - * cipher_context_from_string. - * \param key The key to use. - * \param key_length key length to use, in bits. - * \param operation Operation that the key will be used for, either - * POLARSSL_ENCRYPT or POLARSSL_DECRYPT. - * - * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails or a cipher specific - * error code. - */ -int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, int key_length, - const operation_t operation ); - -/** - * \brief Reset the given context, setting the IV to iv - * - * \param ctx generic cipher context - * \param iv IV to use or NONCE_COUNTER in the case of a CTR-mode cipher - * - * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA - * if parameter verification fails. - */ -int cipher_reset( cipher_context_t *ctx, const unsigned char *iv ); - -/** - * \brief Generic cipher update function. Encrypts/decrypts - * using the given cipher context. Writes as many block - * size'd blocks of data as possible to output. Any data - * that cannot be written immediately will either be added - * to the next block, or flushed when cipher_final is - * called. - * - * \param ctx generic cipher context - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. Should be able to hold at - * least ilen + block_size. Cannot be the same buffer as - * input! - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * - * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an - * unsupported mode for a cipher or a cipher specific - * error code. - */ -int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen ); - -/** - * \brief Generic cipher finalisation function. If data still - * needs to be flushed from an incomplete block, data - * contained within it will be padded with the size of - * the last block, and written to the output buffer. - * - * \param ctx Generic cipher context - * \param output buffer to write data to. Needs block_size data available. - * \param olen length of the data written to the output buffer. - * - * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, - * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting or a cipher specific error code. - */ -int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen); - - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int cipher_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* POLARSSL_MD_H */ diff --git a/polarssl/src/include/polarssl/cipher_wrap.h b/polarssl/src/include/polarssl/cipher_wrap.h deleted file mode 100644 index e81c11d..0000000 --- a/polarssl/src/include/polarssl/cipher_wrap.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * \file cipher_wrap.h - * - * \brief Cipher wrappers. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_CIPHER_WRAP_H -#define POLARSSL_CIPHER_WRAP_H - -#include "config.h" -#include "cipher.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(POLARSSL_AES_C) - -extern const cipher_info_t aes_128_cbc_info; -extern const cipher_info_t aes_192_cbc_info; -extern const cipher_info_t aes_256_cbc_info; - -#if defined(POLARSSL_CIPHER_MODE_CFB) -extern const cipher_info_t aes_128_cfb128_info; -extern const cipher_info_t aes_192_cfb128_info; -extern const cipher_info_t aes_256_cfb128_info; -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -extern const cipher_info_t aes_128_ctr_info; -extern const cipher_info_t aes_192_ctr_info; -extern const cipher_info_t aes_256_ctr_info; -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -#endif /* defined(POLARSSL_AES_C) */ - -#if defined(POLARSSL_CAMELLIA_C) - -extern const cipher_info_t camellia_128_cbc_info; -extern const cipher_info_t camellia_192_cbc_info; -extern const cipher_info_t camellia_256_cbc_info; - -#if defined(POLARSSL_CIPHER_MODE_CFB) -extern const cipher_info_t camellia_128_cfb128_info; -extern const cipher_info_t camellia_192_cfb128_info; -extern const cipher_info_t camellia_256_cfb128_info; -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -extern const cipher_info_t camellia_128_ctr_info; -extern const cipher_info_t camellia_192_ctr_info; -extern const cipher_info_t camellia_256_ctr_info; -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -#endif /* defined(POLARSSL_CAMELLIA_C) */ - -#if defined(POLARSSL_DES_C) - -extern const cipher_info_t des_cbc_info; -extern const cipher_info_t des_ede_cbc_info; -extern const cipher_info_t des_ede3_cbc_info; - -#endif /* defined(POLARSSL_DES_C) */ - -#if defined(POLARSSL_CIPHER_NULL_CIPHER) -extern const cipher_info_t null_cipher_info; -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - -#ifdef __cplusplus -} -#endif - -#endif /* POLARSSL_CIPHER_WRAP_H */ diff --git a/polarssl/src/include/polarssl/config.h b/polarssl/src/include/polarssl/config.h deleted file mode 100644 index 4e27446..0000000 --- a/polarssl/src/include/polarssl/config.h +++ /dev/null @@ -1,744 +0,0 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - */ -#ifndef POLARSSL_CONFIG_H -#define POLARSSL_CONFIG_H - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -/** - * \name SECTION: System support - * - * This section sets system specific settings. - * \{ - */ - -/** - * \def POLARSSL_HAVE_INT8 - * - * The system uses 8-bit wide native integers. - * - * Uncomment if native integers are 8-bit wide. -#define POLARSSL_HAVE_INT8 - */ - -/** - * \def POLARSSL_HAVE_INT16 - * - * The system uses 16-bit wide native integers. - * - * Uncomment if native integers are 16-bit wide. -#define POLARSSL_HAVE_INT16 - */ - -/** - * \def POLARSSL_HAVE_LONGLONG - * - * The compiler supports the use of long long. - * - * Uncomment if the compiler supports long long. -#define POLARSSL_HAVE_LONGLONG - */ - -/** - * \def POLARSSL_HAVE_ASM - * - * The compiler has support for asm() - * - * Uncomment to enable the use of assembly code. - * - * Requires support for asm() in compiler. - * - * Used in: - * library/timing.c - * library/padlock.c - * include/polarssl/bn_mul.h - * - */ -#define POLARSSL_HAVE_ASM - -/** - * \def POLARSSL_HAVE_SSE2 - * - * CPI supports SSE2 instruction set. - * - * Uncomment if the CPU supports SSE2 (IA-32 specific). - * -#define POLARSSL_HAVE_SSE2 - */ -/* \} name */ - -/** - * \name SECTION: PolarSSL feature support - * - * This section sets support for features that are or are not needed - * within the modules that are enabled. - * \{ - */ - -/** - * \def POLARSSL_AES_ROM_TABLES - * - * Store the AES tables in ROM. - * - * Uncomment this macro to store the AES tables in ROM. - * -#define POLARSSL_AES_ROM_TABLES - */ - -/** - * \def POLARSSL_CIPHER_MODE_CFB - * - * Enable Cipher Feedback mode (CFB) for symmetric ciphers. - */ -//#define POLARSSL_CIPHER_MODE_CFB - -/** - * \def POLARSSL_CIPHER_MODE_CTR - * - * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. - */ -//#define POLARSSL_CIPHER_MODE_CTR - -/** - * \def POLARSSL_CIPHER_NULL_CIPHER - * - * Enable NULL cipher. - * Warning: Only do so when you know what you are doing. This allows for - * encryption or channels without any security! - * - * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable - * the following ciphersuites: - * SSL_RSA_NULL_MD5 - * SSL_RSA_NULL_SHA - * SSL_RSA_NULL_SHA256 - * - * Uncomment this macro to enable the NULL cipher and ciphersuites -#define POLARSSL_CIPHER_NULL_CIPHER - */ - -/** - * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES - * - * Enable weak ciphersuites in SSL / TLS (like RC4_40) - * Warning: Only do so when you know what you are doing. This allows for - * channels without virtually no security at all! - * - * This enables the following ciphersuites: - * SSL_RSA_DES_SHA - * SSL_EDH_RSA_DES_SHA - * - * Uncomment this macro to enable weak ciphersuites -#define POLARSSL_ENABLE_WEAK_CIPHERSUITES - */ - -/** - * \def POLARSSL_GENPRIME - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C - * - * Enable the RSA prime-number generation code. - */ -//#define POLARSSL_GENPRIME - -/** - * \def POLARSSL_FS_IO - * - * Enable functions that use the filesystem. - */ -//#define POLARSSL_FS_IO - -/** - * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - * - * Do not add default entropy sources. These are the platform specific, - * hardclock and HAVEGE based poll functions. - * - * This is useful to have more control over the added entropy sources in an - * application. - * - * Uncomment this macro to prevent loading of default entropy functions. -#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - */ - -/** - * \def POLARSSL_NO_PLATFORM_ENTROPY - * - * Do not use built-in platform entropy functions. - * This is useful if your platform does not support - * standards like the /dev/urandom or Windows CryptoAPI. - * - * Uncomment this macro to disable the built-in platform entropy functions. -#define POLARSSL_NO_PLATFORM_ENTROPY - */ - -/** - * \def POLARSSL_PKCS1_V21 - * - * Requires: POLARSSL_MD_C, POLARSSL_RSA_C - * - * Enable support for PKCS#1 v2.1 encoding. - * This enables support for RSAES-OAEP and RSASSA-PSS operations. - */ -//#define POLARSSL_PKCS1_V21 - -/** - * \def POLARSSL_RSA_NO_CRT - * - * Do not use the Chinese Remainder Theorem for the RSA private operation. - * - * Uncomment this macro to disable the use of CRT in RSA. - * -#define POLARSSL_RSA_NO_CRT - */ - -/** - * \def POLARSSL_SELF_TEST - * - * Enable the checkup functions (*_self_test). - */ -//#define POLARSSL_SELF_TEST - -/** - * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an unknown critical extension. - * - * Uncomment to prevent an error. - * -#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - */ -/* \} name */ - -/** - * \name SECTION: PolarSSL modules - * - * This section enables or disables entire modules in PolarSSL - * \{ - */ - -/** - * \def POLARSSL_AES_C - * - * Enable the AES block cipher. - * - * Module: library/aes.c - * Caller: library/ssl_tls.c - * library/pem.c - * library/ctr_drbg.c - * - * This module enables the following ciphersuites: - * SSL_RSA_AES_128_SHA - * SSL_RSA_AES_256_SHA - * SSL_EDH_RSA_AES_256_SHA - */ -#define POLARSSL_AES_C - -/** - * \def POLARSSL_ARC4_C - * - * Enable the ARCFOUR stream cipher. - * - * Module: library/arc4.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites: - * SSL_RSA_RC4_128_MD5 - * SSL_RSA_RC4_128_SHA - */ -//#define POLARSSL_ARC4_C - -/** - * \def POLARSSL_ASN1_PARSE_C - * - * Enable the generic ASN1 parser. - * - * Module: library/asn1.c - * Caller: library/x509parse.c - */ -#define POLARSSL_ASN1_PARSE_C - -/** - * \def POLARSSL_ASN1_WRITE_C - * - * Enable the generic ASN1 writer. - * - * Module: library/asn1write.c - */ -#define POLARSSL_ASN1_WRITE_C - -/** - * \def POLARSSL_BASE64_C - * - * Enable the Base64 module. - * - * Module: library/base64.c - * Caller: library/pem.c - * - * This module is required for PEM support (required by X.509). - */ -//#define POLARSSL_BASE64_C - -/** - * \def POLARSSL_BIGNUM_C - * - * Enable the multo-precision integer library. - * - * Module: library/bignum.c - * Caller: library/dhm.c - * library/rsa.c - * library/ssl_tls.c - * library/x509parse.c - * - * This module is required for RSA and DHM support. - */ -#define POLARSSL_BIGNUM_C - -/** - * \def POLARSSL_CAMELLIA_C - * - * Enable the Camellia block cipher. - * - * Module: library/camellia.c - * Caller: library/ssl_tls.c - * - * This module enabled the following cipher suites: - * SSL_RSA_CAMELLIA_128_SHA - * SSL_RSA_CAMELLIA_256_SHA - * SSL_EDH_RSA_CAMELLIA_256_SHA - */ -//#define POLARSSL_CAMELLIA_C - -/** - * \def POLARSSL_CERTS_C - * - * Enable the test certificates. - * - * Module: library/certs.c - * Caller: - * - * This module is used for testing (ssl_client/server). - */ -//#define POLARSSL_CERTS_C - -/** - * \def POLARSSL_CIPHER_C - * - * Enable the generic cipher layer. - * - * Module: library/cipher.c - * Caller: - * - * Uncomment to enable generic cipher wrappers. - */ -//#define POLARSSL_CIPHER_C - -/** - * \def POLARSSL_CTR_DRBG_C - * - * Enable the CTR_DRBG AES-256-based random generator - * - * Module: library/ctr_drbg.c - * Caller: - * - * Requires: POLARSSL_AES_C - * - * This module provides the CTR_DRBG AES-256 random number generator. - */ -#define POLARSSL_CTR_DRBG_C - -/** - * \def POLARSSL_DEBUG_C - * - * Enable the debug functions. - * - * Module: library/debug.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module provides debugging functions. - */ -//#define POLARSSL_DEBUG_C - -/** - * \def POLARSSL_DES_C - * - * Enable the DES block cipher. - * - * Module: library/des.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites: - * SSL_RSA_DES_168_SHA - * SSL_EDH_RSA_DES_168_SHA - */ -//#define POLARSSL_DES_C - -/** - * \def POLARSSL_DHM_C - * - * Enable the Diffie-Hellman-Merkle key exchange. - * - * Module: library/dhm.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module enables the following ciphersuites: - * SSL_EDH_RSA_DES_168_SHA - * SSL_EDH_RSA_AES_256_SHA - * SSL_EDH_RSA_CAMELLIA_256_SHA - */ -//#define POLARSSL_DHM_C - -/** - * \def POLARSSL_ENTROPY_C - * - * Enable the platform-specific entropy code. - * - * Module: library/entropy.c - * Caller: - * - * Requires: POLARSSL_SHA4_C - * - * This module provides a generic entropy pool - */ -#define POLARSSL_ENTROPY_C - -/** - * \def POLARSSL_ERROR_C - * - * Enable error code to error string conversion. - * - * Module: library/error.c - * Caller: - * - * This module enables err_strerror(). - */ -#define POLARSSL_ERROR_C - -/** - * \def POLARSSL_GCM_C - * - * Enable the Galois/Counter Mode (GCM) for AES - * - * Module: library/gcm.c - * - * Requires: POLARSSL_AES_C - */ -//#define POLARSSL_GCM_C - -/** - * \def POLARSSL_HAVEGE_C - * - * Enable the HAVEGE random generator. - * - * Module: library/havege.c - * Caller: - * - * Requires: POLARSSL_TIMING_C - * - * This module enables the HAVEGE random number generator. - */ -//#define POLARSSL_HAVEGE_C - -/** - * \def POLARSSL_MD_C - * - * Enable the generic message digest layer. - * - * Module: library/md.c - * Caller: - * - * Uncomment to enable generic message digest wrappers. - */ -//#define POLARSSL_MD_C - -/** - * \def POLARSSL_MD2_C - * - * Enable the MD2 hash algorithm - * - * Module: library/md2.c - * Caller: library/x509parse.c - * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. - * -#define POLARSSL_MD2_C - */ - -/** - * \def POLARSSL_MD4_C - * - * Enable the MD4 hash algorithm - * - * Module: library/md4.c - * Caller: library/x509parse.c - * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. - * -#define POLARSSL_MD4_C - */ - -/** - * \def POLARSSL_MD5_C - * - * Enable the MD5 hash algorithm - * - * Module: library/md5.c - * Caller: library/ssl_tls.c - * library/x509parse.c - * - * This module is required for SSL/TLS and X.509. - */ -#define POLARSSL_MD5_C - -/** - * \def POLARSSL_NET_C - * - * Enable the TCP/IP networking routines. - * - * Module: library/net.c - * Caller: - * - * This module provides TCP/IP networking routines. - */ -//#define POLARSSL_NET_C - -/** - * \def POLARSSL_PADLOCK_C - * - * Enable VIA Padlock support on x86. - * - * Module: library/padlock.c - * Caller: library/aes.c - * - * This modules adds support for the VIA PadLock on x86. - */ -//#define POLARSSL_PADLOCK_C - -/** - * \def POLARSSL_PEM_C - * - * Enable PEM decoding - * - * Module: library/pem.c - * Caller: library/x509parse.c - * - * Requires: POLARSSL_BASE64_C - * - * This modules adds support for decoding PEM files. - */ -//#define POLARSSL_PEM_C - -/** - * \def POLARSSL_PKCS11_C - * - * Enable support for PKCS#11 smartcard support. - * - * Module: library/ssl_srv.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS PKCS #11 smartcard support. - * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) -#define POLARSSL_PKCS11_C - */ - -/** - * \def POLARSSL_RSA_C - * - * Enable the RSA public-key cryptosystem. - * - * Module: library/rsa.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509.c - * - * Requires: POLARSSL_BIGNUM_C - * - * This module is required for SSL/TLS and MD5-signed certificates. - */ -#define POLARSSL_RSA_C - -/** - * \def POLARSSL_SHA1_C - * - * Enable the SHA1 cryptographic hash algorithm. - * - * Module: library/sha1.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509parse.c - * - * This module is required for SSL/TLS and SHA1-signed certificates. - */ -#define POLARSSL_SHA1_C - -/** - * \def POLARSSL_SHA2_C - * - * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. - * - * Module: library/sha2.c - * Caller: library/md_wrap.c - * library/x509parse.c - * - * This module adds support for SHA-224 and SHA-256. - */ -#define POLARSSL_SHA2_C - -/** - * \def POLARSSL_SHA4_C - * - * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. - * - * Module: library/sha4.c - * Caller: library/md_wrap.c - * library/x509parse.c - * - * This module adds support for SHA-384 and SHA-512. - */ -#define POLARSSL_SHA4_C - -/** - * \def POLARSSL_SSL_CLI_C - * - * Enable the SSL/TLS client code. - * - * Module: library/ssl_cli.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS client support. - */ -#define POLARSSL_SSL_CLI_C - -/* - * \def POLARSSL_SSL_SRV_C - * - * Enable the SSL/TLS server code. - * - * Module: library/ssl_srv.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS server support. - */ -//#define POLARSSL_SSL_SRV_C - -/** - * \def POLARSSL_SSL_TLS_C - * - * Enable the generic SSL/TLS code. - * - * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C - * - * This module is required for SSL/TLS. - */ -#define POLARSSL_SSL_TLS_C - -/** - * \def POLARSSL_TIMING_C - * - * Enable the portable timing interface. - * - * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. - */ -//#define POLARSSL_TIMING_C - -/** - * \def POLARSSL_VERSION_C - * - * Enable run-time version information. - * - * Module: library/version.c - * - * This module provides run-time version information. - */ -#define POLARSSL_VERSION_C - -/** - * \def POLARSSL_X509_PARSE_C - * - * Enable X.509 certificate parsing. - * - * Module: library/x509parse.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C - * - * This module is required for X.509 certificate parsing. - */ -#define POLARSSL_X509_PARSE_C - -/** - * \def POLARSSL_X509_WRITE_C - * - * Enable X.509 buffer writing. - * - * Module: library/x509write.c - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C - * - * This module is required for X.509 certificate request writing. - */ -//#define POLARSSL_X509_WRITE_C - -/** - * \def POLARSSL_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -//#define POLARSSL_XTEA_C -/* \} name */ - -#endif /* config.h */ diff --git a/polarssl/src/include/polarssl/ctr_drbg.h b/polarssl/src/include/polarssl/ctr_drbg.h deleted file mode 100644 index 83861a9..0000000 --- a/polarssl/src/include/polarssl/ctr_drbg.h +++ /dev/null @@ -1,228 +0,0 @@ -/** - * \file ctr_drbg.h - * - * \brief CTR_DRBG based on AES-256 (NIST SP 800-90) - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_CTR_DRBG_H -#define POLARSSL_CTR_DRBG_H - -#include - -#include "aes.h" - -#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ -#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */ -#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */ -#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */ - -#define CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */ -#define CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */ -#define CTR_DRBG_KEYBITS ( CTR_DRBG_KEYSIZE * 8 ) -#define CTR_DRBG_SEEDLEN ( CTR_DRBG_KEYSIZE + CTR_DRBG_BLOCKSIZE ) - /**< The seed length (counter + AES key) */ -#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default */ -#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -#define CTR_DRBG_PR_OFF 0 /**< No prediction resistance */ -#define CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief CTR_DRBG context structure - */ -typedef struct -{ - unsigned char counter[16]; /*!< counter (V) */ - int reseed_counter; /*!< reseed counter */ - int prediction_resistance; /*!< enable prediction resistance (Automatic - reseed before every random generation) */ - size_t entropy_len; /*!< amount of entropy grabbed on each (re)seed */ - int reseed_interval; /*!< reseed interval */ - - aes_context aes_ctx; /*!< AES context */ - - /* - * Callbacks (Entropy) - */ - int (*f_entropy)(void *, unsigned char *, size_t); - - void *p_entropy; /*!< context for the entropy function */ -} -ctr_drbg_context; - -/** - * \brief CTR_DRBG initialization - * - * Note: Personalization data can be provided in addition to the more generic - * entropy source to make this instantiation as unique as possible. - * - * \param ctx CTR_DRBG context to be initialized - * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer - * length) - * \param p_entropy Entropy context - * \param custom Personalization data (Device specific identifiers) - * (Can be NULL) - * \param len Length of personalization data - * - * \return 0 if successful, or - * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int ctr_drbg_init( ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ); - -/** - * \brief Enable / disable prediction resistance (Default: Off) - * - * Note: If enabled, entropy is used for ctx->entropy_len before each call! - * Only use this if you have ample supply of good entropy! - * - * \param ctx CTR_DRBG context - * \param resistance CTR_DRBG_PR_ON or CTR_DRBG_PR_OFF - */ -void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, - int resistance ); - -/** - * \brief Set the amount of entropy grabbed on each (re)seed - * (Default: CTR_DRBG_ENTROPY_LEN) - * - * \param ctx CTR_DRBG context - * \param len Amount of entropy to grab - */ -void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, - size_t len ); - -/** - * \brief Set the reseed interval - * (Default: CTR_DRBG_RESEED_INTERVAL) - * - * \param ctx CTR_DRBG context - * \param interval Reseed interval - */ -void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, - int interval ); - -/** - * \brief CTR_DRBG reseeding (extracts data from entropy source) - * - * \param ctx CTR_DRBG context - * \param additional Additional data to add to state (Can be NULL) - * \param len Length of additional data - * - * \return 0 if successful, or - * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int ctr_drbg_reseed( ctr_drbg_context *ctx, - const unsigned char *additional, size_t len ); - -/** - * \brief CTR_DRBG update state - * - * \param ctx CTR_DRBG context - * \param additional Additional data to update state with - * \param add_len Length of additional data - */ -void ctr_drbg_update( ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); - -/** - * \brief CTR_DRBG generate random with additional update input - * - * Note: Automatically reseeds if reseed_counter is reached. - * - * \param p_rng CTR_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * \param additional Additional data to update with (Can be NULL) - * \param add_len Length of additional data - * - * \return 0 if successful, or - * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or - * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG - */ -int ctr_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, size_t add_len ); - -/** - * \brief CTR_DRBG generate random - * - * Note: Automatically reseeds if reseed_counter is reached. - * - * \param p_rng CTR_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * - * \return 0 if successful, or - * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or - * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG - */ -int ctr_drbg_random( void *p_rng, - unsigned char *output, size_t output_len ); - -#if defined(POLARSSL_FS_IO) -/** - * \brief Write a seed file - * - * \param path Name of the file - * - * \return 0 if successful, 1 on file error, or - * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path ); - -/** - * \brief Read and update a seed file. Seed is added to this - * instance - * - * \param path Name of the file - * - * \return 0 if successful, 1 on file error, - * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or - * POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG - */ -int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path ); -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int ctr_drbg_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* ctr_drbg.h */ diff --git a/polarssl/src/include/polarssl/debug.h b/polarssl/src/include/polarssl/debug.h deleted file mode 100644 index 511e926..0000000 --- a/polarssl/src/include/polarssl/debug.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * \file debug.h - * - * \brief Debug functions - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_DEBUG_H -#define POLARSSL_DEBUG_H - -#include "config.h" -#include "ssl.h" - -#if defined(POLARSSL_DEBUG_C) - -#define SSL_DEBUG_MSG( level, args ) \ - debug_print_msg( ssl, level, __FILE__, __LINE__, debug_fmt args ); - -#define SSL_DEBUG_RET( level, text, ret ) \ - debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ); - -#define SSL_DEBUG_BUF( level, text, buf, len ) \ - debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ); - -#define SSL_DEBUG_MPI( level, text, X ) \ - debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ); - -#define SSL_DEBUG_CRT( level, text, crt ) \ - debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ); - -#else - -#define SSL_DEBUG_MSG( level, args ) do { } while( 0 ) -#define SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) -#define SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) -#define SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) -#define SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) - -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -char *debug_fmt( const char *format, ... ); - -void debug_print_msg( const ssl_context *ssl, int level, - const char *file, int line, const char *text ); - -void debug_print_ret( const ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret ); - -void debug_print_buf( const ssl_context *ssl, int level, - const char *file, int line, const char *text, - unsigned char *buf, size_t len ); - -void debug_print_mpi( const ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mpi *X ); - -void debug_print_crt( const ssl_context *ssl, int level, - const char *file, int line, - const char *text, const x509_cert *crt ); - -#ifdef __cplusplus -} -#endif - -#endif /* debug.h */ diff --git a/polarssl/src/include/polarssl/des.h b/polarssl/src/include/polarssl/des.h deleted file mode 100644 index 653e68b..0000000 --- a/polarssl/src/include/polarssl/des.h +++ /dev/null @@ -1,227 +0,0 @@ -/** - * \file des.h - * - * \brief DES block cipher - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_DES_H -#define POLARSSL_DES_H - -#include - -#define DES_ENCRYPT 1 -#define DES_DECRYPT 0 - -#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ - -#define DES_KEY_SIZE 8 - -/** - * \brief DES context structure - */ -typedef struct -{ - int mode; /*!< encrypt/decrypt */ - unsigned long sk[32]; /*!< DES subkeys */ -} -des_context; - -/** - * \brief Triple-DES context structure - */ -typedef struct -{ - int mode; /*!< encrypt/decrypt */ - unsigned long sk[96]; /*!< 3DES subkeys */ -} -des3_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Set key parity on the given key to odd. - * - * DES keys are 56 bits long, but each byte is padded with - * a parity bit to allow verification. - * - * \param key 8-byte secret key - */ -void des_key_set_parity( unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief Check that key parity on the given key is odd. - * - * DES keys are 56 bits long, but each byte is padded with - * a parity bit to allow verification. - * - * \param key 8-byte secret key - * - * \return 0 is parity was ok, 1 if parity was not correct. - */ -int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief Check that key is not a weak or semi-weak DES key - * - * \param key 8-byte secret key - * - * \return 0 if no weak key was found, 1 if a weak key was identified. - */ -int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief DES key schedule (56-bit, encryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - * - * \return 0 - */ -int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief DES key schedule (56-bit, decryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - * - * \return 0 - */ -int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief Triple-DES key schedule (112-bit, encryption) - * - * \param ctx 3DES context to be initialized - * \param key 16-byte secret key - * - * \return 0 - */ -int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ); - -/** - * \brief Triple-DES key schedule (112-bit, decryption) - * - * \param ctx 3DES context to be initialized - * \param key 16-byte secret key - * - * \return 0 - */ -int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ); - -/** - * \brief Triple-DES key schedule (168-bit, encryption) - * - * \param ctx 3DES context to be initialized - * \param key 24-byte secret key - * - * \return 0 - */ -int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ); - -/** - * \brief Triple-DES key schedule (168-bit, decryption) - * - * \param ctx 3DES context to be initialized - * \param key 24-byte secret key - * - * \return 0 - */ -int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ); - -/** - * \brief DES-ECB block encryption/decryption - * - * \param ctx DES context - * \param input 64-bit input block - * \param output 64-bit output block - * - * \return 0 if successful - */ -int des_crypt_ecb( des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -/** - * \brief DES-CBC buffer encryption/decryption - * - * \param ctx DES context - * \param mode DES_ENCRYPT or DES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - */ -int des_crypt_cbc( des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief 3DES-ECB block encryption/decryption - * - * \param ctx 3DES context - * \param input 64-bit input block - * \param output 64-bit output block - * - * \return 0 if successful - */ -int des3_crypt_ecb( des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -/** - * \brief 3DES-CBC buffer encryption/decryption - * - * \param ctx 3DES context - * \param mode DES_ENCRYPT or DES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or POLARSSL_ERR_DES_INVALID_INPUT_LENGTH - */ -int des3_crypt_cbc( des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); - -/* - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int des_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* des.h */ diff --git a/polarssl/src/include/polarssl/dhm.h b/polarssl/src/include/polarssl/dhm.h deleted file mode 100644 index 0c8dd55..0000000 --- a/polarssl/src/include/polarssl/dhm.h +++ /dev/null @@ -1,153 +0,0 @@ -/** - * \file dhm.h - * - * \brief Diffie-Hellman-Merkle key exchange - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_DHM_H -#define POLARSSL_DHM_H - -#include "bignum.h" - -/* - * DHM Error codes - */ -#define POLARSSL_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */ -#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ -#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ -#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ -#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ -#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ - -/** - * \brief DHM context structure - */ -typedef struct -{ - size_t len; /*!< size(P) in chars */ - mpi P; /*!< prime modulus */ - mpi G; /*!< generator */ - mpi X; /*!< secret value */ - mpi GX; /*!< self = G^X mod P */ - mpi GY; /*!< peer = G^Y mod P */ - mpi K; /*!< key = GY^X mod P */ - mpi RP; /*!< cached R^2 mod P */ -} -dhm_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Parse the ServerKeyExchange parameters - * - * \param ctx DHM context - * \param p &(start of input buffer) - * \param end end of buffer - * - * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code - */ -int dhm_read_params( dhm_context *ctx, - unsigned char **p, - const unsigned char *end ); - -/** - * \brief Setup and write the ServerKeyExchange parameters - * - * \param ctx DHM context - * \param x_size private value size in bytes - * \param output destination buffer - * \param olen number of chars written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note This function assumes that ctx->P and ctx->G - * have already been properly set (for example - * using mpi_read_string or mpi_read_binary). - * - * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code - */ -int dhm_make_params( dhm_context *ctx, int x_size, - unsigned char *output, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Import the peer's public value G^Y - * - * \param ctx DHM context - * \param input input buffer - * \param ilen size of buffer - * - * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code - */ -int dhm_read_public( dhm_context *ctx, - const unsigned char *input, size_t ilen ); - -/** - * \brief Create own private value X and export G^X - * - * \param ctx DHM context - * \param x_size private value size in bytes - * \param output destination buffer - * \param olen must be equal to ctx->P.len - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code - */ -int dhm_make_public( dhm_context *ctx, int x_size, - unsigned char *output, size_t olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Derive and export the shared secret (G^Y)^X mod P - * - * \param ctx DHM context - * \param output destination buffer - * \param olen number of chars written - * - * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code - */ -int dhm_calc_secret( dhm_context *ctx, - unsigned char *output, size_t *olen ); - -/* - * \brief Free the components of a DHM key - */ -void dhm_free( dhm_context *ctx ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int dhm_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/polarssl/src/include/polarssl/entropy.h b/polarssl/src/include/polarssl/entropy.h deleted file mode 100644 index 53bce41..0000000 --- a/polarssl/src/include/polarssl/entropy.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - * \file entropy.h - * - * \brief Entropy accumulator implementation - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_ENTROPY_H -#define POLARSSL_ENTROPY_H - -#include - -#include "config.h" - -#include "sha4.h" -#if defined(POLARSSL_HAVEGE_C) -#include "havege.h" -#endif - -#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ -#define POLARSSL_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ -#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ - -#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ -#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ -#define ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ - -#define ENTROPY_SOURCE_MANUAL ENTROPY_MAX_SOURCES - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Entropy poll callback pointer - * - * \param data Callback-specific data pointer - * \param output Data to fill - * \param len Maximum size to provide - * \param olen The actual amount of bytes put into the buffer (Can be 0) - * - * \return 0 if no critical failures occurred, - * POLARSSL_ERR_ENTROPY_SOURCE_FAILED otherwise - */ -typedef int (*f_source_ptr)(void *, unsigned char *, size_t, size_t *); - -/** - * \brief Entropy source state - */ -typedef struct -{ - f_source_ptr f_source; /**< The entropy source callback */ - void * p_source; /**< The callback data pointer */ - size_t size; /**< Amount received */ - size_t threshold; /**< Minimum level required before release */ -} -source_state; - -/** - * \brief Entropy context structure - */ -typedef struct -{ - sha4_context accumulator; - int source_count; - source_state source[ENTROPY_MAX_SOURCES]; -#if defined(POLARSSL_HAVEGE_C) - havege_state havege_data; -#endif -} -entropy_context; - -/** - * \brief Initialize the context - * - * \param ctx Entropy context to initialize - */ -void entropy_init( entropy_context *ctx ); - -/** - * \brief Adds an entropy source to poll - * - * \param ctx Entropy context - * \param f_source Entropy function - * \param p_source Function data - * \param threshold Minimum required from source before entropy is released - * ( with entropy_func() ) - * - * \return 0 if successful or POLARSSL_ERR_ENTROPY_MAX_SOURCES - */ -int entropy_add_source( entropy_context *ctx, - f_source_ptr f_source, void *p_source, - size_t threshold ); - -/** - * \brief Trigger an extra gather poll for the accumulator - * - * \param ctx Entropy context - * - * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED - */ -int entropy_gather( entropy_context *ctx ); - -/** - * \brief Retrieve entropy from the accumulator (Max ENTROPY_BLOCK_SIZE) - * - * \param data Entropy context - * \param output Buffer to fill - * \param len Length of buffer - * - * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED - */ -int entropy_func( void *data, unsigned char *output, size_t len ); - -/** - * \brief Add data to the accumulator manually - * - * \param ctx Entropy context - * \param data Data to add - * \param len Length of data - * - * \return 0 if successful - */ -int entropy_update_manual( entropy_context *ctx, - const unsigned char *data, size_t len ); - -#ifdef __cplusplus -} -#endif - -#endif /* entropy.h */ diff --git a/polarssl/src/include/polarssl/entropy_poll.h b/polarssl/src/include/polarssl/entropy_poll.h deleted file mode 100644 index 0116598..0000000 --- a/polarssl/src/include/polarssl/entropy_poll.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * \file entropy_poll.h - * - * \brief Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_ENTROPY_POLL_H -#define POLARSSL_ENTROPY_POLL_H - -#include - -#include "config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Default thresholds for built-in sources - */ -#define ENTROPY_MIN_PLATFORM 128 /**< Minimum for platform source */ -#define ENTROPY_MIN_HAVEGE 128 /**< Minimum for HAVEGE */ -#define ENTROPY_MIN_HARDCLOCK 32 /**< Minimum for hardclock() */ - -#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) -/** - * \brief Platform-specific entropy poll callback - */ -int platform_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(POLARSSL_HAVEGE_C) -/** - * \brief HAVEGE based entropy poll callback - * - * Requires an HAVEGE state as its data pointer. - */ -int havege_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(POLARSSL_TIMING_C) -/** - * \brief hardclock-based entropy poll callback - */ -int hardclock_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* entropy_poll.h */ diff --git a/polarssl/src/include/polarssl/error.h b/polarssl/src/include/polarssl/error.h deleted file mode 100644 index f3514df..0000000 --- a/polarssl/src/include/polarssl/error.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * \file error.h - * - * \brief Error to string translation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_ERROR_H -#define POLARSSL_ERROR_H - -/** - * Error code layout. - * - * Currently we try to keep all error codes within the negative space of 16 - * bytes signed integers to support all platforms (-0x0000 - -0x8000). In - * addition we'd like to give two layers of information on the error if - * possible. - * - * For that purpose the error codes are segmented in the following manner: - * - * 16 bit error code bit-segmentation - * - * 1 bit - Intentionally not used - * 3 bits - High level module ID - * 5 bits - Module-dependent error code - * 6 bits - Low level module errors - * 1 bit - Intentionally not used - * - * Low-level module errors (0x007E-0x0002) - * - * Module Nr Codes assigned - * MPI 7 0x0002-0x0010 - * GCM 2 0x0012-0x0014 - * AES 2 0x0020-0x0022 - * CAMELLIA 2 0x0024-0x0026 - * XTEA 1 0x0028-0x0028 - * BASE64 2 0x002A-0x002C - * PADLOCK 1 0x0030-0x0030 - * DES 1 0x0032-0x0032 - * CTR_DBRG 3 0x0034-0x003A - * ENTROPY 3 0x003C-0x0040 - * NET 11 0x0042-0x0056 - * ASN1 7 0x0060-0x006C - * MD2 1 0x0070-0x0070 - * MD4 1 0x0072-0x0072 - * MD5 1 0x0074-0x0074 - * SHA1 1 0x0076-0x0076 - * SHA2 1 0x0078-0x0078 - * SHA4 1 0x007A-0x007A - * - * High-level module nr (3 bits - 0x1...-0x8...) - * Name ID Nr of Errors - * PEM 1 8 - * X509 2 21 - * DHM 3 6 - * RSA 4 9 - * MD 5 4 - * CIPHER 6 5 - * SSL 7 30 - * - * Module dependent error code (5 bits 0x.08.-0x.F8.) - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Translate a PolarSSL error code into a string representation, - * Result is truncated if necessary and always includes a terminating - * null byte. - * - * \param errnum error code - * \param buffer buffer to place representation in - * \param buflen length of the buffer - */ -void error_strerror( int errnum, char *buffer, size_t buflen ); - -#ifdef __cplusplus -} -#endif - -#endif /* error.h */ diff --git a/polarssl/src/include/polarssl/gcm.h b/polarssl/src/include/polarssl/gcm.h deleted file mode 100644 index 2f88c70..0000000 --- a/polarssl/src/include/polarssl/gcm.h +++ /dev/null @@ -1,142 +0,0 @@ -/** - * \file gcm.h - * - * \brief Galois/Counter mode for AES - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_GCM_H -#define POLARSSL_GCM_H - -#include "aes.h" - -#include - -#define GCM_ENCRYPT 1 -#define GCM_DECRYPT 0 - -#define POLARSSL_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ -#define POLARSSL_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ - -/** - * \brief GCM context structure - */ -typedef struct { - aes_context aes_ctx; /*!< AES context used */ - uint64_t HL[16]; /*!< Precalculated HTable */ - uint64_t HH[16]; /*!< Precalculated HTable */ -} -gcm_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief GCM initialization (encryption) - * - * \param ctx GCM context to be initialized - * \param key encryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH - */ -int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize ); - -/** - * \brief GCM buffer encryption/decryption using AES - * - * \note On encryption, the output buffer can be the same as the input buffer. - * On decryption, the output buffer cannot be the same as input buffer. - * If buffers overlap, the output buffer must trail at least 8 bytes - * behind the input buffer. - * - * \param ctx GCM context - * \param mode GCM_ENCRYPT or GCM_DECRYPT - * \param length length of the input data - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data - * \param add_len length of additional data - * \param input buffer holding the input data - * \param output buffer for holding the output data - * \param tag_len length of the tag to generate - * \param tag buffer for holding the tag - * - * \return 0 if successful - */ -int gcm_crypt_and_tag( gcm_context *ctx, - int mode, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *input, - unsigned char *output, - size_t tag_len, - unsigned char *tag ); - -/** - * \brief GCM buffer authenticated decryption using AES - * - * \note On decryption, the output buffer cannot be the same as input buffer. - * If buffers overlap, the output buffer must trail at least 8 bytes - * behind the input buffer. - * - * \param ctx GCM context - * \param length length of the input data - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data - * \param add_len length of additional data - * \param tag buffer holding the tag - * \param tag_len length of the tag - * \param input buffer holding the input data - * \param output buffer for holding the output data - * - * \return 0 if successful and authenticated, - * POLARSSL_ERR_GCM_AUTH_FAILED if tag does not match - */ -int gcm_auth_decrypt( gcm_context *ctx, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *tag, - size_t tag_len, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int gcm_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* gcm.h */ diff --git a/polarssl/src/include/polarssl/havege.h b/polarssl/src/include/polarssl/havege.h deleted file mode 100644 index 53c4f38..0000000 --- a/polarssl/src/include/polarssl/havege.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * \file havege.h - * - * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_HAVEGE_H -#define POLARSSL_HAVEGE_H - -#include - -#define COLLECT_SIZE 1024 - -/** - * \brief HAVEGE state structure - */ -typedef struct -{ - int PT1, PT2, offset[2]; - int pool[COLLECT_SIZE]; - int WALK[8192]; -} -havege_state; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief HAVEGE initialization - * - * \param hs HAVEGE state to be initialized - */ -void havege_init( havege_state *hs ); - -/** - * \brief HAVEGE rand function - * - * \param p_rng A HAVEGE state - * \param output Buffer to fill - * \param len Length of buffer - * - * \return 0 - */ -int havege_random( void *p_rng, unsigned char *output, size_t len ); - -#ifdef __cplusplus -} -#endif - -#endif /* havege.h */ diff --git a/polarssl/src/include/polarssl/md.h b/polarssl/src/include/polarssl/md.h deleted file mode 100644 index 88596cb..0000000 --- a/polarssl/src/include/polarssl/md.h +++ /dev/null @@ -1,354 +0,0 @@ -/** - * \file md.h - * - * \brief Generic message digest wrapper - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_MD_H -#define POLARSSL_MD_H - -#include - -#if defined(_MSC_VER) && !defined(inline) -#define inline _inline -#else -#if defined(__ARMCC_VERSION) && !defined(inline) -#define inline __inline -#endif /* __ARMCC_VERSION */ -#endif /*_MSC_VER */ - -#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ -#define POLARSSL_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ -#define POLARSSL_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ -#define POLARSSL_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ - -typedef enum { - POLARSSL_MD_NONE=0, - POLARSSL_MD_MD2, - POLARSSL_MD_MD4, - POLARSSL_MD_MD5, - POLARSSL_MD_SHA1, - POLARSSL_MD_SHA224, - POLARSSL_MD_SHA256, - POLARSSL_MD_SHA384, - POLARSSL_MD_SHA512, -} md_type_t; - -#define POLARSSL_MD_MAX_SIZE 64 /* longest known is SHA512 */ - -/** - * Message digest information. Allows message digest functions to be called - * in a generic way. - */ -typedef struct { - /** Digest identifier */ - md_type_t type; - - /** Name of the message digest */ - const char * name; - - /** Output length of the digest function */ - int size; - - /** Digest initialisation function */ - void (*starts_func)( void *ctx ); - - /** Digest update function */ - void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); - - /** Digest finalisation function */ - void (*finish_func)( void *ctx, unsigned char *output ); - - /** Generic digest function */ - void (*digest_func)( const unsigned char *input, size_t ilen, - unsigned char *output ); - - /** Generic file digest function */ - int (*file_func)( const char *path, unsigned char *output ); - - /** HMAC Initialisation function */ - void (*hmac_starts_func)( void *ctx, const unsigned char *key, size_t keylen ); - - /** HMAC update function */ - void (*hmac_update_func)( void *ctx, const unsigned char *input, size_t ilen ); - - /** HMAC finalisation function */ - void (*hmac_finish_func)( void *ctx, unsigned char *output); - - /** HMAC context reset function */ - void (*hmac_reset_func)( void *ctx ); - - /** Generic HMAC function */ - void (*hmac_func)( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ); - - /** Allocate a new context */ - void * (*ctx_alloc_func)( void ); - - /** Free the given context */ - void (*ctx_free_func)( void *ctx ); - -} md_info_t; - -/** - * Generic message digest context. - */ -typedef struct { - /** Information about the associated message digest */ - const md_info_t *md_info; - - /** Digest-specific context */ - void *md_ctx; -} md_context_t; - -#define MD_CONTEXT_T_INIT { \ - NULL, /* md_info */ \ - NULL, /* md_ctx */ \ -} - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Returns the list of digests supported by the generic digest module. - * - * \return a statically allocated array of digests, the last entry - * is 0. - */ -const int *md_list( void ); - -/** - * \brief Returns the message digest information associated with the - * given digest name. - * - * \param md_name Name of the digest to search for. - * - * \return The message digest information associated with md_name or - * NULL if not found. - */ -const md_info_t *md_info_from_string( const char *md_name ); - -/** - * \brief Returns the message digest information associated with the - * given digest type. - * - * \param md_type type of digest to search for. - * - * \return The message digest information associated with md_type or - * NULL if not found. - */ -const md_info_t *md_info_from_type( md_type_t md_type ); - -/** - * \brief Initialises and fills the message digest context structure with - * the appropriate values. - * - * \param ctx context to initialise. May not be NULL. The - * digest-specific context (ctx->md_ctx) must be NULL. It will - * be allocated, and must be freed using md_free_ctx() later. - * \param md_info message digest to use. - * - * \returns \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on - * parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if - * allocation of the digest-specific context failed. - */ -int md_init_ctx( md_context_t *ctx, const md_info_t *md_info ); - -/** - * \brief Free the message-specific context of ctx. Freeing ctx itself - * remains the responsibility of the caller. - * - * \param ctx Free the message-specific context - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_free_ctx( md_context_t *ctx ); - -/** - * \brief Returns the size of the message digest output. - * - * \param md_info message digest info - * - * \return size of the message digest output. - */ -static inline unsigned char md_get_size( const md_info_t *md_info ) -{ - return md_info->size; -} - -/** - * \brief Returns the type of the message digest output. - * - * \param md_info message digest info - * - * \return type of the message digest output. - */ -static inline md_type_t md_get_type( const md_info_t *md_info ) -{ - return md_info->type; -} - -/** - * \brief Returns the name of the message digest output. - * - * \param md_info message digest info - * - * \return name of the message digest output. - */ -static inline const char *md_get_name( const md_info_t *md_info ) -{ - return md_info->name; -} - -/** - * \brief Set-up the given context for a new message digest - * - * \param ctx generic message digest context. - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_starts( md_context_t *ctx ); - -/** - * \brief Generic message digest process buffer - * - * \param ctx Generic message digest context - * \param input buffer holding the datal - * \param ilen length of the input data - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief Generic message digest final digest - * - * \param ctx Generic message digest context - * \param output Generic message digest checksum result - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_finish( md_context_t *ctx, unsigned char *output ); - -/** - * \brief Output = message_digest( input buffer ) - * - * \param md_info message digest info - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic message digest checksum result - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md( const md_info_t *md_info, const unsigned char *input, size_t ilen, - unsigned char *output ); - -/** - * \brief Output = message_digest( file contents ) - * - * \param md_info message digest info - * \param path input file name - * \param output generic message digest checksum result - * - * \return 0 if successful, POLARSSL_ERR_MD_FILE_OPEN_FAILED if fopen - * failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed, - * POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL. - */ -int md_file( const md_info_t *md_info, const char *path, unsigned char *output ); - -/** - * \brief Generic HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param key HMAC secret key - * \param keylen length of the HMAC key - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen ); - -/** - * \brief Generic HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief Generic HMAC final digest - * - * \param ctx HMAC context - * \param output Generic HMAC checksum result - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_hmac_finish( md_context_t *ctx, unsigned char *output); - -/** - * \brief Generic HMAC context reset - * - * \param ctx HMAC context to be reset - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_hmac_reset( md_context_t *ctx ); - -/** - * \brief Output = Generic_HMAC( hmac key, input buffer ) - * - * \param md_info message digest info - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic HMAC-result - * - * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ); - -#ifdef __cplusplus -} -#endif - -#endif /* POLARSSL_MD_H */ diff --git a/polarssl/src/include/polarssl/md2.h b/polarssl/src/include/polarssl/md2.h deleted file mode 100644 index 1f60470..0000000 --- a/polarssl/src/include/polarssl/md2.h +++ /dev/null @@ -1,153 +0,0 @@ -/** - * \file md2.h - * - * \brief MD2 message digest algorithm (hash function) - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_MD2_H -#define POLARSSL_MD2_H - -#include - -#define POLARSSL_ERR_MD2_FILE_IO_ERROR -0x0070 /**< Read/write error in file. */ - -/** - * \brief MD2 context structure - */ -typedef struct -{ - unsigned char cksum[16]; /*!< checksum of the data block */ - unsigned char state[48]; /*!< intermediate digest state */ - unsigned char buffer[16]; /*!< data block being processed */ - - unsigned char ipad[16]; /*!< HMAC: inner padding */ - unsigned char opad[16]; /*!< HMAC: outer padding */ - size_t left; /*!< amount of data in buffer */ -} -md2_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD2 context setup - * - * \param ctx context to be initialized - */ -void md2_starts( md2_context *ctx ); - -/** - * \brief MD2 process buffer - * - * \param ctx MD2 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD2 final digest - * - * \param ctx MD2 context - * \param output MD2 checksum result - */ -void md2_finish( md2_context *ctx, unsigned char output[16] ); - -/** - * \brief Output = MD2( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD2 checksum result - */ -void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ); - -/** - * \brief Output = MD2( file contents ) - * - * \param path input file name - * \param output MD2 checksum result - * - * \return 0 if successful, or POLARSSL_ERR_MD2_FILE_IO_ERROR - */ -int md2_file( const char *path, unsigned char output[16] ); - -/** - * \brief MD2 HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param key HMAC secret key - * \param keylen length of the HMAC key - */ -void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen ); - -/** - * \brief MD2 HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD2 HMAC final digest - * - * \param ctx HMAC context - * \param output MD2 HMAC checksum result - */ -void md2_hmac_finish( md2_context *ctx, unsigned char output[16] ); - -/** - * \brief MD2 HMAC context reset - * - * \param ctx HMAC context to be reset - */ -void md2_hmac_reset( md2_context *ctx ); - -/** - * \brief Output = HMAC-MD2( hmac key, input buffer ) - * - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output HMAC-MD2 result - */ -void md2_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[16] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int md2_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* md2.h */ diff --git a/polarssl/src/include/polarssl/md4.h b/polarssl/src/include/polarssl/md4.h deleted file mode 100644 index 2bd35ea..0000000 --- a/polarssl/src/include/polarssl/md4.h +++ /dev/null @@ -1,152 +0,0 @@ -/** - * \file md4.h - * - * \brief MD4 message digest algorithm (hash function) - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_MD4_H -#define POLARSSL_MD4_H - -#include - -#define POLARSSL_ERR_MD4_FILE_IO_ERROR -0x0072 /**< Read/write error in file. */ - -/** - * \brief MD4 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - - unsigned char ipad[64]; /*!< HMAC: inner padding */ - unsigned char opad[64]; /*!< HMAC: outer padding */ -} -md4_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD4 context setup - * - * \param ctx context to be initialized - */ -void md4_starts( md4_context *ctx ); - -/** - * \brief MD4 process buffer - * - * \param ctx MD4 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD4 final digest - * - * \param ctx MD4 context - * \param output MD4 checksum result - */ -void md4_finish( md4_context *ctx, unsigned char output[16] ); - -/** - * \brief Output = MD4( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD4 checksum result - */ -void md4( const unsigned char *input, size_t ilen, unsigned char output[16] ); - -/** - * \brief Output = MD4( file contents ) - * - * \param path input file name - * \param output MD4 checksum result - * - * \return 0 if successful, or POLARSSL_ERR_MD4_FILE_IO_ERROR - */ -int md4_file( const char *path, unsigned char output[16] ); - -/** - * \brief MD4 HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param key HMAC secret key - * \param keylen length of the HMAC key - */ -void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen ); - -/** - * \brief MD4 HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD4 HMAC final digest - * - * \param ctx HMAC context - * \param output MD4 HMAC checksum result - */ -void md4_hmac_finish( md4_context *ctx, unsigned char output[16] ); - -/** - * \brief MD4 HMAC context reset - * - * \param ctx HMAC context to be reset - */ -void md4_hmac_reset( md4_context *ctx ); - -/** - * \brief Output = HMAC-MD4( hmac key, input buffer ) - * - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output HMAC-MD4 result - */ -void md4_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[16] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int md4_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* md4.h */ diff --git a/polarssl/src/include/polarssl/md5.h b/polarssl/src/include/polarssl/md5.h deleted file mode 100644 index 936e9c9..0000000 --- a/polarssl/src/include/polarssl/md5.h +++ /dev/null @@ -1,154 +0,0 @@ -/** - * \file md5.h - * - * \brief MD5 message digest algorithm (hash function) - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_MD5_H -#define POLARSSL_MD5_H - -#include - -#define POLARSSL_ERR_MD5_FILE_IO_ERROR -0x0074 /**< Read/write error in file. */ - -/** - * \brief MD5 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - - unsigned char ipad[64]; /*!< HMAC: inner padding */ - unsigned char opad[64]; /*!< HMAC: outer padding */ -} -md5_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD5 context setup - * - * \param ctx context to be initialized - */ -void md5_starts( md5_context *ctx ); - -/** - * \brief MD5 process buffer - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD5 final digest - * - * \param ctx MD5 context - * \param output MD5 checksum result - */ -void md5_finish( md5_context *ctx, unsigned char output[16] ); - -/** - * \brief Output = MD5( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD5 checksum result - */ -void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); - -/** - * \brief Output = MD5( file contents ) - * - * \param path input file name - * \param output MD5 checksum result - * - * \return 0 if successful, or POLARSSL_ERR_MD5_FILE_IO_ERROR - */ -int md5_file( const char *path, unsigned char output[16] ); - -/** - * \brief MD5 HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param key HMAC secret key - * \param keylen length of the HMAC key - */ -void md5_hmac_starts( md5_context *ctx, - const unsigned char *key, size_t keylen ); - -/** - * \brief MD5 HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md5_hmac_update( md5_context *ctx, - const unsigned char *input, size_t ilen ); - -/** - * \brief MD5 HMAC final digest - * - * \param ctx HMAC context - * \param output MD5 HMAC checksum result - */ -void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ); - -/** - * \brief MD5 HMAC context reset - * - * \param ctx HMAC context to be reset - */ -void md5_hmac_reset( md5_context *ctx ); - -/** - * \brief Output = HMAC-MD5( hmac key, input buffer ) - * - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output HMAC-MD5 result - */ -void md5_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[16] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int md5_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* md5.h */ diff --git a/polarssl/src/include/polarssl/md_wrap.h b/polarssl/src/include/polarssl/md_wrap.h deleted file mode 100644 index 46849d0..0000000 --- a/polarssl/src/include/polarssl/md_wrap.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * \file md_wrap.h - * - * \brief Message digest wrappers. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_MD_WRAP_H -#define POLARSSL_MD_WRAP_H - -#include "config.h" -#include "md.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(POLARSSL_MD2_C) -extern const md_info_t md2_info; -#endif -#if defined(POLARSSL_MD4_C) -extern const md_info_t md4_info; -#endif -#if defined(POLARSSL_MD5_C) -extern const md_info_t md5_info; -#endif -#if defined(POLARSSL_SHA1_C) -extern const md_info_t sha1_info; -#endif -#if defined(POLARSSL_SHA2_C) -extern const md_info_t sha224_info; -extern const md_info_t sha256_info; -#endif -#if defined(POLARSSL_SHA4_C) -extern const md_info_t sha384_info; -extern const md_info_t sha512_info; -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* POLARSSL_MD_WRAP_H */ diff --git a/polarssl/src/include/polarssl/net.h b/polarssl/src/include/polarssl/net.h deleted file mode 100644 index 88302ac..0000000 --- a/polarssl/src/include/polarssl/net.h +++ /dev/null @@ -1,159 +0,0 @@ -/** - * \file net.h - * - * \brief Network communication functions - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_NET_H -#define POLARSSL_NET_H - -#include - -#define POLARSSL_ERR_NET_UNKNOWN_HOST -0x0056 /**< Failed to get an IP address for the given hostname. */ -#define POLARSSL_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ -#define POLARSSL_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ -#define POLARSSL_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ -#define POLARSSL_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ -#define POLARSSL_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ -#define POLARSSL_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ -#define POLARSSL_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ -#define POLARSSL_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ -#define POLARSSL_ERR_NET_WANT_READ -0x0052 /**< Connection requires a read call. */ -#define POLARSSL_ERR_NET_WANT_WRITE -0x0054 /**< Connection requires a write call. */ - -#define POLARSSL_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Initiate a TCP connection with host:port - * - * \param fd Socket to use - * \param host Host to connect to - * \param port Port to connect to - * - * \return 0 if successful, or one of: - * POLARSSL_ERR_NET_SOCKET_FAILED, - * POLARSSL_ERR_NET_UNKNOWN_HOST, - * POLARSSL_ERR_NET_CONNECT_FAILED - */ -int net_connect( int *fd, const char *host, int port ); - -/** - * \brief Create a listening socket on bind_ip:port. - * If bind_ip == NULL, all interfaces are binded. - * - * \param fd Socket to use - * \param bind_ip IP to bind to, can be NULL - * \param port Port number to use - * - * \return 0 if successful, or one of: - * POLARSSL_ERR_NET_SOCKET_FAILED, - * POLARSSL_ERR_NET_BIND_FAILED, - * POLARSSL_ERR_NET_LISTEN_FAILED - */ -int net_bind( int *fd, const char *bind_ip, int port ); - -/** - * \brief Accept a connection from a remote client - * - * \param bind_fd Relevant socket - * \param client_fd Will contain the connected client socket - * \param client_ip Will contain the client IP address - * - * \return 0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or - * POLARSSL_ERR_NET_WOULD_BLOCK is bind_fd was set to - * non-blocking and accept() is blocking. - */ -int net_accept( int bind_fd, int *client_fd, void *client_ip ); - -/** - * \brief Set the socket blocking - * - * \param fd Socket to set - * - * \return 0 if successful, or a non-zero error code - */ -int net_set_block( int fd ); - -/** - * \brief Set the socket non-blocking - * - * \param fd Socket to set - * - * \return 0 if successful, or a non-zero error code - */ -int net_set_nonblock( int fd ); - -/** - * \brief Portable usleep helper - * - * \param usec Amount of microseconds to sleep - * - * \note Real amount of time slept will not be less than - * select()'s timeout granularity (typically, 10ms). - */ -void net_usleep( unsigned long usec ); - -/** - * \brief Read at most 'len' characters. If no error occurs, - * the actual amount read is returned. - * - * \param ctx Socket - * \param buf The buffer to write to - * \param len Maximum length of the buffer - * - * \return This function returns the number of bytes received, - * or a non-zero error code; POLARSSL_ERR_NET_WANT_READ - * indicates read() is blocking. - */ -int net_recv( void *ctx, unsigned char *buf, size_t len ); - -/** - * \brief Write at most 'len' characters. If no error occurs, - * the actual amount read is returned. - * - * \param ctx Socket - * \param buf The buffer to read from - * \param len The length of the buffer - * - * \return This function returns the number of bytes sent, - * or a non-zero error code; POLARSSL_ERR_NET_WANT_WRITE - * indicates write() is blocking. - */ -int net_send( void *ctx, const unsigned char *buf, size_t len ); - -/** - * \brief Gracefully shutdown the connection - * - * \param fd The socket to close - */ -void net_close( int fd ); - -#ifdef __cplusplus -} -#endif - -#endif /* net.h */ diff --git a/polarssl/src/include/polarssl/openssl.h b/polarssl/src/include/polarssl/openssl.h deleted file mode 100644 index 62609a2..0000000 --- a/polarssl/src/include/polarssl/openssl.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * \file openssl.h - * - * \brief OpenSSL wrapper (definitions, inline functions). - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * OpenSSL wrapper contributed by David Barett - */ -#ifndef POLARSSL_OPENSSL_H -#define POLARSSL_OPENSSL_H - -#include "aes.h" -#include "md5.h" -#include "rsa.h" -#include "sha1.h" - -#define AES_SIZE 16 -#define AES_BLOCK_SIZE 16 -#define AES_KEY aes_context -#define MD5_CTX md5_context -#define SHA_CTX sha1_context - -#define SHA1_Init( CTX ) \ - sha1_starts( (CTX) ) -#define SHA1_Update( CTX, BUF, LEN ) \ - sha1_update( (CTX), (unsigned char *)(BUF), (LEN) ) -#define SHA1_Final( OUT, CTX ) \ - sha1_finish( (CTX), (OUT) ) - -#define MD5_Init( CTX ) \ - md5_starts( (CTX) ) -#define MD5_Update( CTX, BUF, LEN ) \ - md5_update( (CTX), (unsigned char *)(BUF), (LEN) ) -#define MD5_Final( OUT, CTX ) \ - md5_finish( (CTX), (OUT) ) - -#define AES_set_encrypt_key( KEY, KEYSIZE, CTX ) \ - aes_setkey_enc( (CTX), (KEY), (KEYSIZE) ) -#define AES_set_decrypt_key( KEY, KEYSIZE, CTX ) \ - aes_setkey_dec( (CTX), (KEY), (KEYSIZE) ) -#define AES_cbc_encrypt( INPUT, OUTPUT, LEN, CTX, IV, MODE ) \ - aes_crypt_cbc( (CTX), (MODE), (LEN), (IV), (INPUT), (OUTPUT) ) - -/* - * RSA stuff follows. TODO: needs cleanup - */ -inline int __RSA_Passthrough( void *output, void *input, int size ) -{ - memcpy( output, input, size ); - return size; -} - -inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr, - int len ) -{ - unsigned char *buffer = *(unsigned char **) bufptr; - rsa_context *rsa; - - /* - * Not a general-purpose parser: only parses public key from *exactly* - * openssl genrsa -out privkey.pem 512 (or 1024) - * openssl rsa -in privkey.pem -out privatekey.der -outform der - * openssl rsa -in privkey.pem -out pubkey.der -outform der -pubout - * - * TODO: make a general-purpose parse - */ - if( ignore != 0 || ( len != 94 && len != 162 ) ) - return( 0 ); - - rsa = (rsa_context *) malloc( sizeof( rsa_rsa ) ); - if( rsa == NULL ) - return( 0 ); - - memset( rsa, 0, sizeof( rsa_context ) ); - - if( ( len == 94 && - mpi_read_binary( &rsa->N, &buffer[ 25], 64 ) == 0 && - mpi_read_binary( &rsa->E, &buffer[ 91], 3 ) == 0 ) || - ( len == 162 && - mpi_read_binary( &rsa->N, &buffer[ 29], 128 ) == 0 ) && - mpi_read_binary( &rsa->E, &buffer[159], 3 ) == 0 ) - { - /* - * key read successfully - */ - rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3; - return( rsa ); - } - else - { - memset( rsa, 0, sizeof( rsa_context ) ); - free( rsa ); - return( 0 ); - } -} - -#define RSA rsa_context -#define RSA_PKCS1_PADDING 1 /* ignored; always encrypt with this */ -#define RSA_size( CTX ) (CTX)->len -#define RSA_free( CTX ) rsa_free( CTX ) -#define ERR_get_error( ) "ERR_get_error() not supported" -#define RSA_blinding_off( IGNORE ) - -#define d2i_RSAPrivateKey( a, b, c ) new rsa_context /* TODO: C++ bleh */ - -inline int RSA_public_decrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PUBLIC, &outsize, input, output ) ) return outsize; else return -1; } -inline int RSA_private_decrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PRIVATE, &outsize, input, output ) ) return outsize; else return -1; } -inline int RSA_public_encrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PUBLIC, size, input, output ) ) return RSA_size(key); else return -1; } -inline int RSA_private_encrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PRIVATE, size, input, output ) ) return RSA_size(key); else return -1; } - -#ifdef __cplusplus -} -#endif - -#endif /* openssl.h */ diff --git a/polarssl/src/include/polarssl/padlock.h b/polarssl/src/include/polarssl/padlock.h deleted file mode 100644 index ce13570..0000000 --- a/polarssl/src/include/polarssl/padlock.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * \file padlock.h - * - * \brief VIA PadLock ACE for HW encryption/decryption supported by some processors - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_PADLOCK_H -#define POLARSSL_PADLOCK_H - -#include "aes.h" - -#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ - -#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) - -#ifndef POLARSSL_HAVE_X86 -#define POLARSSL_HAVE_X86 -#endif - -#define PADLOCK_RNG 0x000C -#define PADLOCK_ACE 0x00C0 -#define PADLOCK_PHE 0x0C00 -#define PADLOCK_PMM 0x3000 - -#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15)) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PadLock detection routine - * - * \param The feature to detect - * - * \return 1 if CPU has support for the feature, 0 otherwise - */ -int padlock_supports( int feature ); - -/** - * \brief PadLock AES-ECB block en(de)cryption - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if success, 1 if operation failed - */ -int padlock_xcryptecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief PadLock AES-CBC buffer en(de)cryption - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if success, 1 if operation failed - */ -int padlock_xcryptcbc( aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -#ifdef __cplusplus -} -#endif - -#endif /* HAVE_X86 */ - -#endif /* padlock.h */ diff --git a/polarssl/src/include/polarssl/pem.h b/polarssl/src/include/polarssl/pem.h deleted file mode 100644 index 1505401..0000000 --- a/polarssl/src/include/polarssl/pem.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * \file pem.h - * - * \brief Privacy Enhanced Mail (PEM) decoding - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_PEM_H -#define POLARSSL_PEM_H - -#include - -/** - * \name PEM Error codes - * These error codes are returned in case of errors reading the - * PEM data. - * \{ - */ -#define POLARSSL_ERR_PEM_NO_HEADER_PRESENT -0x1080 /**< No PEM header found. */ -#define POLARSSL_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ -#define POLARSSL_ERR_PEM_MALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ -#define POLARSSL_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ -#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ -#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ -#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ -#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ -/* \} name */ - -/** - * \brief PEM context structure - */ -typedef struct -{ - unsigned char *buf; /*!< buffer for decoded data */ - size_t buflen; /*!< length of the buffer */ - unsigned char *info; /*!< buffer for extra header information */ -} -pem_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PEM context setup - * - * \param ctx context to be initialized - */ -void pem_init( pem_context *ctx ); - -/** - * \brief Read a buffer for PEM information and store the resulting - * data into the specified context buffers. - * - * \param ctx context to use - * \param header header string to seek and expect - * \param footer footer string to seek and expect - * \param data source data to look in - * \param pwd password for decryption (can be NULL) - * \param pwdlen length of password - * \param use_len destination for total length used - * - * \return 0 on success, ior a specific PEM error code - */ -int pem_read_buffer( pem_context *ctx, char *header, char *footer, - const unsigned char *data, - const unsigned char *pwd, - size_t pwdlen, size_t *use_len ); - -/** - * \brief PEM context memory freeing - * - * \param ctx context to be freed - */ -void pem_free( pem_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* pem.h */ diff --git a/polarssl/src/include/polarssl/pkcs11.h b/polarssl/src/include/polarssl/pkcs11.h deleted file mode 100644 index a65a72e..0000000 --- a/polarssl/src/include/polarssl/pkcs11.h +++ /dev/null @@ -1,126 +0,0 @@ -/** - * \file pkcs11.h - * - * \brief Wrapper for PKCS#11 library libpkcs11-helper - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_PKCS11_H -#define POLARSSL_PKCS11_H - -#include "config.h" - -#if defined(POLARSSL_PKCS11_C) - -#include "x509.h" - -#include - -/** - * Context for PKCS #11 private keys. - */ -typedef struct { - pkcs11h_certificate_t pkcs11h_cert; - int len; -} pkcs11_context; - -/** - * Fill in a PolarSSL certificate, based on the given PKCS11 helper certificate. - * - * \param cert X.509 certificate to fill - * \param pkcs11h_cert PKCS #11 helper certificate - * - * \return 0 on success. - */ -int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11h_cert ); - -/** - * Initialise a pkcs11_context, storing the given certificate. Note that the - * pkcs11_context will take over control of the certificate, freeing it when - * done. - * - * \param priv_key Private key structure to fill. - * \param pkcs11_cert PKCS #11 helper certificate - * - * \return 0 on success - */ -int pkcs11_priv_key_init( pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert ); - -/** - * Free the contents of the given private key context. Note that the structure - * itself is not freed. - * - * \param priv_key Private key structure to cleanup - */ -void pkcs11_priv_key_free( pkcs11_context *priv_key ); - -/** - * \brief Do an RSA private key decrypt, then remove the message padding - * - * \param ctx PKCS #11 context - * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param olen will contain the plaintext length - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int pkcs11_decrypt( pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - unsigned int output_max_len ); - -/** - * \brief Do a private RSA to sign a message digest - * - * \param ctx PKCS #11 context - * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int pkcs11_sign( pkcs11_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -#endif /* POLARSSL_PKCS11_C */ - -#endif /* POLARSSL_PKCS11_H */ diff --git a/polarssl/src/include/polarssl/rsa.h b/polarssl/src/include/polarssl/rsa.h deleted file mode 100644 index 513b037..0000000 --- a/polarssl/src/include/polarssl/rsa.h +++ /dev/null @@ -1,379 +0,0 @@ -/** - * \file rsa.h - * - * \brief The RSA public-key cryptosystem - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_RSA_H -#define POLARSSL_RSA_H - -#include "bignum.h" - -/* - * RSA Error codes - */ -#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ -#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ -#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ -#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */ -#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ -#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ -#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ -#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ -#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ - -/* - * PKCS#1 constants - */ -#define SIG_RSA_RAW 0 -#define SIG_RSA_MD2 2 -#define SIG_RSA_MD4 3 -#define SIG_RSA_MD5 4 -#define SIG_RSA_SHA1 5 -#define SIG_RSA_SHA224 14 -#define SIG_RSA_SHA256 11 -#define SIG_RSA_SHA384 12 -#define SIG_RSA_SHA512 13 - -#define RSA_PUBLIC 0 -#define RSA_PRIVATE 1 - -#define RSA_PKCS_V15 0 -#define RSA_PKCS_V21 1 - -#define RSA_SIGN 1 -#define RSA_CRYPT 2 - -#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30" -#define ASN1_STR_NULL "\x05" -#define ASN1_STR_OID "\x06" -#define ASN1_STR_OCTET_STRING "\x04" - -#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00" -#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a" -#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00" - -#define OID_ISO_MEMBER_BODIES "\x2a" -#define OID_ISO_IDENTIFIED_ORG "\x2b" - -/* - * ISO Member bodies OID parts - */ -#define OID_COUNTRY_US "\x86\x48" -#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d" - -/* - * ISO Identified organization OID parts - */ -#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a" - -/* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ -#define ASN1_HASH_MDX \ -( \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \ - ASN1_STR_OID "\x08" \ - OID_DIGEST_ALG_MDX \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x10" \ -) - -#define ASN1_HASH_SHA1 \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \ - ASN1_STR_OID "\x05" \ - OID_HASH_ALG_SHA1 \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x14" - -#define ASN1_HASH_SHA1_ALT \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \ - ASN1_STR_OID "\x05" \ - OID_HASH_ALG_SHA1 \ - ASN1_STR_OCTET_STRING "\x14" - -#define ASN1_HASH_SHA2X \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \ - ASN1_STR_OID "\x09" \ - OID_HASH_ALG_SHA2X \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x00" - -/** - * \brief RSA context structure - */ -typedef struct -{ - int ver; /*!< always 0 */ - size_t len; /*!< size(N) in chars */ - - mpi N; /*!< public modulus */ - mpi E; /*!< public exponent */ - - mpi D; /*!< private exponent */ - mpi P; /*!< 1st prime factor */ - mpi Q; /*!< 2nd prime factor */ - mpi DP; /*!< D % (P - 1) */ - mpi DQ; /*!< D % (Q - 1) */ - mpi QP; /*!< 1 / (Q % P) */ - - mpi RN; /*!< cached R^2 mod N */ - mpi RP; /*!< cached R^2 mod P */ - mpi RQ; /*!< cached R^2 mod Q */ - - int padding; /*!< RSA_PKCS_V15 for 1.5 padding and - RSA_PKCS_v21 for OAEP/PSS */ - int hash_id; /*!< Hash identifier of md_type_t as - specified in the md.h header file - for the EME-OAEP and EMSA-PSS - encoding */ -} -rsa_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Initialize an RSA context - * - * \param ctx RSA context to be initialized - * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 - * \param hash_id RSA_PKCS_V21 hash identifier - * - * \note The hash_id parameter is actually ignored - * when using RSA_PKCS_V15 padding. - */ -void rsa_init( rsa_context *ctx, - int padding, - int hash_id); - -/** - * \brief Generate an RSA keypair - * - * \param ctx RSA context that will hold the key - * \param f_rng RNG function - * \param p_rng RNG parameter - * \param nbits size of the public key in bits - * \param exponent public exponent (e.g., 65537) - * - * \note rsa_init() must be called beforehand to setup - * the RSA context. - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_gen_key( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ); - -/** - * \brief Check a public RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_check_pubkey( const rsa_context *ctx ); - -/** - * \brief Check a private RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_check_privkey( const rsa_context *ctx ); - -/** - * \brief Do an RSA public key operation - * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note This function does NOT take care of message - * padding. Also, be sure to set input[0] = 0 or assure that - * input is smaller than N. - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_public( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Do an RSA private key operation - * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_private( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Add the message padding, then do an RSA operation - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding) - * \param p_rng RNG parameter - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_pkcs1_encrypt( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Do an RSA operation, then remove the message padding - * - * \param ctx RSA context - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int rsa_pkcs1_decrypt( rsa_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Do a private RSA to sign a message digest - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding) - * \param p_rng RNG parameter - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding keep in mind that - * the hash_id in the RSA context is the one used for the - * encoding. hash_id in the function call is the type of hash - * that is encoded. According to RFC 3447 it is advised to - * keep both hashes the same. - */ -int rsa_pkcs1_sign( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Do a public RSA and check the message digest - * - * \param ctx points to an RSA public key - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding keep in mind that - * the hash_id in the RSA context is the one used for the - * verification. hash_id in the function call is the type of hash - * that is verified. According to RFC 3447 it is advised to - * keep both hashes the same. - */ -int rsa_pkcs1_verify( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Free the components of an RSA key - * - * \param ctx RSA Context to free - */ -void rsa_free( rsa_context *ctx ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int rsa_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* rsa.h */ diff --git a/polarssl/src/include/polarssl/sha1.h b/polarssl/src/include/polarssl/sha1.h deleted file mode 100644 index 0d5e67e..0000000 --- a/polarssl/src/include/polarssl/sha1.h +++ /dev/null @@ -1,152 +0,0 @@ -/** - * \file sha1.h - * - * \brief SHA-1 cryptographic hash function - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_SHA1_H -#define POLARSSL_SHA1_H - -#include - -#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */ - -/** - * \brief SHA-1 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - - unsigned char ipad[64]; /*!< HMAC: inner padding */ - unsigned char opad[64]; /*!< HMAC: outer padding */ -} -sha1_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-1 context setup - * - * \param ctx context to be initialized - */ -void sha1_starts( sha1_context *ctx ); - -/** - * \brief SHA-1 process buffer - * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-1 final digest - * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void sha1_finish( sha1_context *ctx, unsigned char output[20] ); - -/** - * \brief Output = SHA-1( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-1 checksum result - */ -void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); - -/** - * \brief Output = SHA-1( file contents ) - * - * \param path input file name - * \param output SHA-1 checksum result - * - * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR - */ -int sha1_file( const char *path, unsigned char output[20] ); - -/** - * \brief SHA-1 HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param key HMAC secret key - * \param keylen length of the HMAC key - */ -void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ); - -/** - * \brief SHA-1 HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-1 HMAC final digest - * - * \param ctx HMAC context - * \param output SHA-1 HMAC checksum result - */ -void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); - -/** - * \brief SHA-1 HMAC context reset - * - * \param ctx HMAC context to be reset - */ -void sha1_hmac_reset( sha1_context *ctx ); - -/** - * \brief Output = HMAC-SHA-1( hmac key, input buffer ) - * - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output HMAC-SHA-1 result - */ -void sha1_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[20] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int sha1_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* sha1.h */ diff --git a/polarssl/src/include/polarssl/sha2.h b/polarssl/src/include/polarssl/sha2.h deleted file mode 100644 index 811b0fd..0000000 --- a/polarssl/src/include/polarssl/sha2.h +++ /dev/null @@ -1,160 +0,0 @@ -/** - * \file sha2.h - * - * \brief SHA-224 and SHA-256 cryptographic hash function - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_SHA2_H -#define POLARSSL_SHA2_H - -#include - -#define POLARSSL_ERR_SHA2_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */ - -/** - * \brief SHA-256 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[8]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - - unsigned char ipad[64]; /*!< HMAC: inner padding */ - unsigned char opad[64]; /*!< HMAC: outer padding */ - int is224; /*!< 0 => SHA-256, else SHA-224 */ -} -sha2_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-256 context setup - * - * \param ctx context to be initialized - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void sha2_starts( sha2_context *ctx, int is224 ); - -/** - * \brief SHA-256 process buffer - * - * \param ctx SHA-256 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-256 final digest - * - * \param ctx SHA-256 context - * \param output SHA-224/256 checksum result - */ -void sha2_finish( sha2_context *ctx, unsigned char output[32] ); - -/** - * \brief Output = SHA-256( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-224/256 checksum result - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void sha2( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ); - -/** - * \brief Output = SHA-256( file contents ) - * - * \param path input file name - * \param output SHA-224/256 checksum result - * \param is224 0 = use SHA256, 1 = use SHA224 - * - * \return 0 if successful, or POLARSSL_ERR_SHA2_FILE_IO_ERROR - */ -int sha2_file( const char *path, unsigned char output[32], int is224 ); - -/** - * \brief SHA-256 HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen, - int is224 ); - -/** - * \brief SHA-256 HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-256 HMAC final digest - * - * \param ctx HMAC context - * \param output SHA-224/256 HMAC checksum result - */ -void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] ); - -/** - * \brief SHA-256 HMAC context reset - * - * \param ctx HMAC context to be reset - */ -void sha2_hmac_reset( sha2_context *ctx ); - -/** - * \brief Output = HMAC-SHA-256( hmac key, input buffer ) - * - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output HMAC-SHA-224/256 result - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void sha2_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int sha2_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* sha2.h */ diff --git a/polarssl/src/include/polarssl/sha4.h b/polarssl/src/include/polarssl/sha4.h deleted file mode 100644 index dafebec..0000000 --- a/polarssl/src/include/polarssl/sha4.h +++ /dev/null @@ -1,168 +0,0 @@ -/** - * \file sha4.h - * - * \brief SHA-384 and SHA-512 cryptographic hash function - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_SHA4_H -#define POLARSSL_SHA4_H - -#include - -#define POLARSSL_ERR_SHA4_FILE_IO_ERROR -0x007A /**< Read/write error in file. */ - -#if defined(_MSC_VER) || defined(__WATCOMC__) - #define UL64(x) x##ui64 - #define long64 __int64 -#else - #define UL64(x) x##ULL - #define long64 long long -#endif - -/** - * \brief SHA-512 context structure - */ -typedef struct -{ - unsigned long64 total[2]; /*!< number of bytes processed */ - unsigned long64 state[8]; /*!< intermediate digest state */ - unsigned char buffer[128]; /*!< data block being processed */ - - unsigned char ipad[128]; /*!< HMAC: inner padding */ - unsigned char opad[128]; /*!< HMAC: outer padding */ - int is384; /*!< 0 => SHA-512, else SHA-384 */ -} -sha4_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-512 context setup - * - * \param ctx context to be initialized - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void sha4_starts( sha4_context *ctx, int is384 ); - -/** - * \brief SHA-512 process buffer - * - * \param ctx SHA-512 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-512 final digest - * - * \param ctx SHA-512 context - * \param output SHA-384/512 checksum result - */ -void sha4_finish( sha4_context *ctx, unsigned char output[64] ); - -/** - * \brief Output = SHA-512( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-384/512 checksum result - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void sha4( const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ); - -/** - * \brief Output = SHA-512( file contents ) - * - * \param path input file name - * \param output SHA-384/512 checksum result - * \param is384 0 = use SHA512, 1 = use SHA384 - * - * \return 0 if successful, or POLARSSL_ERR_SHA4_FILE_IO_ERROR - */ -int sha4_file( const char *path, unsigned char output[64], int is384 ); - -/** - * \brief SHA-512 HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param is384 0 = use SHA512, 1 = use SHA384 - * \param key HMAC secret key - * \param keylen length of the HMAC key - */ -void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen, - int is384 ); - -/** - * \brief SHA-512 HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha4_hmac_update( sha4_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-512 HMAC final digest - * - * \param ctx HMAC context - * \param output SHA-384/512 HMAC checksum result - */ -void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] ); - -/** - * \brief SHA-512 HMAC context reset - * - * \param ctx HMAC context to be reset - */ -void sha4_hmac_reset( sha4_context *ctx ); - -/** - * \brief Output = HMAC-SHA-512( hmac key, input buffer ) - * - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output HMAC-SHA-384/512 result - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void sha4_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int sha4_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* sha4.h */ diff --git a/polarssl/src/include/polarssl/ssl.h b/polarssl/src/include/polarssl/ssl.h deleted file mode 100644 index 4ac6f86..0000000 --- a/polarssl/src/include/polarssl/ssl.h +++ /dev/null @@ -1,766 +0,0 @@ -/** - * \file ssl.h - * - * \brief SSL/TLS functions. - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_SSL_H -#define POLARSSL_SSL_H - -#include - -#include "net.h" -#include "dhm.h" -#include "rsa.h" -#include "md5.h" -#include "sha1.h" -#include "sha2.h" -#include "sha4.h" -#include "x509.h" -#include "config.h" - -#if defined(POLARSSL_PKCS11_C) -#include "pkcs11.h" -#endif - -#if defined(_MSC_VER) && !defined(inline) -#define inline _inline -#else -#if defined(__ARMCC_VERSION) && !defined(inline) -#define inline __inline -#endif /* __ARMCC_VERSION */ -#endif /*_MSC_VER */ - -/* - * SSL Error codes - */ -#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ -#define POLARSSL_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ -#define POLARSSL_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ -#define POLARSSL_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ -#define POLARSSL_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ -#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ -#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ -#define POLARSSL_ERR_SSL_NO_SESSION_FOUND -0x7400 /**< No session to recover was found. */ -#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ -#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message.*/ -#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ -#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key is not set, but needed. */ -#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ -#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ -#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ -#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ -#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM Read Public. */ -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret. */ -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ -#define POLARSSL_ERR_SSL_MALLOC_FAILED -0x7F00 /**< Memory allocation failed */ - -/* - * Various constants - */ -#define SSL_MAJOR_VERSION_3 3 -#define SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ -#define SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ -#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ -#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ - -#define SSL_IS_CLIENT 0 -#define SSL_IS_SERVER 1 -#define SSL_COMPRESS_NULL 0 - -#define SSL_VERIFY_NONE 0 -#define SSL_VERIFY_OPTIONAL 1 -#define SSL_VERIFY_REQUIRED 2 - -#define SSL_MAX_CONTENT_LEN 16384 - -/* - * Allow an extra 512 bytes for the record header - * and encryption overhead (counter + MAC + padding). - */ -#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + 512) - -/* - * Supported ciphersuites - */ -#define SSL_RSA_NULL_MD5 0x01 /**< Weak! */ -#define SSL_RSA_NULL_SHA 0x02 /**< Weak! */ -#define SSL_RSA_NULL_SHA256 0x3B /**< Weak! */ -#define SSL_RSA_DES_SHA 0x09 /**< Weak! Not in TLS 1.2 */ -#define SSL_EDH_RSA_DES_SHA 0x15 /**< Weak! Not in TLS 1.2 */ - -#define SSL_RSA_RC4_128_MD5 0x04 -#define SSL_RSA_RC4_128_SHA 0x05 - -#define SSL_RSA_DES_168_SHA 0x0A -#define SSL_EDH_RSA_DES_168_SHA 0x16 - -#define SSL_RSA_AES_128_SHA 0x2F -#define SSL_EDH_RSA_AES_128_SHA 0x33 -#define SSL_RSA_AES_256_SHA 0x35 -#define SSL_EDH_RSA_AES_256_SHA 0x39 -#define SSL_RSA_AES_128_SHA256 0x3C /**< TLS 1.2 */ -#define SSL_RSA_AES_256_SHA256 0x3D /**< TLS 1.2 */ -#define SSL_EDH_RSA_AES_128_SHA256 0x67 /**< TLS 1.2 */ -#define SSL_EDH_RSA_AES_256_SHA256 0x6B /**< TLS 1.2 */ - -#define SSL_RSA_CAMELLIA_128_SHA 0x41 -#define SSL_EDH_RSA_CAMELLIA_128_SHA 0x45 -#define SSL_RSA_CAMELLIA_256_SHA 0x84 -#define SSL_EDH_RSA_CAMELLIA_256_SHA 0x88 -#define SSL_RSA_CAMELLIA_128_SHA256 0xBA /**< TLS 1.2 */ -#define SSL_EDH_RSA_CAMELLIA_128_SHA256 0xBE /**< TLS 1.2 */ -#define SSL_RSA_CAMELLIA_256_SHA256 0xC0 /**< TLS 1.2 */ -#define SSL_EDH_RSA_CAMELLIA_256_SHA256 0xC4 /**< TLS 1.2 */ - -#define SSL_RSA_AES_128_GCM_SHA256 0x9C -#define SSL_RSA_AES_256_GCM_SHA384 0x9D -#define SSL_EDH_RSA_AES_128_GCM_SHA256 0x9E -#define SSL_EDH_RSA_AES_256_GCM_SHA384 0x9F - -/* - * Supported Signature and Hash algorithms (For TLS 1.2) - */ -#define SSL_HASH_NONE 0 -#define SSL_HASH_MD5 1 -#define SSL_HASH_SHA1 2 -#define SSL_HASH_SHA224 3 -#define SSL_HASH_SHA256 4 -#define SSL_HASH_SHA384 5 -#define SSL_HASH_SHA512 6 - -#define SSL_SIG_RSA 1 - -/* - * Message, alert and handshake types - */ -#define SSL_MSG_CHANGE_CIPHER_SPEC 20 -#define SSL_MSG_ALERT 21 -#define SSL_MSG_HANDSHAKE 22 -#define SSL_MSG_APPLICATION_DATA 23 - -#define SSL_ALERT_LEVEL_WARNING 1 -#define SSL_ALERT_LEVEL_FATAL 2 - -#define SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ -#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ -#define SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ -#define SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ -#define SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ -#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ -#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ -#define SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ -#define SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ -#define SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ -#define SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ -#define SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ -#define SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ -#define SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ -#define SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ -#define SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ -#define SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ -#define SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ -#define SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ -#define SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ -#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ -#define SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ -#define SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ -#define SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ -#define SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ - -#define SSL_HS_HELLO_REQUEST 0 -#define SSL_HS_CLIENT_HELLO 1 -#define SSL_HS_SERVER_HELLO 2 -#define SSL_HS_CERTIFICATE 11 -#define SSL_HS_SERVER_KEY_EXCHANGE 12 -#define SSL_HS_CERTIFICATE_REQUEST 13 -#define SSL_HS_SERVER_HELLO_DONE 14 -#define SSL_HS_CERTIFICATE_VERIFY 15 -#define SSL_HS_CLIENT_KEY_EXCHANGE 16 -#define SSL_HS_FINISHED 20 - -/* - * TLS extensions - */ -#define TLS_EXT_SERVERNAME 0 -#define TLS_EXT_SERVERNAME_HOSTNAME 0 - -#define TLS_EXT_SIG_ALG 13 - -/* - * SSL state machine - */ -typedef enum -{ - SSL_HELLO_REQUEST, - SSL_CLIENT_HELLO, - SSL_SERVER_HELLO, - SSL_SERVER_CERTIFICATE, - SSL_SERVER_KEY_EXCHANGE, - SSL_CERTIFICATE_REQUEST, - SSL_SERVER_HELLO_DONE, - SSL_CLIENT_CERTIFICATE, - SSL_CLIENT_KEY_EXCHANGE, - SSL_CERTIFICATE_VERIFY, - SSL_CLIENT_CHANGE_CIPHER_SPEC, - SSL_CLIENT_FINISHED, - SSL_SERVER_CHANGE_CIPHER_SPEC, - SSL_SERVER_FINISHED, - SSL_FLUSH_BUFFERS, - SSL_HANDSHAKE_OVER -} -ssl_states; - -typedef struct _ssl_session ssl_session; -typedef struct _ssl_context ssl_context; - -/* - * This structure is used for session resuming. - */ -struct _ssl_session -{ - time_t start; /*!< starting time */ - int ciphersuite; /*!< chosen ciphersuite */ - size_t length; /*!< session id length */ - unsigned char id[32]; /*!< session identifier */ - unsigned char master[48]; /*!< the master secret */ - ssl_session *next; /*!< next session entry */ -}; - -struct _ssl_context -{ - /* - * Miscellaneous - */ - int state; /*!< SSL handshake: current state */ - - int major_ver; /*!< equal to SSL_MAJOR_VERSION_3 */ - int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ - - int max_major_ver; /*!< max. major version from client */ - int max_minor_ver; /*!< max. minor version from client */ - - /* - * Callbacks (RNG, debug, I/O, verification) - */ - int (*f_rng)(void *, unsigned char *, size_t); - void (*f_dbg)(void *, int, const char *); - int (*f_recv)(void *, unsigned char *, size_t); - int (*f_send)(void *, const unsigned char *, size_t); - int (*f_vrfy)(void *, x509_cert *, int, int); - - void *p_rng; /*!< context for the RNG function */ - void *p_dbg; /*!< context for the debug function */ - void *p_recv; /*!< context for reading operations */ - void *p_send; /*!< context for writing operations */ - void *p_vrfy; /*!< context for verification */ - - /* - * Session layer - */ - int resume; /*!< session resuming flag */ - int timeout; /*!< sess. expiration time */ - ssl_session *session; /*!< current session data */ - int (*s_get)(ssl_context *); /*!< (server) get callback */ - int (*s_set)(ssl_context *); /*!< (server) set callback */ - - /* - * Record layer (incoming data) - */ - unsigned char *in_ctr; /*!< 64-bit incoming message counter */ - unsigned char *in_hdr; /*!< 5-byte record header (in_ctr+8) */ - unsigned char *in_msg; /*!< the message contents (in_hdr+5) */ - unsigned char *in_offt; /*!< read offset in application data */ - - int in_msgtype; /*!< record header: message type */ - size_t in_msglen; /*!< record header: message length */ - size_t in_left; /*!< amount of data read so far */ - - size_t in_hslen; /*!< current handshake message length */ - int nb_zero; /*!< # of 0-length encrypted messages */ - - /* - * Record layer (outgoing data) - */ - unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ - unsigned char *out_hdr; /*!< 5-byte record header (out_ctr+8) */ - unsigned char *out_msg; /*!< the message contents (out_hdr+5) */ - - int out_msgtype; /*!< record header: message type */ - size_t out_msglen; /*!< record header: message length */ - size_t out_left; /*!< amount of data not yet written */ - - /* - * PKI layer - */ - rsa_context *rsa_key; /*!< own RSA private key */ -#if defined(POLARSSL_PKCS11_C) - pkcs11_context *pkcs11_key; /*!< own PKCS#11 RSA private key */ -#endif - x509_cert *own_cert; /*!< own X.509 certificate */ - x509_cert *ca_chain; /*!< own trusted CA chain */ - x509_crl *ca_crl; /*!< trusted CA CRLs */ - x509_cert *peer_cert; /*!< peer X.509 cert chain */ - const char *peer_cn; /*!< expected peer CN */ - - int endpoint; /*!< 0: client, 1: server */ - int authmode; /*!< verification mode */ - int client_auth; /*!< flag for client auth. */ - int verify_result; /*!< verification result */ - - /* - * Crypto layer - */ - dhm_context dhm_ctx; /*!< DHM key exchange */ - unsigned char ctx_checksum[500]; /*!< Checksum context(s) */ - - void (*update_checksum)(ssl_context *, unsigned char *, size_t); - void (*calc_verify)(ssl_context *, unsigned char *); - void (*calc_finished)(ssl_context *, unsigned char *, int); - int (*tls_prf)(unsigned char *, size_t, char *, - unsigned char *, size_t, - unsigned char *, size_t); - - int do_crypt; /*!< en(de)cryption flag */ - int *ciphersuites; /*!< allowed ciphersuites */ - size_t pmslen; /*!< premaster length */ - unsigned int keylen; /*!< symmetric key length */ - size_t minlen; /*!< min. ciphertext length */ - size_t ivlen; /*!< IV length */ - size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ - size_t maclen; /*!< MAC length */ - - unsigned char randbytes[64]; /*!< random bytes */ - unsigned char premaster[256]; /*!< premaster secret */ - - unsigned char iv_enc[16]; /*!< IV (encryption) */ - unsigned char iv_dec[16]; /*!< IV (decryption) */ - - unsigned char mac_enc[32]; /*!< MAC (encryption) */ - unsigned char mac_dec[32]; /*!< MAC (decryption) */ - - unsigned long ctx_enc[134]; /*!< encryption context */ - unsigned long ctx_dec[134]; /*!< decryption context */ - - /* - * TLS extensions - */ - unsigned char *hostname; - size_t hostname_len; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -extern int ssl_default_ciphersuites[]; - -/** - * \brief Returns the list of ciphersuites supported by the SSL/TLS module. - * - * \return a statically allocated array of ciphersuites, the last - * entry is 0. - */ -static inline const int *ssl_list_ciphersuites( void ) -{ - return ssl_default_ciphersuites; -} - -/** - * \brief Return the name of the ciphersuite associated with the given - * ID - * - * \param ciphersuite_id SSL ciphersuite ID - * - * \return a string containing the ciphersuite name - */ -const char *ssl_get_ciphersuite_name( const int ciphersuite_id ); - -/** - * \brief Return the ID of the ciphersuite associated with the given - * name - * - * \param ciphersuite_name SSL ciphersuite name - * - * \return the ID with the ciphersuite or 0 if not found - */ -int ssl_get_ciphersuite_id( const char *ciphersuite_name ); - -/** - * \brief Initialize an SSL context - * - * \param ssl SSL context - * - * \return 0 if successful, or POLARSSL_ERR_SSL_MALLOC_FAILED if - * memory allocation failed - */ -int ssl_init( ssl_context *ssl ); - -/** - * \brief Reset an already initialized SSL context for re-use - * while retaining application-set variables, function - * pointers and data. - * - * \param ssl SSL context - */ -void ssl_session_reset( ssl_context *ssl ); - -/** - * \brief Set the current endpoint type - * - * \param ssl SSL context - * \param endpoint must be SSL_IS_CLIENT or SSL_IS_SERVER - */ -void ssl_set_endpoint( ssl_context *ssl, int endpoint ); - -/** - * \brief Set the certificate verification mode - * - * \param ssl SSL context - * \param authmode can be: - * - * SSL_VERIFY_NONE: peer certificate is not checked (default), - * this is insecure and SHOULD be avoided. - * - * SSL_VERIFY_OPTIONAL: peer certificate is checked, however the - * handshake continues even if verification failed; - * ssl_get_verify_result() can be called after the - * handshake is complete. - * - * SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, - * handshake is aborted if verification failed. - */ -void ssl_set_authmode( ssl_context *ssl, int authmode ); - -/** - * \brief Set the verification callback (Optional). - * - * If set, the verification callback is called once for every - * certificate in the chain. The verification function has the - * following parameter: (void *parameter, x509_cert certificate, - * int certifcate_depth, int preverify_ok). It should - * return 0 on SUCCESS. - * - * \param ssl SSL context - * \param f_vrfy verification function - * \param p_vrfy verification parameter - */ -void ssl_set_verify( ssl_context *ssl, - int (*f_vrfy)(void *, x509_cert *, int, int), - void *p_vrfy ); - -/** - * \brief Set the random number generator callback - * - * \param ssl SSL context - * \param f_rng RNG function - * \param p_rng RNG parameter - */ -void ssl_set_rng( ssl_context *ssl, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Set the debug callback - * - * \param ssl SSL context - * \param f_dbg debug function - * \param p_dbg debug parameter - */ -void ssl_set_dbg( ssl_context *ssl, - void (*f_dbg)(void *, int, const char *), - void *p_dbg ); - -/** - * \brief Set the underlying BIO read and write callbacks - * - * \param ssl SSL context - * \param f_recv read callback - * \param p_recv read parameter - * \param f_send write callback - * \param p_send write parameter - */ -void ssl_set_bio( ssl_context *ssl, - int (*f_recv)(void *, unsigned char *, size_t), void *p_recv, - int (*f_send)(void *, const unsigned char *, size_t), void *p_send ); - -/** - * \brief Set the session callbacks (server-side only) - * - * \param ssl SSL context - * \param s_get session get callback - * \param s_set session set callback - */ -void ssl_set_scb( ssl_context *ssl, - int (*s_get)(ssl_context *), - int (*s_set)(ssl_context *) ); - -/** - * \brief Set the session resuming flag, timeout and data - * - * \param ssl SSL context - * \param resume if 0 (default), the session will not be resumed - * \param timeout session timeout in seconds, or 0 (no timeout) - * \param session session context - */ -void ssl_set_session( ssl_context *ssl, int resume, int timeout, - ssl_session *session ); - -/** - * \brief Set the list of allowed ciphersuites - * - * \param ssl SSL context - * \param ciphersuites 0-terminated list of allowed ciphersuites - */ -void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites ); - -/** - * \brief Set the data required to verify peer certificate - * - * \param ssl SSL context - * \param ca_chain trusted CA chain - * \param ca_crl trusted CA CRLs - * \param peer_cn expected peer CommonName (or NULL) - * - * \note TODO: add two more parameters: depth and crl - */ -void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain, - x509_crl *ca_crl, const char *peer_cn ); - -/** - * \brief Set own certificate and private key - * - * \param ssl SSL context - * \param own_cert own public certificate - * \param rsa_key own private RSA key - */ -void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert, - rsa_context *rsa_key ); - -#if defined(POLARSSL_PKCS11_C) -/** - * \brief Set own certificate and PKCS#11 private key - * - * \param ssl SSL context - * \param own_cert own public certificate - * \param pkcs11_key own PKCS#11 RSA key - */ -void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert, - pkcs11_context *pkcs11_key ); -#endif - -/** - * \brief Set the Diffie-Hellman public P and G values, - * read as hexadecimal strings (server-side only) - * - * \param ssl SSL context - * \param dhm_P Diffie-Hellman-Merkle modulus - * \param dhm_G Diffie-Hellman-Merkle generator - * - * \return 0 if successful - */ -int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ); - -/** - * \brief Set the Diffie-Hellman public P and G values, - * read from existing context (server-side only) - * - * \param ssl SSL context - * \param dhm_ctx Diffie-Hellman-Merkle context - * - * \return 0 if successful - */ -int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ); - -/** - * \brief Set hostname for ServerName TLS Extension - * - * - * \param ssl SSL context - * \param hostname the server hostname - * - * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED - */ -int ssl_set_hostname( ssl_context *ssl, const char *hostname ); - -/** - * \brief Set the maximum supported version sent from the client side - * - * \param ssl SSL context - * \param major Major version number (only SSL_MAJOR_VERSION_3 supported) - * \param minor Minor version number (SSL_MINOR_VERSION_0, - * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2, - * SSL_MINOR_VERSION_3 supported) - */ -void ssl_set_max_version( ssl_context *ssl, int major, int minor ); - -/** - * \brief Return the number of data bytes available to read - * - * \param ssl SSL context - * - * \return how many bytes are available in the read buffer - */ -size_t ssl_get_bytes_avail( const ssl_context *ssl ); - -/** - * \brief Return the result of the certificate verification - * - * \param ssl SSL context - * - * \return 0 if successful, or a combination of: - * BADCERT_EXPIRED - * BADCERT_REVOKED - * BADCERT_CN_MISMATCH - * BADCERT_NOT_TRUSTED - */ -int ssl_get_verify_result( const ssl_context *ssl ); - -/** - * \brief Return the name of the current ciphersuite - * - * \param ssl SSL context - * - * \return a string containing the ciphersuite name - */ -const char *ssl_get_ciphersuite( const ssl_context *ssl ); - -/** - * \brief Return the current SSL version (SSLv3/TLSv1/etc) - * - * \param ssl SSL context - * - * \return a string containing the SSL version - */ -const char *ssl_get_version( const ssl_context *ssl ); - -/** - * \brief Perform the SSL handshake - * - * \param ssl SSL context - * - * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ, - * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code. - */ -int ssl_handshake( ssl_context *ssl ); - -/** - * \brief Read at most 'len' application data bytes - * - * \param ssl SSL context - * \param buf buffer that will hold the data - * \param len how many bytes must be read - * - * \return This function returns the number of bytes read, 0 for EOF, - * or a negative error code. - */ -int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ); - -/** - * \brief Write exactly 'len' application data bytes - * - * \param ssl SSL context - * \param buf buffer holding the data - * \param len how many bytes must be written - * - * \return This function returns the number of bytes written, - * or a negative error code. - * - * \note When this function returns POLARSSL_ERR_NET_WANT_WRITE, - * it must be called later with the *same* arguments, - * until it returns a positive value. - */ -int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ); - -/** - * \brief Send an alert message - * - * \param ssl SSL context - * \param level The alert level of the message - * (SSL_ALERT_LEVEL_WARNING or SSL_ALERT_LEVEL_FATAL) - * \param message The alert message (SSL_ALERT_MSG_*) - * - * \return 1 if successful, or a specific SSL error code. - */ -int ssl_send_alert_message( ssl_context *ssl, - unsigned char level, - unsigned char message ); -/** - * \brief Notify the peer that the connection is being closed - * - * \param ssl SSL context - */ -int ssl_close_notify( ssl_context *ssl ); - -/** - * \brief Free an SSL context - * - * \param ssl SSL context - */ -void ssl_free( ssl_context *ssl ); - -/* - * Internal functions (do not call directly) - */ -int ssl_handshake_client( ssl_context *ssl ); -int ssl_handshake_server( ssl_context *ssl ); - -int ssl_derive_keys( ssl_context *ssl ); - -int ssl_read_record( ssl_context *ssl ); -/** - * \return 0 if successful, POLARSSL_ERR_SSL_CONN_EOF on EOF or - * another negative error code. - */ -int ssl_fetch_input( ssl_context *ssl, size_t nb_want ); - -int ssl_write_record( ssl_context *ssl ); -int ssl_flush_output( ssl_context *ssl ); - -int ssl_parse_certificate( ssl_context *ssl ); -int ssl_write_certificate( ssl_context *ssl ); - -int ssl_parse_change_cipher_spec( ssl_context *ssl ); -int ssl_write_change_cipher_spec( ssl_context *ssl ); - -int ssl_parse_finished( ssl_context *ssl ); -int ssl_write_finished( ssl_context *ssl ); - -void ssl_kickstart_checksum( ssl_context *ssl, int ciphersuite, - unsigned char *input_buf, size_t len ); - -#ifdef __cplusplus -} -#endif - -#endif /* ssl.h */ diff --git a/polarssl/src/include/polarssl/timing.h b/polarssl/src/include/polarssl/timing.h deleted file mode 100644 index 355c63c..0000000 --- a/polarssl/src/include/polarssl/timing.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * \file timing.h - * - * \brief Portable interface to the CPU cycle counter - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_TIMING_H -#define POLARSSL_TIMING_H - -/** - * \brief timer structure - */ -struct hr_time -{ - unsigned char opaque[32]; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -extern volatile int alarmed; - -/** - * \brief Return the CPU cycle counter value - */ -unsigned long hardclock( void ); - -/** - * \brief Return the elapsed time in milliseconds - * - * \param val points to a timer structure - * \param reset if set to 1, the timer is restarted - */ -unsigned long get_timer( struct hr_time *val, int reset ); - -/** - * \brief Setup an alarm clock - * - * \param seconds delay before the "alarmed" flag is set - */ -void set_alarm( int seconds ); - -/** - * \brief Sleep for a certain amount of time - * - * \param milliseconds delay in milliseconds - */ -void m_sleep( int milliseconds ); - -#ifdef __cplusplus -} -#endif - -#endif /* timing.h */ diff --git a/polarssl/src/include/polarssl/version.h b/polarssl/src/include/polarssl/version.h deleted file mode 100644 index 98eb0b3..0000000 --- a/polarssl/src/include/polarssl/version.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file version.h - * - * \brief Run-time version information - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * This set of compile-time defines and run-time variables can be used to - * determine the version number of the PolarSSL library used. - */ -#ifndef POLARSSL_VERSION_H -#define POLARSSL_VERSION_H - -#include "config.h" - -/** - * The version number x.y.z is split into three parts. - * Major, Minor, Patchlevel - */ -#define POLARSSL_VERSION_MAJOR 1 -#define POLARSSL_VERSION_MINOR 1 -#define POLARSSL_VERSION_PATCH 1 - -/** - * The single version number has the following structure: - * MMNNPP00 - * Major version | Minor version | Patch version - */ -#define POLARSSL_VERSION_NUMBER 0x01010100 -#define POLARSSL_VERSION_STRING "1.1.1" -#define POLARSSL_VERSION_STRING_FULL "PolarSSL 1.1.1" - -#if defined(POLARSSL_VERSION_C) - -/** - * Get the version number. - * - * \return The constructed version number in the format - * MMNNPP00 (Major, Minor, Patch). - */ -unsigned int version_get_number( void ); - -/** - * Get the version string ("x.y.z"). - * - * \param string The string that will receive the value. - * (Should be at least 9 bytes in size) - */ -void version_get_string( char *string ); - -/** - * Get the full version string ("PolarSSL x.y.z"). - * - * \param string The string that will receive the value. - * (Should be at least 18 bytes in size) - */ -void version_get_string_full( char *string ); - -#endif /* POLARSSL_VERSION_C */ - -#endif /* version.h */ diff --git a/polarssl/src/include/polarssl/x509.h b/polarssl/src/include/polarssl/x509.h deleted file mode 100644 index 2cd883f..0000000 --- a/polarssl/src/include/polarssl/x509.h +++ /dev/null @@ -1,733 +0,0 @@ -/** - * \file x509.h - * - * \brief X.509 certificate and private key decoding - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_X509_H -#define POLARSSL_X509_H - -#include "asn1.h" -#include "rsa.h" -#include "dhm.h" - -/** - * \addtogroup x509_module - * \{ - */ - -/** - * \name X509 Error codes - * \{ - */ -#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ -#define POLARSSL_ERR_X509_CERT_INVALID_PEM -0x2100 /**< The PEM-encoded certificate contains invalid elements, e.g. invalid character. */ -#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT -0x2180 /**< The certificate format is invalid, e.g. different type expected. */ -#define POLARSSL_ERR_X509_CERT_INVALID_VERSION -0x2200 /**< The certificate version element is invalid. */ -#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ -#define POLARSSL_ERR_X509_CERT_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ -#define POLARSSL_ERR_X509_CERT_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ -#define POLARSSL_ERR_X509_CERT_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ -#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY -0x2480 /**< The pubkey tag or value is invalid (only RSA is supported). */ -#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE -0x2500 /**< The signature tag or value invalid. */ -#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS -0x2580 /**< The extension tag or value is invalid. */ -#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION -0x2600 /**< Certificate or CRL has an unsupported version number. */ -#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG -0x2680 /**< Signature algorithm (oid) is unsupported. */ -#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG -0x2700 /**< Key algorithm is unsupported (only RSA is supported). */ -#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH -0x2780 /**< Certificate signature algorithms do not match. (see \c ::x509_cert sig_oid) */ -#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x2800 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ -#define POLARSSL_ERR_X509_KEY_INVALID_VERSION -0x2880 /**< Unsupported RSA key version */ -#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT -0x2900 /**< Invalid RSA key tag or value. */ -#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT -0x2980 /**< Format not recognized as DER or PEM. */ -#define POLARSSL_ERR_X509_INVALID_INPUT -0x2A00 /**< Input invalid. */ -#define POLARSSL_ERR_X509_MALLOC_FAILED -0x2A80 /**< Allocation of memory failed. */ -#define POLARSSL_ERR_X509_FILE_IO_ERROR -0x2B00 /**< Read/write of file failed. */ -/* \} name */ - - -/** - * \name X509 Verify codes - * \{ - */ -#define BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ -#define BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ -#define BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ -#define BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ -#define BADCRL_NOT_TRUSTED 0x10 /**< CRL is not correctly signed by the trusted CA. */ -#define BADCRL_EXPIRED 0x20 /**< CRL is expired. */ -#define BADCERT_MISSING 0x40 /**< Certificate was missing. */ -#define BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ -/* \} name */ -/* \} addtogroup x509_module */ - -/* - * various object identifiers - */ -#define X520_COMMON_NAME 3 -#define X520_COUNTRY 6 -#define X520_LOCALITY 7 -#define X520_STATE 8 -#define X520_ORGANIZATION 10 -#define X520_ORG_UNIT 11 -#define PKCS9_EMAIL 1 - -#define X509_OUTPUT_DER 0x01 -#define X509_OUTPUT_PEM 0x02 -#define PEM_LINE_LENGTH 72 -#define X509_ISSUER 0x01 -#define X509_SUBJECT 0x02 - -#define OID_X520 "\x55\x04" -#define OID_CN OID_X520 "\x03" -#define OID_COUNTRY OID_X520 "\x06" -#define OID_LOCALITY OID_X520 "\x07" -#define OID_STATE OID_X520 "\x08" -#define OID_ORGANIZATION OID_X520 "\x0A" -#define OID_ORG_UNIT OID_X520 "\x0B" - -#define OID_PKCS1 "\x2A\x86\x48\x86\xF7\x0D\x01\x01" -#define OID_PKCS1_RSA OID_PKCS1 "\x01" -#define OID_PKCS1_SHA1 OID_PKCS1 "\x05" - -#define OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" - -#define OID_PKCS9 "\x2A\x86\x48\x86\xF7\x0D\x01\x09" -#define OID_PKCS9_EMAIL OID_PKCS9 "\x01" - -/** ISO arc for standard certificate and CRL extensions */ -#define OID_ID_CE "\x55\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ - -/** - * Private Internet Extensions - * { iso(1) identified-organization(3) dod(6) internet(1) - * security(5) mechanisms(5) pkix(7) } - */ -#define OID_PKIX "\x2B\x06\x01\x05\x05\x07" - -/* - * OIDs for standard certificate extensions - */ -#define OID_AUTHORITY_KEY_IDENTIFIER OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ -#define OID_SUBJECT_KEY_IDENTIFIER OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ -#define OID_KEY_USAGE OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ -#define OID_CERTIFICATE_POLICIES OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ -#define OID_POLICY_MAPPINGS OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ -#define OID_SUBJECT_ALT_NAME OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ -#define OID_ISSUER_ALT_NAME OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ -#define OID_SUBJECT_DIRECTORY_ATTRS OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ -#define OID_BASIC_CONSTRAINTS OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ -#define OID_NAME_CONSTRAINTS OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ -#define OID_POLICY_CONSTRAINTS OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ -#define OID_EXTENDED_KEY_USAGE OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ -#define OID_CRL_DISTRIBUTION_POINTS OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ -#define OID_INIHIBIT_ANYPOLICY OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ -#define OID_FRESHEST_CRL OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ - -/* - * X.509 v3 Key Usage Extension flags - */ -#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ -#define KU_NON_REPUDIATION (0x40) /* bit 1 */ -#define KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ -#define KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ -#define KU_KEY_AGREEMENT (0x08) /* bit 4 */ -#define KU_KEY_CERT_SIGN (0x04) /* bit 5 */ -#define KU_CRL_SIGN (0x02) /* bit 6 */ - -/* - * X.509 v3 Extended key usage OIDs - */ -#define OID_ANY_EXTENDED_KEY_USAGE OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ - -#define OID_KP OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ -#define OID_SERVER_AUTH OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ -#define OID_CLIENT_AUTH OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ -#define OID_CODE_SIGNING OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ -#define OID_EMAIL_PROTECTION OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ -#define OID_TIME_STAMPING OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ -#define OID_OCSP_SIGNING OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ - -#define STRING_SERVER_AUTH "TLS Web Server Authentication" -#define STRING_CLIENT_AUTH "TLS Web Client Authentication" -#define STRING_CODE_SIGNING "Code Signing" -#define STRING_EMAIL_PROTECTION "E-mail Protection" -#define STRING_TIME_STAMPING "Time Stamping" -#define STRING_OCSP_SIGNING "OCSP Signing" - -/* - * OIDs for CRL extensions - */ -#define OID_PRIVATE_KEY_USAGE_PERIOD OID_ID_CE "\x10" -#define OID_CRL_NUMBER OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ - -/* - * Netscape certificate extensions - */ -#define OID_NETSCAPE "\x60\x86\x48\x01\x86\xF8\x42" /**< Netscape OID */ -#define OID_NS_CERT OID_NETSCAPE "\x01" -#define OID_NS_CERT_TYPE OID_NS_CERT "\x01" -#define OID_NS_BASE_URL OID_NS_CERT "\x02" -#define OID_NS_REVOCATION_URL OID_NS_CERT "\x03" -#define OID_NS_CA_REVOCATION_URL OID_NS_CERT "\x04" -#define OID_NS_RENEWAL_URL OID_NS_CERT "\x07" -#define OID_NS_CA_POLICY_URL OID_NS_CERT "\x08" -#define OID_NS_SSL_SERVER_NAME OID_NS_CERT "\x0C" -#define OID_NS_COMMENT OID_NS_CERT "\x0D" -#define OID_NS_DATA_TYPE OID_NETSCAPE "\x02" -#define OID_NS_CERT_SEQUENCE OID_NS_DATA_TYPE "\x05" - -/* - * Netscape certificate types - * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) - */ - -#define NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ -#define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ -#define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ -#define NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ -#define NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ -#define NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ -#define NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ -#define NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ - -#define EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) -#define EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) -#define EXT_KEY_USAGE (1 << 2) -#define EXT_CERTIFICATE_POLICIES (1 << 3) -#define EXT_POLICY_MAPPINGS (1 << 4) -#define EXT_SUBJECT_ALT_NAME (1 << 5) -#define EXT_ISSUER_ALT_NAME (1 << 6) -#define EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) -#define EXT_BASIC_CONSTRAINTS (1 << 8) -#define EXT_NAME_CONSTRAINTS (1 << 9) -#define EXT_POLICY_CONSTRAINTS (1 << 10) -#define EXT_EXTENDED_KEY_USAGE (1 << 11) -#define EXT_CRL_DISTRIBUTION_POINTS (1 << 12) -#define EXT_INIHIBIT_ANYPOLICY (1 << 13) -#define EXT_FRESHEST_CRL (1 << 14) - -#define EXT_NS_CERT_TYPE (1 << 16) - -/* - * Storage format identifiers - * Recognized formats: PEM and DER - */ -#define X509_FORMAT_DER 1 -#define X509_FORMAT_PEM 2 - -/** - * \addtogroup x509_module - * \{ */ - -/** - * \name Structures for parsing X.509 certificates and CRLs - * \{ - */ - -/** - * Type-length-value structure that allows for ASN1 using DER. - */ -typedef asn1_buf x509_buf; - -/** - * Container for ASN1 bit strings. - */ -typedef asn1_bitstring x509_bitstring; - -/** - * Container for ASN1 named information objects. - * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.). - */ -typedef struct _x509_name -{ - x509_buf oid; /**< The object identifier. */ - x509_buf val; /**< The named value. */ - struct _x509_name *next; /**< The next named information object. */ -} -x509_name; - -/** - * Container for a sequence of ASN.1 items - */ -typedef asn1_sequence x509_sequence; - -/** Container for date and time (precision in seconds). */ -typedef struct _x509_time -{ - int year, mon, day; /**< Date. */ - int hour, min, sec; /**< Time. */ -} -x509_time; - -/** - * Container for an X.509 certificate. The certificate may be chained. - */ -typedef struct _x509_cert -{ - x509_buf raw; /**< The raw certificate data (DER). */ - x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ - - int version; /**< The X.509 version. (0=v1, 1=v2, 2=v3) */ - x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ - x509_buf sig_oid1; /**< Signature algorithm, e.g. sha1RSA */ - - x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ - x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ - - x509_name issuer; /**< The parsed issuer data (named information object). */ - x509_name subject; /**< The parsed subject data (named information object). */ - - x509_time valid_from; /**< Start time of certificate validity. */ - x509_time valid_to; /**< End time of certificate validity. */ - - x509_buf pk_oid; /**< Subject public key info. Includes the public key algorithm and the key itself. */ - rsa_context rsa; /**< Container for the RSA context. Only RSA is supported for public keys at this time. */ - - x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ - x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ - x509_buf v3_ext; /**< Optional X.509 v3 extensions. Only Basic Contraints are supported at this time. */ - x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ - - int ext_types; /**< Bit string containing detected and parsed extensions */ - int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ - int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. */ - - unsigned char key_usage; /**< Optional key usage extension value: See the values below */ - - x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ - - unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values below */ - - x509_buf sig_oid2; /**< Signature algorithm. Must match sig_oid1. */ - x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ - int sig_alg; /**< Internal representation of the signature algorithm, e.g. SIG_RSA_MD2 */ - - struct _x509_cert *next; /**< Next certificate in the CA-chain. */ -} -x509_cert; - -/** - * Certificate revocation list entry. - * Contains the CA-specific serial numbers and revocation dates. - */ -typedef struct _x509_crl_entry -{ - x509_buf raw; - - x509_buf serial; - - x509_time revocation_date; - - x509_buf entry_ext; - - struct _x509_crl_entry *next; -} -x509_crl_entry; - -/** - * Certificate revocation list structure. - * Every CRL may have multiple entries. - */ -typedef struct _x509_crl -{ - x509_buf raw; /**< The raw certificate data (DER). */ - x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ - - int version; - x509_buf sig_oid1; - - x509_buf issuer_raw; /**< The raw issuer data (DER). */ - - x509_name issuer; /**< The parsed issuer data (named information object). */ - - x509_time this_update; - x509_time next_update; - - x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ - - x509_buf crl_ext; - - x509_buf sig_oid2; - x509_buf sig; - int sig_alg; - - struct _x509_crl *next; -} -x509_crl; -/** \} name Structures for parsing X.509 certificates and CRLs */ -/** \} addtogroup x509_module */ - -/** - * \name Structures for writing X.509 certificates. - * XvP: commented out as they are not used. - * - typedef struct _x509_node x509_node; - * - typedef struct _x509_raw x509_raw; - */ -/* -typedef struct _x509_node -{ - unsigned char *data; - unsigned char *p; - unsigned char *end; - - size_t len; -} -x509_node; - -typedef struct _x509_raw -{ - x509_node raw; - x509_node tbs; - - x509_node version; - x509_node serial; - x509_node tbs_signalg; - x509_node issuer; - x509_node validity; - x509_node subject; - x509_node subpubkey; - - x509_node signalg; - x509_node sign; -} -x509_raw; -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name Functions to read in DHM parameters, a certificate, CRL or private RSA key - * \{ - */ - -/** \ingroup x509_module */ -/** - * \brief Parse one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. - * - * \param chain points to the start of the chain - * \param buf buffer holding the certificate data - * \param buflen size of the buffer - * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code - */ -int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ); - -/** \ingroup x509_module */ -/** - * \brief Load one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. - * - * \param chain points to the start of the chain - * \param path filename to read the certificates from - * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code - */ -int x509parse_crtfile( x509_cert *chain, const char *path ); - -/** \ingroup x509_module */ -/** - * \brief Parse one or more CRLs and add them - * to the chained list - * - * \param chain points to the start of the chain - * \param buf buffer holding the CRL data - * \param buflen size of the buffer - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ); - -/** \ingroup x509_module */ -/** - * \brief Load one or more CRLs and add them - * to the chained list - * - * \param chain points to the start of the chain - * \param path filename to read the CRLs from - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int x509parse_crlfile( x509_crl *chain, const char *path ); - -/** \ingroup x509_module */ -/** - * \brief Parse a private RSA key - * - * \param rsa RSA context to be initialized - * \param key input buffer - * \param keylen size of the buffer - * \param pwd password for decryption (optional) - * \param pwdlen size of the password - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int x509parse_key( rsa_context *rsa, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ); - -/** \ingroup x509_module */ -/** - * \brief Load and parse a private RSA key - * - * \param rsa RSA context to be initialized - * \param path filename to read the private key from - * \param password password to decrypt the file (can be NULL) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int x509parse_keyfile( rsa_context *rsa, const char *path, - const char *password ); - -/** \ingroup x509_module */ -/** - * \brief Parse a public RSA key - * - * \param rsa RSA context to be initialized - * \param key input buffer - * \param keylen size of the buffer - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int x509parse_public_key( rsa_context *rsa, - const unsigned char *key, size_t keylen ); - -/** \ingroup x509_module */ -/** - * \brief Load and parse a public RSA key - * - * \param rsa RSA context to be initialized - * \param path filename to read the private key from - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int x509parse_public_keyfile( rsa_context *rsa, const char *path ); - -/** \ingroup x509_module */ -/** - * \brief Parse DHM parameters - * - * \param dhm DHM context to be initialized - * \param dhmin input buffer - * \param dhminlen size of the buffer - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen ); - -/** \ingroup x509_module */ -/** - * \brief Load and parse DHM parameters - * - * \param dhm DHM context to be initialized - * \param path filename to read the DHM Parameters from - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int x509parse_dhmfile( dhm_context *dhm, const char *path ); - -/** \} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */ - -/** - * \brief Store the certificate DN in printable form into buf; - * no more than size characters will be written. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param dn The X509 name to represent - * - * \return The amount of data written to the buffer, or -1 in - * case of an error. - */ -int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn ); - -/** - * \brief Store the certificate serial in printable form into buf; - * no more than size characters will be written. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param serial The X509 serial to represent - * - * \return The amount of data written to the buffer, or -1 in - * case of an error. - */ -int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial ); - -/** - * \brief Returns an informational string about the - * certificate. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param crt The X509 certificate to represent - * - * \return The amount of data written to the buffer, or -1 in - * case of an error. - */ -int x509parse_cert_info( char *buf, size_t size, const char *prefix, - const x509_cert *crt ); - -/** - * \brief Returns an informational string about the - * CRL. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param crl The X509 CRL to represent - * - * \return The amount of data written to the buffer, or -1 in - * case of an error. - */ -int x509parse_crl_info( char *buf, size_t size, const char *prefix, - const x509_crl *crl ); - -/** - * \brief Give an known OID, return its descriptive string. - * - * \param oid buffer containing the oid - * - * \return Return a string if the OID is known, - * or NULL otherwise. - */ -const char *x509_oid_get_description( x509_buf *oid ); - -/* - * \brief Give an OID, return a string version of its OID number. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param oid Buffer containing the OID - * - * \return The amount of data written to the buffer, or -1 in - * case of an error. - */ -int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid ); - -/** - * \brief Check a given x509_time against the system time and check - * if it is valid. - * - * \param time x509_time to check - * - * \return Return 0 if the x509_time is still valid, - * or 1 otherwise. - */ -int x509parse_time_expired( const x509_time *time ); - -/** - * \name Functions to verify a certificate - * \{ - */ -/** \ingroup x509_module */ -/** - * \brief Verify the certificate signature - * - * \param crt a certificate to be verified - * \param trust_ca the trusted CA chain - * \param ca_crl the CRL chain for trusted CA's - * \param cn expected Common Name (can be set to - * NULL if the CN must not be verified) - * \param flags result of the verification - * \param f_vrfy verification function - * \param p_vrfy verification parameter - * - * \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED, - * in which case *flags will have one or more of - * the following values set: - * BADCERT_EXPIRED -- - * BADCERT_REVOKED -- - * BADCERT_CN_MISMATCH -- - * BADCERT_NOT_TRUSTED - * - * \note TODO: add two arguments, depth and crl - */ -int x509parse_verify( x509_cert *crt, - x509_cert *trust_ca, - x509_crl *ca_crl, - const char *cn, int *flags, - int (*f_vrfy)(void *, x509_cert *, int, int), - void *p_vrfy ); - -/** - * \brief Verify the certificate signature - * - * \param crt a certificate to be verified - * \param crl the CRL to verify against - * - * \return 1 if the certificate is revoked, 0 otherwise - * - */ -int x509parse_revoked( const x509_cert *crt, const x509_crl *crl ); - -/** \} name Functions to verify a certificate */ - - - -/** - * \name Functions to clear a certificate, CRL or private RSA key - * \{ - */ -/** \ingroup x509_module */ -/** - * \brief Unallocate all certificate data - * - * \param crt Certificate chain to free - */ -void x509_free( x509_cert *crt ); - -/** \ingroup x509_module */ -/** - * \brief Unallocate all CRL data - * - * \param crl CRL chain to free - */ -void x509_crl_free( x509_crl *crl ); - -/** \} name Functions to clear a certificate, CRL or private RSA key */ - - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int x509_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* x509.h */ diff --git a/polarssl/src/include/polarssl/x509write.h b/polarssl/src/include/polarssl/x509write.h deleted file mode 100644 index 8ce3d86..0000000 --- a/polarssl/src/include/polarssl/x509write.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * \file x509write.h - * - * \brief X509 buffer writing functionality - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_X509_WRITE_H -#define POLARSSL_X509_WRITE_H - -#include "rsa.h" - -typedef struct _x509_req_name -{ - char oid[128]; - char name[128]; - - struct _x509_req_name *next; -} -x509_req_name; - -int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ); -int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa ); -int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, - x509_req_name *req_name, int hash_id ); - -#endif /* POLARSSL_X509_WRITE_H */ diff --git a/polarssl/src/include/polarssl/xtea.h b/polarssl/src/include/polarssl/xtea.h deleted file mode 100644 index e2adb87..0000000 --- a/polarssl/src/include/polarssl/xtea.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file xtea.h - * - * \brief XTEA block cipher (32-bit) - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_XTEA_H -#define POLARSSL_XTEA_H - -#include - -#ifdef _MSC_VER -#include -typedef UINT32 uint32_t; -#else -#include -#endif - -#define XTEA_ENCRYPT 1 -#define XTEA_DECRYPT 0 - -#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ - -/** - * \brief XTEA context structure - */ -typedef struct -{ - uint32_t k[4]; /*!< key */ -} -xtea_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief XTEA key schedule - * - * \param ctx XTEA context to be initialized - * \param key the secret key - */ -void xtea_setup( xtea_context *ctx, unsigned char key[16] ); - -/** - * \brief XTEA cipher function - * - * \param ctx XTEA context - * \param mode XTEA_ENCRYPT or XTEA_DECRYPT - * \param input 8-byte input block - * \param output 8-byte output block - * - * \return 0 if successful - */ -int xtea_crypt_ecb( xtea_context *ctx, - int mode, - unsigned char input[8], - unsigned char output[8] ); - -/** - * \brief XTEA CBC cipher function - * - * \param ctx XTEA context - * \param mode XTEA_ENCRYPT or XTEA_DECRYPT - * \param length the length of input, multiple of 8 - * \param iv initialization vector for CBC mode - * \param input input block - * \param output output block - * - * \return 0 if successful, - * POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 - */ -int xtea_crypt_cbc( xtea_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - unsigned char *input, - unsigned char *output); - -/* - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int xtea_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* xtea.h */ diff --git a/polarssl/src/library/aes.c b/polarssl/src/library/aes.c deleted file mode 100644 index 2f52202..0000000 --- a/polarssl/src/library/aes.c +++ /dev/null @@ -1,1346 +0,0 @@ -/* - * FIPS-197 compliant AES implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. - * - * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf - * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_AES_C) - -#include "polarssl/aes.h" -#include "polarssl/padlock.h" - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -#if defined(POLARSSL_PADLOCK_C) -static int aes_padlock_ace = -1; -#endif - -#if defined(POLARSSL_AES_ROM_TABLES) -/* - * Forward S-box - */ -static const unsigned char FSb[256] = -{ - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, - 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, - 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, - 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, - 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, - 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, - 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, - 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, - 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 -}; - -/* - * Forward tables - */ -#define FT \ -\ - V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ - V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ - V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ - V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ - V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ - V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ - V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ - V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ - V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ - V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ - V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ - V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ - V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ - V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ - V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ - V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ - V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ - V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ - V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ - V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ - V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ - V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ - V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ - V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ - V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ - V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ - V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ - V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ - V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ - V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ - V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ - V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ - V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ - V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ - V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ - V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ - V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ - V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ - V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ - V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ - V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ - V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ - V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ - V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ - V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ - V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ - V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ - V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ - V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ - V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ - V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ - V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ - V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ - V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ - V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ - V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ - V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ - V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ - V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ - V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ - V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ - V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ - V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ - V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) - -#define V(a,b,c,d) 0x##a##b##c##d -static const unsigned long FT0[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const unsigned long FT1[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const unsigned long FT2[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const unsigned long FT3[256] = { FT }; -#undef V - -#undef FT - -/* - * Reverse S-box - */ -static const unsigned char RSb[256] = -{ - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, - 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, - 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, - 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, - 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, - 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, - 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, - 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, - 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, - 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, - 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, - 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D -}; - -/* - * Reverse tables - */ -#define RT \ -\ - V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ - V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ - V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ - V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ - V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ - V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ - V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ - V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ - V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ - V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ - V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ - V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ - V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ - V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ - V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ - V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ - V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ - V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ - V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ - V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ - V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ - V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ - V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ - V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ - V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ - V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ - V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ - V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ - V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ - V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ - V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ - V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ - V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ - V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ - V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ - V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ - V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ - V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ - V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ - V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ - V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ - V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ - V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ - V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ - V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ - V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ - V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ - V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ - V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ - V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ - V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ - V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ - V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ - V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ - V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ - V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ - V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ - V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ - V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ - V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ - V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ - V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ - V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ - V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) - -#define V(a,b,c,d) 0x##a##b##c##d -static const unsigned long RT0[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const unsigned long RT1[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const unsigned long RT2[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const unsigned long RT3[256] = { RT }; -#undef V - -#undef RT - -/* - * Round constants - */ -static const unsigned long RCON[10] = -{ - 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x0000001B, 0x00000036 -}; - -#else - -/* - * Forward S-box & tables - */ -static unsigned char FSb[256]; -static unsigned long FT0[256]; -static unsigned long FT1[256]; -static unsigned long FT2[256]; -static unsigned long FT3[256]; - -/* - * Reverse S-box & tables - */ -static unsigned char RSb[256]; -static unsigned long RT0[256]; -static unsigned long RT1[256]; -static unsigned long RT2[256]; -static unsigned long RT3[256]; - -/* - * Round constants - */ -static unsigned long RCON[10]; - -/* - * Tables generation code - */ -#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) -#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) -#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) - -static int aes_init_done = 0; - -static void aes_gen_tables( void ) -{ - int i, x, y, z; - int pow[256]; - int log[256]; - - /* - * compute pow and log tables over GF(2^8) - */ - for( i = 0, x = 1; i < 256; i++ ) - { - pow[i] = x; - log[x] = i; - x = ( x ^ XTIME( x ) ) & 0xFF; - } - - /* - * calculate the round constants - */ - for( i = 0, x = 1; i < 10; i++ ) - { - RCON[i] = (unsigned long) x; - x = XTIME( x ) & 0xFF; - } - - /* - * generate the forward and reverse S-boxes - */ - FSb[0x00] = 0x63; - RSb[0x63] = 0x00; - - for( i = 1; i < 256; i++ ) - { - x = pow[255 - log[i]]; - - y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF; - x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; - x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; - x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; - x ^= y ^ 0x63; - - FSb[i] = (unsigned char) x; - RSb[x] = (unsigned char) i; - } - - /* - * generate the forward and reverse tables - */ - for( i = 0; i < 256; i++ ) - { - x = FSb[i]; - y = XTIME( x ) & 0xFF; - z = ( y ^ x ) & 0xFF; - - FT0[i] = ( (unsigned long) y ) ^ - ( (unsigned long) x << 8 ) ^ - ( (unsigned long) x << 16 ) ^ - ( (unsigned long) z << 24 ); - - FT1[i] = ROTL8( FT0[i] ); - FT2[i] = ROTL8( FT1[i] ); - FT3[i] = ROTL8( FT2[i] ); - - x = RSb[i]; - - RT0[i] = ( (unsigned long) MUL( 0x0E, x ) ) ^ - ( (unsigned long) MUL( 0x09, x ) << 8 ) ^ - ( (unsigned long) MUL( 0x0D, x ) << 16 ) ^ - ( (unsigned long) MUL( 0x0B, x ) << 24 ); - - RT1[i] = ROTL8( RT0[i] ); - RT2[i] = ROTL8( RT1[i] ); - RT3[i] = ROTL8( RT2[i] ); - } -} - -#endif - -/* - * AES key schedule (encryption) - */ -int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ) -{ - unsigned int i; - unsigned long *RK; - -#if !defined(POLARSSL_AES_ROM_TABLES) - if( aes_init_done == 0 ) - { - aes_gen_tables(); - aes_init_done = 1; - - } -#endif - - switch( keysize ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); - } - -#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) - if( aes_padlock_ace == -1 ) - aes_padlock_ace = padlock_supports( PADLOCK_ACE ); - - if( aes_padlock_ace ) - ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); - else -#endif - ctx->rk = RK = ctx->buf; - - for( i = 0; i < (keysize >> 5); i++ ) - { - GET_ULONG_LE( RK[i], key, i << 2 ); - } - - switch( ctx->nr ) - { - case 10: - - for( i = 0; i < 10; i++, RK += 4 ) - { - RK[4] = RK[0] ^ RCON[i] ^ - ( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 ); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; - } - break; - - case 12: - - for( i = 0; i < 8; i++, RK += 6 ) - { - RK[6] = RK[0] ^ RCON[i] ^ - ( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 ); - - RK[7] = RK[1] ^ RK[6]; - RK[8] = RK[2] ^ RK[7]; - RK[9] = RK[3] ^ RK[8]; - RK[10] = RK[4] ^ RK[9]; - RK[11] = RK[5] ^ RK[10]; - } - break; - - case 14: - - for( i = 0; i < 7; i++, RK += 8 ) - { - RK[8] = RK[0] ^ RCON[i] ^ - ( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 ); - - RK[9] = RK[1] ^ RK[8]; - RK[10] = RK[2] ^ RK[9]; - RK[11] = RK[3] ^ RK[10]; - - RK[12] = RK[4] ^ - ( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); - - RK[13] = RK[5] ^ RK[12]; - RK[14] = RK[6] ^ RK[13]; - RK[15] = RK[7] ^ RK[14]; - } - break; - - default: - - break; - } - - return( 0 ); -} - -/* - * AES key schedule (decryption) - */ -int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ) -{ - int i, j; - aes_context cty; - unsigned long *RK; - unsigned long *SK; - int ret; - - switch( keysize ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); - } - -#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) - if( aes_padlock_ace == -1 ) - aes_padlock_ace = padlock_supports( PADLOCK_ACE ); - - if( aes_padlock_ace ) - ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); - else -#endif - ctx->rk = RK = ctx->buf; - - ret = aes_setkey_enc( &cty, key, keysize ); - if( ret != 0 ) - return( ret ); - - SK = cty.rk + cty.nr * 4; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) - { - for( j = 0; j < 4; j++, SK++ ) - { - *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ - RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ - RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ - RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; - } - } - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - memset( &cty, 0, sizeof( aes_context ) ); - - return( 0 ); -} - -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ - FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ - FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y0 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ - FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ - FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y2 >> 24 ) & 0xFF ]; \ -} - -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ - RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ - RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y2 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ - RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ - RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y0 >> 24 ) & 0xFF ]; \ -} - -/* - * AES-ECB block encryption/decryption - */ -int aes_crypt_ecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int i; - unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - -#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) - if( aes_padlock_ace ) - { - if( padlock_xcryptecb( ctx, mode, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - RK = ctx->rk; - - GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++; - GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++; - GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++; - GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++; - - if( mode == AES_DECRYPT ) - { - for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) - { - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^ - ( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^ - ( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^ - ( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^ - ( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - } - else /* AES_ENCRYPT */ - { - for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) - { - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - } - - PUT_ULONG_LE( X0, output, 0 ); - PUT_ULONG_LE( X1, output, 4 ); - PUT_ULONG_LE( X2, output, 8 ); - PUT_ULONG_LE( X3, output, 12 ); - - return( 0 ); -} - -/* - * AES-CBC buffer encryption/decryption - */ -int aes_crypt_cbc( aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[16]; - - if( length % 16 ) - return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); - -#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) - if( aes_padlock_ace ) - { - if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - if( mode == AES_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 16 ); - aes_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - aes_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - - return( 0 ); -} - -#if defined(POLARSSL_CIPHER_MODE_CFB) -/* - * AES-CFB128 buffer encryption/decryption - */ -int aes_crypt_cfb128( aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == AES_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = (n + 1) & 0x0F; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = (n + 1) & 0x0F; - } - } - - *iv_off = n; - - return( 0 ); -} -#endif /*POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -/* - * AES-CTR buffer encryption/decryption - */ -int aes_crypt_ctr( aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block ); - - for( i = 16; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = (n + 1) & 0x0F; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -#if defined(POLARSSL_SELF_TEST) - -#include - -/* - * AES test vectors from: - * - * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip - */ -static const unsigned char aes_test_ecb_dec[3][16] = -{ - { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, - 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, - { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, - 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, - { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, - 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } -}; - -static const unsigned char aes_test_ecb_enc[3][16] = -{ - { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, - 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, - { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, - 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, - { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, - 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } -}; - -static const unsigned char aes_test_cbc_dec[3][16] = -{ - { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, - 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, - { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, - 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, - { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, - 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } -}; - -static const unsigned char aes_test_cbc_enc[3][16] = -{ - { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, - 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, - { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, - 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, - { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, - 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } -}; - -#if defined(POLARSSL_CIPHER_MODE_CFB) -/* - * AES-CFB128 test vectors from: - * - * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - */ -static const unsigned char aes_test_cfb128_key[3][32] = -{ - { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, - 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, - { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, - 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, - 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } -}; - -static const unsigned char aes_test_cfb128_iv[16] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F -}; - -static const unsigned char aes_test_cfb128_pt[64] = -{ - 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, - 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, - 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, - 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, - 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, - 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 -}; - -static const unsigned char aes_test_cfb128_ct[3][64] = -{ - { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, - 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, - 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, - 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, - 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, - 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, - 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, - 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, - { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, - 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, - 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, - 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, - 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, - 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, - 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, - 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, - { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, - 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, - 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, - 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, - 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, - 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, - 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, - 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } -}; -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -/* - * AES-CTR test vectors from: - * - * http://www.faqs.org/rfcs/rfc3686.html - */ - -static const unsigned char aes_test_ctr_key[3][16] = -{ - { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, - 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, - { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, - 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, - { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, - 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } -}; - -static const unsigned char aes_test_ctr_nonce_counter[3][16] = -{ - { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, - 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, - 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } -}; - -static const unsigned char aes_test_ctr_pt[3][48] = -{ - { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, - 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23 } -}; - -static const unsigned char aes_test_ctr_ct[3][48] = -{ - { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, - 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, - { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, - 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, - 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, - 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, - { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, - 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, - 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, - 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, - 0x25, 0xB2, 0x07, 0x2F } -}; - -static const int aes_test_ctr_len[3] = - { 16, 32, 36 }; -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -/* - * Checkup routine - */ -int aes_self_test( int verbose ) -{ - int i, j, u, v; - unsigned char key[32]; - unsigned char buf[64]; - unsigned char prv[16]; - unsigned char iv[16]; -#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB) - size_t offset; -#endif -#if defined(POLARSSL_CIPHER_MODE_CTR) - int len; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; -#endif - aes_context ctx; - - memset( key, 0, 32 ); - - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " AES-ECB-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memset( buf, 0, 16 ); - - if( v == AES_DECRYPT ) - { - aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - else - { - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " AES-CBC-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memset( iv , 0, 16 ); - memset( prv, 0, 16 ); - memset( buf, 0, 16 ); - - if( v == AES_DECRYPT ) - { - aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - else - { - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[16]; - - aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - memcpy( tmp, prv, 16 ); - memcpy( prv, buf, 16 ); - memcpy( buf, tmp, 16 ); - } - - if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - -#if defined(POLARSSL_CIPHER_MODE_CFB) - /* - * CFB128 mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, aes_test_cfb128_iv, 16 ); - memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); - - offset = 0; - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - if( v == AES_DECRYPT ) - { - memcpy( buf, aes_test_cfb128_ct[u], 64 ); - aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - else - { - memcpy( buf, aes_test_cfb128_pt, 64 ); - aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) - /* - * CTR mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " AES-CTR-128 (%s): ", - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); - memcpy( key, aes_test_ctr_key[u], 16 ); - - offset = 0; - aes_setkey_enc( &ctx, key, 128 ); - - if( v == AES_DECRYPT ) - { - len = aes_test_ctr_len[u]; - memcpy( buf, aes_test_ctr_ct[u], len ); - - aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf ); - - if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - else - { - len = aes_test_ctr_len[u]; - memcpy( buf, aes_test_ctr_pt[u], len ); - - aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf ); - - if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); -#endif /* POLARSSL_CIPHER_MODE_CTR */ - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/arc4.c b/polarssl/src/library/arc4.c deleted file mode 100644 index 07665ad..0000000 --- a/polarssl/src/library/arc4.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * An implementation of the ARCFOUR algorithm - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The ARCFOUR algorithm was publicly disclosed on 94/09. - * - * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_ARC4_C) - -#include "polarssl/arc4.h" - -/* - * ARC4 key schedule - */ -void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen ) -{ - int i, j, a; - unsigned int k; - unsigned char *m; - - ctx->x = 0; - ctx->y = 0; - m = ctx->m; - - for( i = 0; i < 256; i++ ) - m[i] = (unsigned char) i; - - j = k = 0; - - for( i = 0; i < 256; i++, k++ ) - { - if( k >= keylen ) k = 0; - - a = m[i]; - j = ( j + a + key[k] ) & 0xFF; - m[i] = m[j]; - m[j] = (unsigned char) a; - } -} - -/* - * ARC4 cipher function - */ -int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input, - unsigned char *output ) -{ - int x, y, a, b; - size_t i; - unsigned char *m; - - x = ctx->x; - y = ctx->y; - m = ctx->m; - - for( i = 0; i < length; i++ ) - { - x = ( x + 1 ) & 0xFF; a = m[x]; - y = ( y + a ) & 0xFF; b = m[y]; - - m[x] = (unsigned char) b; - m[y] = (unsigned char) a; - - output[i] = (unsigned char) - ( input[i] ^ m[(unsigned char)( a + b )] ); - } - - ctx->x = x; - ctx->y = y; - - return( 0 ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include -#include - -/* - * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: - * - * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 - */ -static const unsigned char arc4_test_key[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char arc4_test_pt[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char arc4_test_ct[3][8] = -{ - { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, - { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, - { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } -}; - -/* - * Checkup routine - */ -int arc4_self_test( int verbose ) -{ - int i; - unsigned char ibuf[8]; - unsigned char obuf[8]; - arc4_context ctx; - - for( i = 0; i < 3; i++ ) - { - if( verbose != 0 ) - printf( " ARC4 test #%d: ", i + 1 ); - - memcpy( ibuf, arc4_test_pt[i], 8 ); - - arc4_setup( &ctx, (unsigned char *) arc4_test_key[i], 8 ); - arc4_crypt( &ctx, 8, ibuf, obuf ); - - if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/asn1parse.c b/polarssl/src/library/asn1parse.c deleted file mode 100644 index 2584774..0000000 --- a/polarssl/src/library/asn1parse.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Generic ASN.1 parsing - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_ASN1_PARSE_C) - -#include "polarssl/asn1.h" - -#if defined(POLARSSL_BIGNUM_C) -#include "polarssl/bignum.h" -#endif - -#include -#include -#include - -/* - * ASN.1 DER decoding routines - */ -int asn1_get_len( unsigned char **p, - const unsigned char *end, - size_t *len ) -{ - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - if( ( **p & 0x80 ) == 0 ) - *len = *(*p)++; - else - { - switch( **p & 0x7F ) - { - case 1: - if( ( end - *p ) < 2 ) - return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - *len = (*p)[1]; - (*p) += 2; - break; - - case 2: - if( ( end - *p ) < 3 ) - return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (*p)[1] << 8 ) | (*p)[2]; - (*p) += 3; - break; - - case 3: - if( ( end - *p ) < 4 ) - return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3]; - (*p) += 4; - break; - - case 4: - if( ( end - *p ) < 5 ) - return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4]; - (*p) += 5; - break; - - default: - return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); - } - } - - if( *len > (size_t) ( end - *p ) ) - return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - return( 0 ); -} - -int asn1_get_tag( unsigned char **p, - const unsigned char *end, - size_t *len, int tag ) -{ - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - if( **p != tag ) - return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); - - (*p)++; - - return( asn1_get_len( p, end, len ) ); -} - -int asn1_get_bool( unsigned char **p, - const unsigned char *end, - int *val ) -{ - int ret; - size_t len; - - if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 ) - return( ret ); - - if( len != 1 ) - return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); - - *val = ( **p != 0 ) ? 1 : 0; - (*p)++; - - return( 0 ); -} - -int asn1_get_int( unsigned char **p, - const unsigned char *end, - int *val ) -{ - int ret; - size_t len; - - if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) - return( ret ); - - if( len > sizeof( int ) || ( **p & 0x80 ) != 0 ) - return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); - - *val = 0; - - while( len-- > 0 ) - { - *val = ( *val << 8 ) | **p; - (*p)++; - } - - return( 0 ); -} - -#if defined(POLARSSL_BIGNUM_C) -int asn1_get_mpi( unsigned char **p, - const unsigned char *end, - mpi *X ) -{ - int ret; - size_t len; - - if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) - return( ret ); - - ret = mpi_read_binary( X, *p, len ); - - *p += len; - - return( ret ); -} -#endif /* POLARSSL_BIGNUM_C */ - -int asn1_get_bitstring( unsigned char **p, const unsigned char *end, - asn1_bitstring *bs) -{ - int ret; - - /* Certificate type is a single byte bitstring */ - if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 ) - return( ret ); - - /* Check length, subtract one for actual bit string length */ - if ( bs->len < 1 ) - return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); - bs->len -= 1; - - /* Get number of unused bits, ensure unused bits <= 7 */ - bs->unused_bits = **p; - if( bs->unused_bits > 7 ) - return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); - (*p)++; - - /* Get actual bitstring */ - bs->p = *p; - *p += bs->len; - - if( *p != end ) - return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return 0; -} - - -/* - * Parses and splits an ASN.1 "SEQUENCE OF " - */ -int asn1_get_sequence_of( unsigned char **p, - const unsigned char *end, - asn1_sequence *cur, - int tag) -{ - int ret; - size_t len; - asn1_buf *buf; - - /* Get main sequence tag */ - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - if( *p + len != end ) - return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - buf = &(cur->buf); - buf->tag = **p; - - if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) - return( ret ); - - buf->p = *p; - *p += buf->len; - - /* Allocate and assign next pointer */ - if (*p < end) - { - cur->next = (asn1_sequence *) malloc( - sizeof( asn1_sequence ) ); - - if( cur->next == NULL ) - return( POLARSSL_ERR_ASN1_MALLOC_FAILED ); - - cur = cur->next; - } - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if( *p != end ) - return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -#endif diff --git a/polarssl/src/library/asn1write.c b/polarssl/src/library/asn1write.c deleted file mode 100644 index e50c17c..0000000 --- a/polarssl/src/library/asn1write.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * ASN.1 buffer writing functionality - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_ASN1_WRITE_C) - -#include "polarssl/asn1write.h" - -int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) -{ - if( len < 0x80 ) - { - if( *p - start < 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = len; - return( 1 ); - } - - if( len <= 0xFF ) - { - if( *p - start < 2 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = len; - *--(*p) = 0x81; - return( 2 ); - } - - if( *p - start < 3 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - // We assume we never have lengths larger than 65535 bytes - // - *--(*p) = len % 256; - *--(*p) = ( len / 256 ) % 256; - *--(*p) = 0x82; - - return( 3 ); -} - -int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) -{ - if( *p - start < 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = tag; - - return( 1 ); -} - -int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ) -{ - int ret; - size_t len = 0; - - // Write the MPI - // - len = mpi_size( X ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - mpi_write_binary( X, *p, len ); - - // DER format assumes 2s complement for numbers, so the leftmost bit - // should be 0 for positive numbers and 1 for negative numbers. - // - if ( X->s ==1 && **p & 0x80 ) - { - if( *p - start < 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0x00; - len += 1; - } - - ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) ); - - return( len ); -} - -int asn1_write_null( unsigned char **p, unsigned char *start ) -{ - int ret; - size_t len = 0; - - // Write NULL - // - ASN1_CHK_ADD( len, asn1_write_len( p, start, 0) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_NULL ) ); - - return( len ); -} - -int asn1_write_oid( unsigned char **p, unsigned char *start, char *oid ) -{ - int ret; - size_t len = 0; - - // Write OID - // - len = strlen( oid ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, oid, len ); - - ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) ); - ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) ); - - return( len ); -} - -int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - char *algorithm_oid ) -{ - int ret; - size_t null_len = 0; - size_t oid_len = 0; - size_t len = 0; - - // Write NULL - // - ASN1_CHK_ADD( null_len, asn1_write_null( p, start ) ); - - // Write OID - // - ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, algorithm_oid ) ); - - len = oid_len + null_len; - ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + null_len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - return( len ); -} - -int asn1_write_int( unsigned char **p, unsigned char *start, int val ) -{ - int ret; - size_t len = 0; - - // TODO negative values and values larger than 128 - // DER format assumes 2s complement for numbers, so the leftmost bit - // should be 0 for positive numbers and 1 for negative numbers. - // - if( *p - start < 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - len += 1; - *--(*p) = val; - - if ( val > 0 && **p & 0x80 ) - { - if( *p - start < 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0x00; - len += 1; - } - - ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) ); - - return( len ); -} - -int asn1_write_printable_string( unsigned char **p, unsigned char *start, - char *text ) -{ - int ret; - size_t len = 0; - - // Write string - // - len = strlen( text ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, text, len ); - - ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) ); - - return( len ); -} - -int asn1_write_ia5_string( unsigned char **p, unsigned char *start, - char *text ) -{ - int ret; - size_t len = 0; - - // Write string - // - len = strlen( text ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, text, len ); - - ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) ); - - return( len ); -} - - -#endif diff --git a/polarssl/src/library/base64.c b/polarssl/src/library/base64.c deleted file mode 100644 index 8601c94..0000000 --- a/polarssl/src/library/base64.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * RFC 1521 base64 encoding/decoding - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_BASE64_C) - -#include "polarssl/base64.h" - -static const unsigned char base64_enc_map[64] = -{ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '+', '/' -}; - -static const unsigned char base64_dec_map[128] = -{ - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, - 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 127, 127, 127, 127, 127 -}; - -/* - * Encode a buffer into base64 format - */ -int base64_encode( unsigned char *dst, size_t *dlen, - const unsigned char *src, size_t slen ) -{ - size_t i, n; - int C1, C2, C3; - unsigned char *p; - - if( slen == 0 ) - return( 0 ); - - n = (slen << 3) / 6; - - switch( (slen << 3) - (n * 6) ) - { - case 2: n += 3; break; - case 4: n += 2; break; - default: break; - } - - if( *dlen < n + 1 ) - { - *dlen = n + 1; - return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - n = (slen / 3) * 3; - - for( i = 0, p = dst; i < n; i += 3 ) - { - C1 = *src++; - C2 = *src++; - C3 = *src++; - - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; - *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; - *p++ = base64_enc_map[C3 & 0x3F]; - } - - if( i < slen ) - { - C1 = *src++; - C2 = ((i + 1) < slen) ? *src++ : 0; - - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; - - if( (i + 1) < slen ) - *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; - else *p++ = '='; - - *p++ = '='; - } - - *dlen = p - dst; - *p = 0; - - return( 0 ); -} - -/* - * Decode a base64-formatted buffer - */ -int base64_decode( unsigned char *dst, size_t *dlen, - const unsigned char *src, size_t slen ) -{ - size_t i, j, n; - unsigned long x; - unsigned char *p; - - for( i = j = n = 0; i < slen; i++ ) - { - if( ( slen - i ) >= 2 && - src[i] == '\r' && src[i + 1] == '\n' ) - continue; - - if( src[i] == '\n' ) - continue; - - if( src[i] == '=' && ++j > 2 ) - return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); - - if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) - return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); - - if( base64_dec_map[src[i]] < 64 && j != 0 ) - return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); - - n++; - } - - if( n == 0 ) - return( 0 ); - - n = ((n * 6) + 7) >> 3; - - if( *dlen < n ) - { - *dlen = n; - return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) - { - if( *src == '\r' || *src == '\n' ) - continue; - - j -= ( base64_dec_map[*src] == 64 ); - x = (x << 6) | ( base64_dec_map[*src] & 0x3F ); - - if( ++n == 4 ) - { - n = 0; - if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); - if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); - if( j > 2 ) *p++ = (unsigned char)( x ); - } - } - - *dlen = p - dst; - - return( 0 ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include -#include - -static const unsigned char base64_test_dec[64] = -{ - 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, - 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, - 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, - 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, - 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, - 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, - 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, - 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 -}; - -static const unsigned char base64_test_enc[] = - "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" - "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; - -/* - * Checkup routine - */ -int base64_self_test( int verbose ) -{ - size_t len; - unsigned char *src, buffer[128]; - - if( verbose != 0 ) - printf( " Base64 encoding test: " ); - - len = sizeof( buffer ); - src = (unsigned char *) base64_test_dec; - - if( base64_encode( buffer, &len, src, 64 ) != 0 || - memcmp( base64_test_enc, buffer, 88 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n Base64 decoding test: " ); - - len = sizeof( buffer ); - src = (unsigned char *) base64_test_enc; - - if( base64_decode( buffer, &len, src, 88 ) != 0 || - memcmp( base64_test_dec, buffer, 64 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/bignum.c b/polarssl/src/library/bignum.c deleted file mode 100644 index 0cb9505..0000000 --- a/polarssl/src/library/bignum.c +++ /dev/null @@ -1,2111 +0,0 @@ -/* - * Multi-precision integer library - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * This MPI implementation is based on: - * - * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf - * http://www.stillhq.com/extracted/gnupg-api/mpi/ - * http://math.libtomcrypt.com/files/tommath.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_BIGNUM_C) - -#include "polarssl/bignum.h" -#include "polarssl/bn_mul.h" - -#include - -#define ciL (sizeof(t_uint)) /* chars in limb */ -#define biL (ciL << 3) /* bits in limb */ -#define biH (ciL << 2) /* half limb size */ - -/* - * Convert between bits/chars and number of limbs - */ -#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) -#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) - -/* - * Initialize one MPI - */ -void mpi_init( mpi *X ) -{ - if( X == NULL ) - return; - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Unallocate one MPI - */ -void mpi_free( mpi *X ) -{ - if( X == NULL ) - return; - - if( X->p != NULL ) - { - memset( X->p, 0, X->n * ciL ); - free( X->p ); - } - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Enlarge to the specified number of limbs - */ -int mpi_grow( mpi *X, size_t nblimbs ) -{ - t_uint *p; - - if( nblimbs > POLARSSL_MPI_MAX_LIMBS ) - return( POLARSSL_ERR_MPI_MALLOC_FAILED ); - - if( X->n < nblimbs ) - { - if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL ) - return( POLARSSL_ERR_MPI_MALLOC_FAILED ); - - memset( p, 0, nblimbs * ciL ); - - if( X->p != NULL ) - { - memcpy( p, X->p, X->n * ciL ); - memset( X->p, 0, X->n * ciL ); - free( X->p ); - } - - X->n = nblimbs; - X->p = p; - } - - return( 0 ); -} - -/* - * Copy the contents of Y into X - */ -int mpi_copy( mpi *X, const mpi *Y ) -{ - int ret; - size_t i; - - if( X == Y ) - return( 0 ); - - for( i = Y->n - 1; i > 0; i-- ) - if( Y->p[i] != 0 ) - break; - i++; - - X->s = Y->s; - - MPI_CHK( mpi_grow( X, i ) ); - - memset( X->p, 0, X->n * ciL ); - memcpy( X->p, Y->p, i * ciL ); - -cleanup: - - return( ret ); -} - -/* - * Swap the contents of X and Y - */ -void mpi_swap( mpi *X, mpi *Y ) -{ - mpi T; - - memcpy( &T, X, sizeof( mpi ) ); - memcpy( X, Y, sizeof( mpi ) ); - memcpy( Y, &T, sizeof( mpi ) ); -} - -/* - * Set value from integer - */ -int mpi_lset( mpi *X, t_sint z ) -{ - int ret; - - MPI_CHK( mpi_grow( X, 1 ) ); - memset( X->p, 0, X->n * ciL ); - - X->p[0] = ( z < 0 ) ? -z : z; - X->s = ( z < 0 ) ? -1 : 1; - -cleanup: - - return( ret ); -} - -/* - * Get a specific bit - */ -int mpi_get_bit( mpi *X, size_t pos ) -{ - if( X->n * biL <= pos ) - return( 0 ); - - return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01; -} - -/* - * Set a bit to a specific value of 0 or 1 - */ -int mpi_set_bit( mpi *X, size_t pos, unsigned char val ) -{ - int ret = 0; - size_t off = pos / biL; - size_t idx = pos % biL; - - if( val != 0 && val != 1 ) - return POLARSSL_ERR_MPI_BAD_INPUT_DATA; - - if( X->n * biL <= pos ) - { - if( val == 0 ) - return ( 0 ); - - MPI_CHK( mpi_grow( X, off + 1 ) ); - } - - X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx ); - -cleanup: - - return( ret ); -} - -/* - * Return the number of least significant bits - */ -size_t mpi_lsb( const mpi *X ) -{ - size_t i, j, count = 0; - - for( i = 0; i < X->n; i++ ) - for( j = 0; j < biL; j++, count++ ) - if( ( ( X->p[i] >> j ) & 1 ) != 0 ) - return( count ); - - return( 0 ); -} - -/* - * Return the number of most significant bits - */ -size_t mpi_msb( const mpi *X ) -{ - size_t i, j; - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - - for( j = biL; j > 0; j-- ) - if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 ) - break; - - return( ( i * biL ) + j ); -} - -/* - * Return the total size in bytes - */ -size_t mpi_size( const mpi *X ) -{ - return( ( mpi_msb( X ) + 7 ) >> 3 ); -} - -/* - * Convert an ASCII character to digit value - */ -static int mpi_get_digit( t_uint *d, int radix, char c ) -{ - *d = 255; - - if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; - if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; - if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; - - if( *d >= (t_uint) radix ) - return( POLARSSL_ERR_MPI_INVALID_CHARACTER ); - - return( 0 ); -} - -/* - * Import from an ASCII string - */ -int mpi_read_string( mpi *X, int radix, const char *s ) -{ - int ret; - size_t i, j, slen, n; - t_uint d; - mpi T; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &T ); - - slen = strlen( s ); - - if( radix == 16 ) - { - n = BITS_TO_LIMBS( slen << 2 ); - - MPI_CHK( mpi_grow( X, n ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = slen, j = 0; i > 0; i--, j++ ) - { - if( i == 1 && s[i - 1] == '-' ) - { - X->s = -1; - break; - } - - MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); - X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 ); - } - } - else - { - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = 0; i < slen; i++ ) - { - if( i == 0 && s[i] == '-' ) - { - X->s = -1; - continue; - } - - MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); - MPI_CHK( mpi_mul_int( &T, X, radix ) ); - - if( X->s == 1 ) - { - MPI_CHK( mpi_add_int( X, &T, d ) ); - } - else - { - MPI_CHK( mpi_sub_int( X, &T, d ) ); - } - } - } - -cleanup: - - mpi_free( &T ); - - return( ret ); -} - -/* - * Helper to write the digits high-order first - */ -static int mpi_write_hlp( mpi *X, int radix, char **p ) -{ - int ret; - t_uint r; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - MPI_CHK( mpi_mod_int( &r, X, radix ) ); - MPI_CHK( mpi_div_int( X, NULL, X, radix ) ); - - if( mpi_cmp_int( X, 0 ) != 0 ) - MPI_CHK( mpi_write_hlp( X, radix, p ) ); - - if( r < 10 ) - *(*p)++ = (char)( r + 0x30 ); - else - *(*p)++ = (char)( r + 0x37 ); - -cleanup: - - return( ret ); -} - -/* - * Export into an ASCII string - */ -int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ) -{ - int ret = 0; - size_t n; - char *p; - mpi T; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - n = mpi_msb( X ); - if( radix >= 4 ) n >>= 1; - if( radix >= 16 ) n >>= 1; - n += 3; - - if( *slen < n ) - { - *slen = n; - return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); - } - - p = s; - mpi_init( &T ); - - if( X->s == -1 ) - *p++ = '-'; - - if( radix == 16 ) - { - int c; - size_t i, j, k; - - for( i = X->n, k = 0; i > 0; i-- ) - { - for( j = ciL; j > 0; j-- ) - { - c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; - - if( c == 0 && k == 0 && ( i + j + 3 ) != 0 ) - continue; - - p += sprintf( p, "%02X", c ); - k = 1; - } - } - } - else - { - MPI_CHK( mpi_copy( &T, X ) ); - - if( T.s == -1 ) - T.s = 1; - - MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); - } - - *p++ = '\0'; - *slen = p - s; - -cleanup: - - mpi_free( &T ); - - return( ret ); -} - -#if defined(POLARSSL_FS_IO) -/* - * Read X from an opened file - */ -int mpi_read_file( mpi *X, int radix, FILE *fin ) -{ - t_uint d; - size_t slen; - char *p; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ POLARSSL_MPI_READ_BUFFER_SIZE ]; - - memset( s, 0, sizeof( s ) ); - if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) - return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); - - slen = strlen( s ); - if( slen == sizeof( s ) - 2 ) - return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); - - if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } - if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } - - p = s + slen; - while( --p >= s ) - if( mpi_get_digit( &d, radix, *p ) != 0 ) - break; - - return( mpi_read_string( X, radix, p + 1 ) ); -} - -/* - * Write X into an opened file (or stdout if fout == NULL) - */ -int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ) -{ - int ret; - size_t n, slen, plen; - /* - * Buffer should have space for minus sign, hexified MPI and '\0' - */ - char s[ 2 * POLARSSL_MPI_MAX_SIZE + 2 ]; - - n = sizeof( s ); - memset( s, 0, n ); - n -= 2; - - MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) ); - - if( p == NULL ) p = ""; - - plen = strlen( p ); - slen = strlen( s ); - s[slen++] = '\r'; - s[slen++] = '\n'; - - if( fout != NULL ) - { - if( fwrite( p, 1, plen, fout ) != plen || - fwrite( s, 1, slen, fout ) != slen ) - return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); - } - else - printf( "%s%s", p, s ); - -cleanup: - - return( ret ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * Import X from unsigned binary data, big endian - */ -int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t i, j, n; - - for( n = 0; n < buflen; n++ ) - if( buf[n] != 0 ) - break; - - MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = buflen, j = 0; i > n; i--, j++ ) - X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3); - -cleanup: - - return( ret ); -} - -/* - * Export X into unsigned binary data, big endian - */ -int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ) -{ - size_t i, j, n; - - n = mpi_size( X ); - - if( buflen < n ) - return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); - - memset( buf, 0, buflen ); - - for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) - buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); - - return( 0 ); -} - -/* - * Left-shift: X <<= count - */ -int mpi_shift_l( mpi *X, size_t count ) -{ - int ret; - size_t i, v0, t1; - t_uint r0 = 0, r1; - - v0 = count / (biL ); - t1 = count & (biL - 1); - - i = mpi_msb( X ) + count; - - if( X->n * biL < i ) - MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) ); - - ret = 0; - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = X->n; i > v0; i-- ) - X->p[i - 1] = X->p[i - v0 - 1]; - - for( ; i > 0; i-- ) - X->p[i - 1] = 0; - } - - /* - * shift by count % limb_size - */ - if( t1 > 0 ) - { - for( i = v0; i < X->n; i++ ) - { - r1 = X->p[i] >> (biL - t1); - X->p[i] <<= t1; - X->p[i] |= r0; - r0 = r1; - } - } - -cleanup: - - return( ret ); -} - -/* - * Right-shift: X >>= count - */ -int mpi_shift_r( mpi *X, size_t count ) -{ - size_t i, v0, v1; - t_uint r0 = 0, r1; - - v0 = count / biL; - v1 = count & (biL - 1); - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = 0; i < X->n - v0; i++ ) - X->p[i] = X->p[i + v0]; - - for( ; i < X->n; i++ ) - X->p[i] = 0; - } - - /* - * shift by count % limb_size - */ - if( v1 > 0 ) - { - for( i = X->n; i > 0; i-- ) - { - r1 = X->p[i - 1] << (biL - v1); - X->p[i - 1] >>= v1; - X->p[i - 1] |= r0; - r0 = r1; - } - } - - return( 0 ); -} - -/* - * Compare unsigned values - */ -int mpi_cmp_abs( const mpi *X, const mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( 1 ); - if( j > i ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mpi_cmp_mpi( const mpi *X, const mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( X->s ); - if( j > i ) return( -Y->s ); - - if( X->s > 0 && Y->s < 0 ) return( 1 ); - if( Y->s > 0 && X->s < 0 ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mpi_cmp_int( const mpi *X, t_sint z ) -{ - mpi Y; - t_uint p[1]; - - *p = ( z < 0 ) ? -z : z; - Y.s = ( z < 0 ) ? -1 : 1; - Y.n = 1; - Y.p = p; - - return( mpi_cmp_mpi( X, &Y ) ); -} - -/* - * Unsigned addition: X = |A| + |B| (HAC 14.7) - */ -int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ) -{ - int ret; - size_t i, j; - t_uint *o, *p, c; - - if( X == B ) - { - const mpi *T = A; A = X; B = T; - } - - if( X != A ) - MPI_CHK( mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned additions. - */ - X->s = 1; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MPI_CHK( mpi_grow( X, j ) ); - - o = B->p; p = X->p; c = 0; - - for( i = 0; i < j; i++, o++, p++ ) - { - *p += c; c = ( *p < c ); - *p += *o; c += ( *p < *o ); - } - - while( c != 0 ) - { - if( i >= X->n ) - { - MPI_CHK( mpi_grow( X, i + 1 ) ); - p = X->p + i; - } - - *p += c; c = ( *p < c ); i++; - } - -cleanup: - - return( ret ); -} - -/* - * Helper for mpi substraction - */ -static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d ) -{ - size_t i; - t_uint c, z; - - for( i = c = 0; i < n; i++, s++, d++ ) - { - z = ( *d < c ); *d -= c; - c = ( *d < *s ) + z; *d -= *s; - } - - while( c != 0 ) - { - z = ( *d < c ); *d -= c; - c = z; i++; d++; - } -} - -/* - * Unsigned substraction: X = |A| - |B| (HAC 14.9) - */ -int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ) -{ - mpi TB; - int ret; - size_t n; - - if( mpi_cmp_abs( A, B ) < 0 ) - return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); - - mpi_init( &TB ); - - if( X == B ) - { - MPI_CHK( mpi_copy( &TB, B ) ); - B = &TB; - } - - if( X != A ) - MPI_CHK( mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned substractions. - */ - X->s = 1; - - ret = 0; - - for( n = B->n; n > 0; n-- ) - if( B->p[n - 1] != 0 ) - break; - - mpi_sub_hlp( n, B->p, X->p ); - -cleanup: - - mpi_free( &TB ); - - return( ret ); -} - -/* - * Signed addition: X = A + B - */ -int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s < 0 ) - { - if( mpi_cmp_abs( A, B ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MPI_CHK( mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MPI_CHK( mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed substraction: X = A - B - */ -int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s > 0 ) - { - if( mpi_cmp_abs( A, B ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MPI_CHK( mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MPI_CHK( mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed addition: X = A + b - */ -int mpi_add_int( mpi *X, const mpi *A, t_sint b ) -{ - mpi _B; - t_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_add_mpi( X, A, &_B ) ); -} - -/* - * Signed substraction: X = A - b - */ -int mpi_sub_int( mpi *X, const mpi *A, t_sint b ) -{ - mpi _B; - t_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_sub_mpi( X, A, &_B ) ); -} - -/* - * Helper for mpi multiplication - */ -static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) -{ - t_uint c = 0, t = 0; - -#if defined(MULADDC_HUIT) - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_HUIT - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#else - for( ; i >= 16; i -= 16 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#endif - - t++; - - do { - *d += c; c = ( *d < c ); d++; - } - while( c != 0 ); -} - -/* - * Baseline multiplication: X = A * B (HAC 14.12) - */ -int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret; - size_t i, j; - mpi TA, TB; - - mpi_init( &TA ); mpi_init( &TB ); - - if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; } - if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; } - - for( i = A->n; i > 0; i-- ) - if( A->p[i - 1] != 0 ) - break; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MPI_CHK( mpi_grow( X, i + j ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i++; j > 0; j-- ) - mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); - - X->s = A->s * B->s; - -cleanup: - - mpi_free( &TB ); mpi_free( &TA ); - - return( ret ); -} - -/* - * Baseline multiplication: X = A * b - */ -int mpi_mul_int( mpi *X, const mpi *A, t_sint b ) -{ - mpi _B; - t_uint p[1]; - - _B.s = 1; - _B.n = 1; - _B.p = p; - p[0] = b; - - return( mpi_mul_mpi( X, A, &_B ) ); -} - -/* - * Division by mpi: A = Q * B + R (HAC 14.20) - */ -int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ) -{ - int ret; - size_t i, n, t, k; - mpi X, Y, Z, T1, T2; - - if( mpi_cmp_int( B, 0 ) == 0 ) - return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); - - mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); - mpi_init( &T1 ); mpi_init( &T2 ); - - if( mpi_cmp_abs( A, B ) < 0 ) - { - if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ); - if( R != NULL ) MPI_CHK( mpi_copy( R, A ) ); - return( 0 ); - } - - MPI_CHK( mpi_copy( &X, A ) ); - MPI_CHK( mpi_copy( &Y, B ) ); - X.s = Y.s = 1; - - MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); - MPI_CHK( mpi_lset( &Z, 0 ) ); - MPI_CHK( mpi_grow( &T1, 2 ) ); - MPI_CHK( mpi_grow( &T2, 3 ) ); - - k = mpi_msb( &Y ) % biL; - if( k < biL - 1 ) - { - k = biL - 1 - k; - MPI_CHK( mpi_shift_l( &X, k ) ); - MPI_CHK( mpi_shift_l( &Y, k ) ); - } - else k = 0; - - n = X.n - 1; - t = Y.n - 1; - mpi_shift_l( &Y, biL * (n - t) ); - - while( mpi_cmp_mpi( &X, &Y ) >= 0 ) - { - Z.p[n - t]++; - mpi_sub_mpi( &X, &X, &Y ); - } - mpi_shift_r( &Y, biL * (n - t) ); - - for( i = n; i > t ; i-- ) - { - if( X.p[i] >= Y.p[t] ) - Z.p[i - t - 1] = ~0; - else - { -#if defined(POLARSSL_HAVE_LONGLONG) - t_udbl r; - - r = (t_udbl) X.p[i] << biL; - r |= (t_udbl) X.p[i - 1]; - r /= Y.p[t]; - if( r > ((t_udbl) 1 << biL) - 1) - r = ((t_udbl) 1 << biL) - 1; - - Z.p[i - t - 1] = (t_uint) r; -#else - /* - * __udiv_qrnnd_c, from gmp/longlong.h - */ - t_uint q0, q1, r0, r1; - t_uint d0, d1, d, m; - - d = Y.p[t]; - d0 = ( d << biH ) >> biH; - d1 = ( d >> biH ); - - q1 = X.p[i] / d1; - r1 = X.p[i] - d1 * q1; - r1 <<= biH; - r1 |= ( X.p[i - 1] >> biH ); - - m = q1 * d0; - if( r1 < m ) - { - q1--, r1 += d; - while( r1 >= d && r1 < m ) - q1--, r1 += d; - } - r1 -= m; - - q0 = r1 / d1; - r0 = r1 - d1 * q0; - r0 <<= biH; - r0 |= ( X.p[i - 1] << biH ) >> biH; - - m = q0 * d0; - if( r0 < m ) - { - q0--, r0 += d; - while( r0 >= d && r0 < m ) - q0--, r0 += d; - } - r0 -= m; - - Z.p[i - t - 1] = ( q1 << biH ) | q0; -#endif - } - - Z.p[i - t - 1]++; - do - { - Z.p[i - t - 1]--; - - MPI_CHK( mpi_lset( &T1, 0 ) ); - T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; - T1.p[1] = Y.p[t]; - MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); - - MPI_CHK( mpi_lset( &T2, 0 ) ); - T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; - T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; - T2.p[2] = X.p[i]; - } - while( mpi_cmp_mpi( &T1, &T2 ) > 0 ); - - MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); - MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); - MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); - - if( mpi_cmp_int( &X, 0 ) < 0 ) - { - MPI_CHK( mpi_copy( &T1, &Y ) ); - MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); - MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); - Z.p[i - t - 1]--; - } - } - - if( Q != NULL ) - { - mpi_copy( Q, &Z ); - Q->s = A->s * B->s; - } - - if( R != NULL ) - { - mpi_shift_r( &X, k ); - mpi_copy( R, &X ); - - R->s = A->s; - if( mpi_cmp_int( R, 0 ) == 0 ) - R->s = 1; - } - -cleanup: - - mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); - mpi_free( &T1 ); mpi_free( &T2 ); - - return( ret ); -} - -/* - * Division by int: A = Q * b + R - * - * Returns 0 if successful - * 1 if memory allocation failed - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 - */ -int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ) -{ - mpi _B; - t_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_div_mpi( Q, R, A, &_B ) ); -} - -/* - * Modulo: R = A mod B - */ -int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ) -{ - int ret; - - if( mpi_cmp_int( B, 0 ) < 0 ) - return POLARSSL_ERR_MPI_NEGATIVE_VALUE; - - MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); - - while( mpi_cmp_int( R, 0 ) < 0 ) - MPI_CHK( mpi_add_mpi( R, R, B ) ); - - while( mpi_cmp_mpi( R, B ) >= 0 ) - MPI_CHK( mpi_sub_mpi( R, R, B ) ); - -cleanup: - - return( ret ); -} - -/* - * Modulo: r = A mod b - */ -int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ) -{ - size_t i; - t_uint x, y, z; - - if( b == 0 ) - return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); - - if( b < 0 ) - return POLARSSL_ERR_MPI_NEGATIVE_VALUE; - - /* - * handle trivial cases - */ - if( b == 1 ) - { - *r = 0; - return( 0 ); - } - - if( b == 2 ) - { - *r = A->p[0] & 1; - return( 0 ); - } - - /* - * general case - */ - for( i = A->n, y = 0; i > 0; i-- ) - { - x = A->p[i - 1]; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - - x <<= biH; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - } - - /* - * If A is negative, then the current y represents a negative value. - * Flipping it to the positive side. - */ - if( A->s < 0 && y != 0 ) - y = b - y; - - *r = y; - - return( 0 ); -} - -/* - * Fast Montgomery initialization (thanks to Tom St Denis) - */ -static void mpi_montg_init( t_uint *mm, const mpi *N ) -{ - t_uint x, m0 = N->p[0]; - - x = m0; - x += ( ( m0 + 2 ) & 4 ) << 1; - x *= ( 2 - ( m0 * x ) ); - - if( biL >= 16 ) x *= ( 2 - ( m0 * x ) ); - if( biL >= 32 ) x *= ( 2 - ( m0 * x ) ); - if( biL >= 64 ) x *= ( 2 - ( m0 * x ) ); - - *mm = ~x + 1; -} - -/* - * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) - */ -static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T ) -{ - size_t i, n, m; - t_uint u0, u1, *d; - - memset( T->p, 0, T->n * ciL ); - - d = T->p; - n = N->n; - m = ( B->n < n ) ? B->n : n; - - for( i = 0; i < n; i++ ) - { - /* - * T = (T + u0*B + u1*N) / 2^biL - */ - u0 = A->p[i]; - u1 = ( d[0] + u0 * B->p[0] ) * mm; - - mpi_mul_hlp( m, B->p, d, u0 ); - mpi_mul_hlp( n, N->p, d, u1 ); - - *d++ = u0; d[n + 1] = 0; - } - - memcpy( A->p, d, (n + 1) * ciL ); - - if( mpi_cmp_abs( A, N ) >= 0 ) - mpi_sub_hlp( n, N->p, A->p ); - else - /* prevent timing attacks */ - mpi_sub_hlp( n, A->p, T->p ); -} - -/* - * Montgomery reduction: A = A * R^-1 mod N - */ -static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T ) -{ - t_uint z = 1; - mpi U; - - U.n = U.s = z; - U.p = &z; - - mpi_montmul( A, &U, N, mm, T ); -} - -/* - * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) - */ -int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ) -{ - int ret; - size_t wbits, wsize, one = 1; - size_t i, j, nblimbs; - size_t bufsize, nbits; - t_uint ei, mm, state; - mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ]; - - if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - /* - * Init temps and window size - */ - mpi_montg_init( &mm, N ); - mpi_init( &RR ); mpi_init( &T ); - memset( W, 0, sizeof( W ) ); - - i = mpi_msb( E ); - - wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : - ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; - - if( wsize > POLARSSL_MPI_WINDOW_SIZE ) - wsize = POLARSSL_MPI_WINDOW_SIZE; - - j = N->n + 1; - MPI_CHK( mpi_grow( X, j ) ); - MPI_CHK( mpi_grow( &W[1], j ) ); - MPI_CHK( mpi_grow( &T, j * 2 ) ); - - /* - * If 1st call, pre-compute R^2 mod N - */ - if( _RR == NULL || _RR->p == NULL ) - { - MPI_CHK( mpi_lset( &RR, 1 ) ); - MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) ); - MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) ); - - if( _RR != NULL ) - memcpy( _RR, &RR, sizeof( mpi ) ); - } - else - memcpy( &RR, _RR, sizeof( mpi ) ); - - /* - * W[1] = A * R^2 * R^-1 mod N = A * R mod N - */ - if( mpi_cmp_mpi( A, N ) >= 0 ) - mpi_mod_mpi( &W[1], A, N ); - else mpi_copy( &W[1], A ); - - mpi_montmul( &W[1], &RR, N, mm, &T ); - - /* - * X = R^2 * R^-1 mod N = R mod N - */ - MPI_CHK( mpi_copy( X, &RR ) ); - mpi_montred( X, N, mm, &T ); - - if( wsize > 1 ) - { - /* - * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) - */ - j = one << (wsize - 1); - - MPI_CHK( mpi_grow( &W[j], N->n + 1 ) ); - MPI_CHK( mpi_copy( &W[j], &W[1] ) ); - - for( i = 0; i < wsize - 1; i++ ) - mpi_montmul( &W[j], &W[j], N, mm, &T ); - - /* - * W[i] = W[i - 1] * W[1] - */ - for( i = j + 1; i < (one << wsize); i++ ) - { - MPI_CHK( mpi_grow( &W[i], N->n + 1 ) ); - MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) ); - - mpi_montmul( &W[i], &W[1], N, mm, &T ); - } - } - - nblimbs = E->n; - bufsize = 0; - nbits = 0; - wbits = 0; - state = 0; - - while( 1 ) - { - if( bufsize == 0 ) - { - if( nblimbs-- == 0 ) - break; - - bufsize = sizeof( t_uint ) << 3; - } - - bufsize--; - - ei = (E->p[nblimbs] >> bufsize) & 1; - - /* - * skip leading 0s - */ - if( ei == 0 && state == 0 ) - continue; - - if( ei == 0 && state == 1 ) - { - /* - * out of window, square X - */ - mpi_montmul( X, X, N, mm, &T ); - continue; - } - - /* - * add ei to current window - */ - state = 2; - - nbits++; - wbits |= (ei << (wsize - nbits)); - - if( nbits == wsize ) - { - /* - * X = X^wsize R^-1 mod N - */ - for( i = 0; i < wsize; i++ ) - mpi_montmul( X, X, N, mm, &T ); - - /* - * X = X * W[wbits] R^-1 mod N - */ - mpi_montmul( X, &W[wbits], N, mm, &T ); - - state--; - nbits = 0; - wbits = 0; - } - } - - /* - * process the remaining bits - */ - for( i = 0; i < nbits; i++ ) - { - mpi_montmul( X, X, N, mm, &T ); - - wbits <<= 1; - - if( (wbits & (one << wsize)) != 0 ) - mpi_montmul( X, &W[1], N, mm, &T ); - } - - /* - * X = A^E * R * R^-1 mod N = A^E mod N - */ - mpi_montred( X, N, mm, &T ); - -cleanup: - - for( i = (one << (wsize - 1)); i < (one << wsize); i++ ) - mpi_free( &W[i] ); - - mpi_free( &W[1] ); mpi_free( &T ); - - if( _RR == NULL ) - mpi_free( &RR ); - - return( ret ); -} - -/* - * Greatest common divisor: G = gcd(A, B) (HAC 14.54) - */ -int mpi_gcd( mpi *G, const mpi *A, const mpi *B ) -{ - int ret; - size_t lz, lzt; - mpi TG, TA, TB; - - mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB ); - - MPI_CHK( mpi_copy( &TA, A ) ); - MPI_CHK( mpi_copy( &TB, B ) ); - - lz = mpi_lsb( &TA ); - lzt = mpi_lsb( &TB ); - - if ( lzt < lz ) - lz = lzt; - - MPI_CHK( mpi_shift_r( &TA, lz ) ); - MPI_CHK( mpi_shift_r( &TB, lz ) ); - - TA.s = TB.s = 1; - - while( mpi_cmp_int( &TA, 0 ) != 0 ) - { - MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) ); - MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) ); - - if( mpi_cmp_mpi( &TA, &TB ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) ); - MPI_CHK( mpi_shift_r( &TA, 1 ) ); - } - else - { - MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) ); - MPI_CHK( mpi_shift_r( &TB, 1 ) ); - } - } - - MPI_CHK( mpi_shift_l( &TB, lz ) ); - MPI_CHK( mpi_copy( G, &TB ) ); - -cleanup: - - mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB ); - - return( ret ); -} - -int mpi_fill_random( mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - - MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) ); - -cleanup: - return( ret ); -} - -#if defined(POLARSSL_GENPRIME) - -/* - * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) - */ -int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ) -{ - int ret; - mpi G, TA, TU, U1, U2, TB, TV, V1, V2; - - if( mpi_cmp_int( N, 0 ) <= 0 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 ); - mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV ); - mpi_init( &V1 ); mpi_init( &V2 ); - - MPI_CHK( mpi_gcd( &G, A, N ) ); - - if( mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; - goto cleanup; - } - - MPI_CHK( mpi_mod_mpi( &TA, A, N ) ); - MPI_CHK( mpi_copy( &TU, &TA ) ); - MPI_CHK( mpi_copy( &TB, N ) ); - MPI_CHK( mpi_copy( &TV, N ) ); - - MPI_CHK( mpi_lset( &U1, 1 ) ); - MPI_CHK( mpi_lset( &U2, 0 ) ); - MPI_CHK( mpi_lset( &V1, 0 ) ); - MPI_CHK( mpi_lset( &V2, 1 ) ); - - do - { - while( ( TU.p[0] & 1 ) == 0 ) - { - MPI_CHK( mpi_shift_r( &TU, 1 ) ); - - if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) - { - MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) ); - MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) ); - } - - MPI_CHK( mpi_shift_r( &U1, 1 ) ); - MPI_CHK( mpi_shift_r( &U2, 1 ) ); - } - - while( ( TV.p[0] & 1 ) == 0 ) - { - MPI_CHK( mpi_shift_r( &TV, 1 ) ); - - if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) - { - MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) ); - MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) ); - } - - MPI_CHK( mpi_shift_r( &V1, 1 ) ); - MPI_CHK( mpi_shift_r( &V2, 1 ) ); - } - - if( mpi_cmp_mpi( &TU, &TV ) >= 0 ) - { - MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) ); - MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) ); - MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) ); - } - else - { - MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) ); - MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) ); - MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) ); - } - } - while( mpi_cmp_int( &TU, 0 ) != 0 ); - - while( mpi_cmp_int( &V1, 0 ) < 0 ) - MPI_CHK( mpi_add_mpi( &V1, &V1, N ) ); - - while( mpi_cmp_mpi( &V1, N ) >= 0 ) - MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) ); - - MPI_CHK( mpi_copy( X, &V1 ) ); - -cleanup: - - mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 ); - mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV ); - mpi_free( &V1 ); mpi_free( &V2 ); - - return( ret ); -} - -static const int small_prime[] = -{ - 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, - 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, - 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, - 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, - 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, - 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, - 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997, -103 -}; - -/* - * Miller-Rabin primality test (HAC 4.24) - */ -int mpi_is_prime( mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, xs; - size_t i, j, n, s; - mpi W, R, T, A, RR; - - if( mpi_cmp_int( X, 0 ) == 0 || - mpi_cmp_int( X, 1 ) == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - - if( mpi_cmp_int( X, 2 ) == 0 ) - return( 0 ); - - mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A ); - mpi_init( &RR ); - - xs = X->s; X->s = 1; - - /* - * test trivial factors first - */ - if( ( X->p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - - for( i = 0; small_prime[i] > 0; i++ ) - { - t_uint r; - - if( mpi_cmp_int( X, small_prime[i] ) <= 0 ) - return( 0 ); - - MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) ); - - if( r == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - } - - /* - * W = |X| - 1 - * R = W >> lsb( W ) - */ - MPI_CHK( mpi_sub_int( &W, X, 1 ) ); - s = mpi_lsb( &W ); - MPI_CHK( mpi_copy( &R, &W ) ); - MPI_CHK( mpi_shift_r( &R, s ) ); - - i = mpi_msb( X ); - /* - * HAC, table 4.4 - */ - n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : - ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : - ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); - - for( i = 0; i < n; i++ ) - { - /* - * pick a random A, 1 < A < |X| - 1 - */ - MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - if( mpi_cmp_mpi( &A, &W ) >= 0 ) - { - j = mpi_msb( &A ) - mpi_msb( &W ); - MPI_CHK( mpi_shift_r( &A, j + 1 ) ); - } - A.p[0] |= 3; - - /* - * A = A^R mod |X| - */ - MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) ); - - if( mpi_cmp_mpi( &A, &W ) == 0 || - mpi_cmp_int( &A, 1 ) == 0 ) - continue; - - j = 1; - while( j < s && mpi_cmp_mpi( &A, &W ) != 0 ) - { - /* - * A = A * A mod |X| - */ - MPI_CHK( mpi_mul_mpi( &T, &A, &A ) ); - MPI_CHK( mpi_mod_mpi( &A, &T, X ) ); - - if( mpi_cmp_int( &A, 1 ) == 0 ) - break; - - j++; - } - - /* - * not prime if A != |X| - 1 or A == 1 - */ - if( mpi_cmp_mpi( &A, &W ) != 0 || - mpi_cmp_int( &A, 1 ) == 0 ) - { - ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; - break; - } - } - -cleanup: - - X->s = xs; - - mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A ); - mpi_free( &RR ); - - return( ret ); -} - -/* - * Prime number generation - */ -int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t k, n; - mpi Y; - - if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &Y ); - - n = BITS_TO_LIMBS( nbits ); - - MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); - - k = mpi_msb( X ); - if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) ); - if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) ); - - X->p[0] |= 3; - - if( dh_flag == 0 ) - { - while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) - { - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MPI_CHK( mpi_add_int( X, X, 2 ) ); - } - } - else - { - MPI_CHK( mpi_sub_int( &Y, X, 1 ) ); - MPI_CHK( mpi_shift_r( &Y, 1 ) ); - - while( 1 ) - { - if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 ) - { - if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 ) - break; - - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - } - - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MPI_CHK( mpi_add_int( &Y, X, 1 ) ); - MPI_CHK( mpi_add_int( X, X, 2 ) ); - MPI_CHK( mpi_shift_r( &Y, 1 ) ); - } - } - -cleanup: - - mpi_free( &Y ); - - return( ret ); -} - -#endif - -#if defined(POLARSSL_SELF_TEST) - -#define GCD_PAIR_COUNT 3 - -static const int gcd_pairs[GCD_PAIR_COUNT][3] = -{ - { 693, 609, 21 }, - { 1764, 868, 28 }, - { 768454923, 542167814, 1 } -}; - -/* - * Checkup routine - */ -int mpi_self_test( int verbose ) -{ - int ret, i; - mpi A, E, N, X, Y, U, V; - - mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X ); - mpi_init( &Y ); mpi_init( &U ); mpi_init( &V ); - - MPI_CHK( mpi_read_string( &A, 16, - "EFE021C2645FD1DC586E69184AF4A31E" \ - "D5F53E93B5F123FA41680867BA110131" \ - "944FE7952E2517337780CB0DB80E61AA" \ - "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); - - MPI_CHK( mpi_read_string( &E, 16, - "B2E7EFD37075B9F03FF989C7C5051C20" \ - "34D2A323810251127E7BF8625A4F49A5" \ - "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ - "5B5C25763222FEFCCFC38B832366C29E" ) ); - - MPI_CHK( mpi_read_string( &N, 16, - "0066A198186C18C10B2F5ED9B522752A" \ - "9830B69916E535C8F047518A889A43A5" \ - "94B6BED27A168D31D4A52F88925AA8F5" ) ); - - MPI_CHK( mpi_mul_mpi( &X, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "602AB7ECA597A3D6B56FF9829A5E8B85" \ - "9E857EA95A03512E2BAE7391688D264A" \ - "A5663B0341DB9CCFD2C4C5F421FEC814" \ - "8001B72E848A38CAE1C65F78E56ABDEF" \ - "E12D3C039B8A02D6BE593F0BBBDA56F1" \ - "ECF677152EF804370C1A305CAF3B5BF1" \ - "30879B56C61DE584A0F53A2447A51E" ) ); - - if( verbose != 0 ) - printf( " MPI test #1 (mul_mpi): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "256567336059E52CAE22925474705F39A94" ) ); - - MPI_CHK( mpi_read_string( &V, 16, - "6613F26162223DF488E9CD48CC132C7A" \ - "0AC93C701B001B092E4E5B9F73BCD27B" \ - "9EE50D0657C77F374E903CDFA4C642" ) ); - - if( verbose != 0 ) - printf( " MPI test #2 (div_mpi): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 || - mpi_cmp_mpi( &Y, &V ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "36E139AEA55215609D2816998ED020BB" \ - "BD96C37890F65171D948E9BC7CBAA4D9" \ - "325D24D6A3C12710F10A09FA08AB87" ) ); - - if( verbose != 0 ) - printf( " MPI test #3 (exp_mod): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - -#if defined(POLARSSL_GENPRIME) - MPI_CHK( mpi_inv_mod( &X, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ - "C3DBA76456363A10869622EAC2DD84EC" \ - "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); - - if( verbose != 0 ) - printf( " MPI test #4 (inv_mod): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); -#endif - - if( verbose != 0 ) - printf( " MPI test #5 (simple gcd): " ); - - for ( i = 0; i < GCD_PAIR_COUNT; i++) - { - MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) ); - MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) ); - - MPI_CHK( mpi_gcd( &A, &X, &Y ) ); - - if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) - { - if( verbose != 0 ) - printf( "failed at %d\n", i ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - -cleanup: - - if( ret != 0 && verbose != 0 ) - printf( "Unexpected error, return code = %08X\n", ret ); - - mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X ); - mpi_free( &Y ); mpi_free( &U ); mpi_free( &V ); - - if( verbose != 0 ) - printf( "\n" ); - - return( ret ); -} - -#endif - -#endif diff --git a/polarssl/src/library/camellia.c b/polarssl/src/library/camellia.c deleted file mode 100644 index 34b8f29..0000000 --- a/polarssl/src/library/camellia.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * Camellia implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The Camellia block cipher was designed by NTT and Mitsubishi Electric - * Corporation. - * - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_CAMELLIA_C) - -#include "polarssl/camellia.h" - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -static const unsigned char SIGMA_CHARS[6][8] = -{ - { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, - { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, - { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, - { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, - { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, - { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } -}; - -#if defined(POLARSSL_CAMELLIA_SMALL_MEMORY) - -static const unsigned char FSb[256] = -{ - 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, - 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, - 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, - 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, - 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, - 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, - 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, - 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, - 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, - 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, - 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, - 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, - 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, - 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, - 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, - 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 -}; - -#define SBOX1(n) FSb[(n)] -#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) -#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) -#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] - -#else - -static const unsigned char FSb[256] = -{ - 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, - 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, - 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, - 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, - 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, - 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, - 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, - 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, - 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, - 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, - 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, - 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, - 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, - 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, - 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, - 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 -}; - -static const unsigned char FSb2[256] = -{ - 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, - 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, - 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, - 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, - 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, - 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, - 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, - 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, - 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, - 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, - 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, - 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, - 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, - 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, - 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, - 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 -}; - -static const unsigned char FSb3[256] = -{ - 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, - 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, - 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, - 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, - 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, - 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, - 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, - 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, - 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, - 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, - 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, - 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, - 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, - 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, - 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, - 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 -}; - -static const unsigned char FSb4[256] = -{ - 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, - 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, - 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, - 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, - 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, - 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, - 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, - 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, - 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, - 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, - 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, - 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, - 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, - 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, - 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, - 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 -}; - -#define SBOX1(n) FSb[(n)] -#define SBOX2(n) FSb2[(n)] -#define SBOX3(n) FSb3[(n)] -#define SBOX4(n) FSb4[(n)] - -#endif - -static const unsigned char shifts[2][4][4] = -{ - { - { 1, 1, 1, 1 }, /* KL */ - { 0, 0, 0, 0 }, /* KR */ - { 1, 1, 1, 1 }, /* KA */ - { 0, 0, 0, 0 } /* KB */ - }, - { - { 1, 0, 1, 1 }, /* KL */ - { 1, 1, 0, 1 }, /* KR */ - { 1, 1, 1, 0 }, /* KA */ - { 1, 1, 0, 1 } /* KB */ - } -}; - -static const signed char indexes[2][4][20] = -{ - { - { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, - 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ - { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, - 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ - }, - { - { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, - -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ - { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, - 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ - { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, - 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ - { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, - 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ - } -}; - -static const signed char transposes[2][20] = -{ - { - 21, 22, 23, 20, - -1, -1, -1, -1, - 18, 19, 16, 17, - 11, 8, 9, 10, - 15, 12, 13, 14 - }, - { - 25, 26, 27, 24, - 29, 30, 31, 28, - 18, 19, 16, 17, - -1, -1, -1, -1, - -1, -1, -1, -1 - } -}; - -/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ -#define ROTL(DEST, SRC, SHIFT) \ -{ \ - (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ - (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ - (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ - (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ -} - -#define FL(XL, XR, KL, KR) \ -{ \ - (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ - (XL) = ((XR) | (KR)) ^ (XL); \ -} - -#define FLInv(YL, YR, KL, KR) \ -{ \ - (YL) = ((YR) | (KR)) ^ (YL); \ - (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ -} - -#define SHIFT_AND_PLACE(INDEX, OFFSET) \ -{ \ - TK[0] = KC[(OFFSET) * 4 + 0]; \ - TK[1] = KC[(OFFSET) * 4 + 1]; \ - TK[2] = KC[(OFFSET) * 4 + 2]; \ - TK[3] = KC[(OFFSET) * 4 + 3]; \ - \ - for ( i = 1; i <= 4; i++ ) \ - if (shifts[(INDEX)][(OFFSET)][i -1]) \ - ROTL(TK + i * 4, TK, (15 * i) % 32); \ - \ - for ( i = 0; i < 20; i++ ) \ - if (indexes[(INDEX)][(OFFSET)][i] != -1) { \ - RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ - } \ -} - -static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2]) -{ - uint32_t I0, I1; - I0 = x[0] ^ k[0]; - I1 = x[1] ^ k[1]; - - I0 = (SBOX1((I0 >> 24) & 0xFF) << 24) | - (SBOX2((I0 >> 16) & 0xFF) << 16) | - (SBOX3((I0 >> 8) & 0xFF) << 8) | - (SBOX4((I0 ) & 0xFF) ); - I1 = (SBOX2((I1 >> 24) & 0xFF) << 24) | - (SBOX3((I1 >> 16) & 0xFF) << 16) | - (SBOX4((I1 >> 8) & 0xFF) << 8) | - (SBOX1((I1 ) & 0xFF) ); - - I0 ^= (I1 << 8) | (I1 >> 24); - I1 ^= (I0 << 16) | (I0 >> 16); - I0 ^= (I1 >> 8) | (I1 << 24); - I1 ^= (I0 >> 8) | (I0 << 24); - - z[0] ^= I1; - z[1] ^= I0; -} - -/* - * Camellia key schedule (encryption) - */ -int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize ) -{ - int idx; - size_t i; - uint32_t *RK; - unsigned char t[64]; - uint32_t SIGMA[6][2]; - uint32_t KC[16]; - uint32_t TK[20]; - - RK = ctx->rk; - - memset(t, 0, 64); - memset(RK, 0, sizeof(ctx->rk)); - - switch( keysize ) - { - case 128: ctx->nr = 3; idx = 0; break; - case 192: - case 256: ctx->nr = 4; idx = 1; break; - default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH ); - } - - for( i = 0; i < keysize / 8; ++i) - t[i] = key[i]; - - if (keysize == 192) { - for (i = 0; i < 8; i++) - t[24 + i] = ~t[16 + i]; - } - - /* - * Prepare SIGMA values - */ - for (i = 0; i < 6; i++) { - GET_ULONG_BE(SIGMA[i][0], SIGMA_CHARS[i], 0); - GET_ULONG_BE(SIGMA[i][1], SIGMA_CHARS[i], 4); - } - - /* - * Key storage in KC - * Order: KL, KR, KA, KB - */ - memset(KC, 0, sizeof(KC)); - - /* Store KL, KR */ - for (i = 0; i < 8; i++) - GET_ULONG_BE(KC[i], t, i * 4); - - /* Generate KA */ - for( i = 0; i < 4; ++i) - KC[8 + i] = KC[i] ^ KC[4 + i]; - - camellia_feistel(KC + 8, SIGMA[0], KC + 10); - camellia_feistel(KC + 10, SIGMA[1], KC + 8); - - for( i = 0; i < 4; ++i) - KC[8 + i] ^= KC[i]; - - camellia_feistel(KC + 8, SIGMA[2], KC + 10); - camellia_feistel(KC + 10, SIGMA[3], KC + 8); - - if (keysize > 128) { - /* Generate KB */ - for( i = 0; i < 4; ++i) - KC[12 + i] = KC[4 + i] ^ KC[8 + i]; - - camellia_feistel(KC + 12, SIGMA[4], KC + 14); - camellia_feistel(KC + 14, SIGMA[5], KC + 12); - } - - /* - * Generating subkeys - */ - - /* Manipulating KL */ - SHIFT_AND_PLACE(idx, 0); - - /* Manipulating KR */ - if (keysize > 128) { - SHIFT_AND_PLACE(idx, 1); - } - - /* Manipulating KA */ - SHIFT_AND_PLACE(idx, 2); - - /* Manipulating KB */ - if (keysize > 128) { - SHIFT_AND_PLACE(idx, 3); - } - - /* Do transpositions */ - for ( i = 0; i < 20; i++ ) { - if (transposes[idx][i] != -1) { - RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; - } - } - - return( 0 ); -} - -/* - * Camellia key schedule (decryption) - */ -int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize ) -{ - int idx; - size_t i; - camellia_context cty; - uint32_t *RK; - uint32_t *SK; - int ret; - - switch( keysize ) - { - case 128: ctx->nr = 3; idx = 0; break; - case 192: - case 256: ctx->nr = 4; idx = 1; break; - default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH ); - } - - RK = ctx->rk; - - ret = camellia_setkey_enc(&cty, key, keysize); - if( ret != 0 ) - return( ret ); - - SK = cty.rk + 24 * 2 + 8 * idx * 2; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4) - { - *RK++ = *SK++; - *RK++ = *SK++; - } - - SK -= 2; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - memset( &cty, 0, sizeof( camellia_context ) ); - - return( 0 ); -} - -/* - * Camellia-ECB block encryption/decryption - */ -int camellia_crypt_ecb( camellia_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int NR; - uint32_t *RK, X[4]; - - ( (void) mode ); - - NR = ctx->nr; - RK = ctx->rk; - - GET_ULONG_BE( X[0], input, 0 ); - GET_ULONG_BE( X[1], input, 4 ); - GET_ULONG_BE( X[2], input, 8 ); - GET_ULONG_BE( X[3], input, 12 ); - - X[0] ^= *RK++; - X[1] ^= *RK++; - X[2] ^= *RK++; - X[3] ^= *RK++; - - while (NR) { - --NR; - camellia_feistel(X, RK, X + 2); - RK += 2; - camellia_feistel(X + 2, RK, X); - RK += 2; - camellia_feistel(X, RK, X + 2); - RK += 2; - camellia_feistel(X + 2, RK, X); - RK += 2; - camellia_feistel(X, RK, X + 2); - RK += 2; - camellia_feistel(X + 2, RK, X); - RK += 2; - - if (NR) { - FL(X[0], X[1], RK[0], RK[1]); - RK += 2; - FLInv(X[2], X[3], RK[0], RK[1]); - RK += 2; - } - } - - X[2] ^= *RK++; - X[3] ^= *RK++; - X[0] ^= *RK++; - X[1] ^= *RK++; - - PUT_ULONG_BE( X[2], output, 0 ); - PUT_ULONG_BE( X[3], output, 4 ); - PUT_ULONG_BE( X[0], output, 8 ); - PUT_ULONG_BE( X[1], output, 12 ); - - return( 0 ); -} - -/* - * Camellia-CBC buffer encryption/decryption - */ -int camellia_crypt_cbc( camellia_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[16]; - - if( length % 16 ) - return( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); - - if( mode == CAMELLIA_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 16 ); - camellia_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - camellia_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - - return( 0 ); -} - -#if defined(POLARSSL_CIPHER_MODE_CFB) -/* - * Camellia-CFB128 buffer encryption/decryption - */ -int camellia_crypt_cfb128( camellia_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == CAMELLIA_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = (n + 1) & 0x0F; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = (n + 1) & 0x0F; - } - } - - *iv_off = n; - - return( 0 ); -} -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -/* - * Camellia-CTR buffer encryption/decryption - */ -int camellia_crypt_ctr( camellia_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter, stream_block ); - - for( i = 16; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = (n + 1) & 0x0F; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -#if defined(POLARSSL_SELF_TEST) - -#include - -/* - * Camellia test vectors from: - * - * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt - * (For each bitlength: Key 0, Nr 39) - */ -#define CAMELLIA_TESTS_ECB 2 - -static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = -{ - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, -}; - -static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = -{ - { - { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, - 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, - { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, - 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } - }, - { - { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, - 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, - { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, - 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } - }, - { - { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, - 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, - { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, - 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } - } -}; - -#define CAMELLIA_TESTS_CBC 3 - -static const unsigned char camellia_test_cbc_key[3][32] = -{ - { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, - 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } - , - { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, - 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, - 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } - , - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } -}; - -static const unsigned char camellia_test_cbc_iv[16] = - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } -; - -static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = -{ - { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, - { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, - { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, - 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } - -}; - -static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = -{ - { - { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, - 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, - { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, - 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, - { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, - 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } - }, - { - { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, - 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, - { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, - 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, - { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, - 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } - }, - { - { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, - 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, - { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, - 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, - { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, - 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } - } -}; - -#if defined(POLARSSL_CIPHER_MODE_CTR) -/* - * Camellia-CTR test vectors from: - * - * http://www.faqs.org/rfcs/rfc5528.html - */ - -static const unsigned char camellia_test_ctr_key[3][16] = -{ - { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, - 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, - { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, - 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, - { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, - 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } -}; - -static const unsigned char camellia_test_ctr_nonce_counter[3][16] = -{ - { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, - 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, - 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } -}; - -static const unsigned char camellia_test_ctr_pt[3][48] = -{ - { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, - 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23 } -}; - -static const unsigned char camellia_test_ctr_ct[3][48] = -{ - { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, - 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, - { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, - 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, - 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, - 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, - { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, - 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, - 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, - 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, - 0xDF, 0x50, 0x86, 0x96 } -}; - -static const int camellia_test_ctr_len[3] = - { 16, 32, 36 }; -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -/* - * Checkup routine - */ -int camellia_self_test( int verbose ) -{ - int i, j, u, v; - unsigned char key[32]; - unsigned char buf[64]; - unsigned char src[16]; - unsigned char dst[16]; - unsigned char iv[16]; -#if defined(POLARSSL_CIPHER_MODE_CTR) - size_t offset, len; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; -#endif - - camellia_context ctx; - - memset( key, 0, 32 ); - - for (j = 0; j < 6; j++) { - u = j >> 1; - v = j & 1; - - if( verbose != 0 ) - printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, - (v == CAMELLIA_DECRYPT) ? "dec" : "enc"); - - for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { - memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u); - - if (v == CAMELLIA_DECRYPT) { - camellia_setkey_dec(&ctx, key, 128 + u * 64); - memcpy(src, camellia_test_ecb_cipher[u][i], 16); - memcpy(dst, camellia_test_ecb_plain[i], 16); - } else { /* CAMELLIA_ENCRYPT */ - camellia_setkey_enc(&ctx, key, 128 + u * 64); - memcpy(src, camellia_test_ecb_plain[i], 16); - memcpy(dst, camellia_test_ecb_cipher[u][i], 16); - } - - camellia_crypt_ecb(&ctx, v, src, buf); - - if( memcmp( buf, dst, 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - /* - * CBC mode - */ - for( j = 0; j < 6; j++ ) - { - u = j >> 1; - v = j & 1; - - if( verbose != 0 ) - printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, - ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" ); - - memcpy( src, camellia_test_cbc_iv, 16); - memcpy( dst, camellia_test_cbc_iv, 16); - memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u); - - if (v == CAMELLIA_DECRYPT) { - camellia_setkey_dec(&ctx, key, 128 + u * 64); - } else { - camellia_setkey_enc(&ctx, key, 128 + u * 64); - } - - for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { - - if (v == CAMELLIA_DECRYPT) { - memcpy( iv , src, 16 ); - memcpy(src, camellia_test_cbc_cipher[u][i], 16); - memcpy(dst, camellia_test_cbc_plain[i], 16); - } else { /* CAMELLIA_ENCRYPT */ - memcpy( iv , dst, 16 ); - memcpy(src, camellia_test_cbc_plain[i], 16); - memcpy(dst, camellia_test_cbc_cipher[u][i], 16); - } - - camellia_crypt_cbc(&ctx, v, 16, iv, src, buf); - - if( memcmp( buf, dst, 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - -#if defined(POLARSSL_CIPHER_MODE_CTR) - /* - * CTR mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " CAMELLIA-CTR-128 (%s): ", - ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" ); - - memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); - memcpy( key, camellia_test_ctr_key[u], 16 ); - - offset = 0; - camellia_setkey_enc( &ctx, key, 128 ); - - if( v == CAMELLIA_DECRYPT ) - { - len = camellia_test_ctr_len[u]; - memcpy( buf, camellia_test_ctr_ct[u], len ); - - camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf ); - - if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - else - { - len = camellia_test_ctr_len[u]; - memcpy( buf, camellia_test_ctr_pt[u], len ); - - camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf ); - - if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); -#endif /* POLARSSL_CIPHER_MODE_CTR */ - - return ( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/certs.c b/polarssl/src/library/certs.c deleted file mode 100644 index e2d07f7..0000000 --- a/polarssl/src/library/certs.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * X.509 test certificates - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_CERTS_C) - -const char test_ca_crt[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" -"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" -"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" -"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" -"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" -"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" -"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" -"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" -"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" -"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" -"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" -"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" -"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" -"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" -"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" -"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" -"-----END CERTIFICATE-----\r\n"; - -const char test_ca_key[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"Proc-Type: 4,ENCRYPTED\r\n" -"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" -"\r\n" -"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" -"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" -"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" -"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" -"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" -"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" -"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" -"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" -"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" -"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" -"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" -"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" -"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" -"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" -"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" -"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" -"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" -"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" -"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" -"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" -"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" -"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" -"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" -"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" -"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; - -const char test_ca_pwd[] = "PolarSSLTest"; - -const char test_srv_crt[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN\r\n" -"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/\r\n" -"uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD\r\n" -"d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf\r\n" -"CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr\r\n" -"lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w\r\n" -"bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB\r\n" -"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf\r\n" -"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n" -"AQEAvc+WwZUemsJu2IiI2Cp6liA+UAvIx98dQe3kZs2zAoF9VwQbXcYzWQ/BILkj\r\n" -"NImKbPL9x0g2jIDn4ZvGYFywMwIO/d++YbwYiQw42/v7RiMy94zBPnzeHi86dy/0\r\n" -"jpOOJUx3IXRsGLdyjb/1T11klcFqGnARiK+8VYolMPP6afKvLXX7K4kiUpsFQhUp\r\n" -"E5VeM5pV1Mci2ETOJau2cO40FJvI/C9W/wR+GAArMaw2fxG77E3laaa0LAOlexM6\r\n" -"A4KOb5f5cGTM5Ih6tEF5FVq3/9vzNIYMa1FqzacBLZF8zSHYLEimXBdzjBoN4qDU\r\n" -"/WzRyYRBRjAI49mzHX6raleqnw==\r\n" -"-----END CERTIFICATE-----\r\n"; - -const char test_srv_key[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"MIIEogIBAAKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/uOhFkNvuiBZS0/FDUEeW\r\n" -"Ellkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFDd185fAkER4KwVzlw7aPs\r\n" -"FRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVfCrFTxjB+FTms+Vruf5Ke\r\n" -"pgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTrlZvc/kFeF6babFtpzAK6\r\n" -"FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9wbp7OvViJ4lNZnm5akmXi\r\n" -"iD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQABAoIBABaJ9eiRQq4Ypv+w\r\n" -"UTcVpLC0oTueWzcpor1i1zjG4Vzqe/Ok2FqyGToGKMlFK7Hwwa+LEyeJ3xyV5yd4\r\n" -"v1Mw9bDZFdJC1eCBjoUAHtX6k9HOE0Vd6woVQ4Vi6OPI1g7B5Mnr/58rNrnN6TMs\r\n" -"x58NF6euecwTU811QJrZtLbX7j2Cr28yB2Vs8qyYlHwVw5jbDOv43D7vU5gmlIDN\r\n" -"0JQRuWAnOuPzZNoJr4SfJKqHNGxYYY6pHZ1s0dOTLIDb/B8KQWapA2kRmZyid2EH\r\n" -"nwzgLbAsHJCf+bQnhXjXuxtUsrcIL8noZLazlOMxwNEammglVWW23Ud/QRnFgJg5\r\n" -"UgcAcRECgYEA19uYetht5qmwdJ+12oC6zeO+vXLcyD9gon23T5J6w2YThld7/OW0\r\n" -"oArQJGgkAdaq0pcTyOIjtTQVMFygdVmCEJmxh/3RutPcTeydqW9fphKDMej32J8e\r\n" -"GniGmNGiclbcfNOS8E5TGp445yZb9P1+7AHng16bGg3Ykj5EA4G+HCcCgYEAyHAl\r\n" -"//ekk8YjQElm+8izLtFkymIK0aCtEe9C/RIRhFYBeFaotC5dStNhBOncn4ovMAPD\r\n" -"lX/92yDi9OP8PPLN3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n" -"LYl3YWr2h3EGKICT03kEoTkiDBvCeOpW7cCGl2cCgYBD5whoXHz1+ptPlI4YVjZt\r\n" -"Xh86aU+ajpVPiEyJ84I6xXmO4SZXv8q6LaycR0ZMbcL+zBelMb4Z2nBv7jNrtuR7\r\n" -"ZF28cdPv+YVr3esaybZE/73VjXup4SQPH6r3l7qKTVi+y6+FeJ4b2Xn8/MwgnT23\r\n" -"8EFrye7wmzpthrjOgZnUMQKBgE9Lhsz/5J0Nis6Y+2Pqn3CLKEukg9Ewtqdct2y0\r\n" -"5Dcta0F3TyCRIxlCDKTL/BslqMtfAdY4H268UO0+8IAQMn9boqzBrHIgs/pvc5kx\r\n" -"TbKHmw2wtWR6vYersBKVgVpbCGSRssDYHGFu1n74qM4HJ/RGcR1zI9QUe1gopSFD\r\n" -"xDtLAoGAVAdWvrqDwgoL2hHW3scGpxdE/ygJDOwHnf+1B9goKAOP5lf2FJaiAxf3\r\n" -"ectoPOgZbCmm/iiDmigu703ld3O+VoCLDD4qx3R+KyALL78gtVJYzSRiKhzgCZ3g\r\n" -"mKsIVRBq4IfwiwyMNG2BYZQAwbSDjjPtn/kPBduPzPj7eriByhI=\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; - -const char test_cli_crt[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" -"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" -"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" -"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" -"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" -"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" -"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" -"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" -"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n" -"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n" -"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n" -"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n" -"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n" -"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n" -"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n" -"-----END CERTIFICATE-----\r\n"; - -const char test_cli_key[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" -"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" -"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" -"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" -"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" -"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" -"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" -"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" -"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" -"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" -"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" -"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" -"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" -"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" -"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" -"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" -"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" -"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" -"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" -"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" -"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" -"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" -"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" -"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" -"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; - -const char test_dhm_params[] = -"-----BEGIN DH PARAMETERS-----\r\n" -"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" -"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" -"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" -"-----END DH PARAMETERS-----\r\n"; - -#endif diff --git a/polarssl/src/library/cipher.c b/polarssl/src/library/cipher.c deleted file mode 100644 index 0d1258b..0000000 --- a/polarssl/src/library/cipher.c +++ /dev/null @@ -1,557 +0,0 @@ -/** - * \file cipher.c - * - * \brief Generic cipher wrapper for PolarSSL - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_CIPHER_C) - -#include "polarssl/cipher.h" -#include "polarssl/cipher_wrap.h" - -#include - -#if defined _MSC_VER && !defined strcasecmp -#define strcasecmp _stricmp -#endif - -static const int supported_ciphers[] = { - -#if defined(POLARSSL_AES_C) - POLARSSL_CIPHER_AES_128_CBC, - POLARSSL_CIPHER_AES_192_CBC, - POLARSSL_CIPHER_AES_256_CBC, - -#if defined(POLARSSL_CIPHER_MODE_CFB) - POLARSSL_CIPHER_AES_128_CFB128, - POLARSSL_CIPHER_AES_192_CFB128, - POLARSSL_CIPHER_AES_256_CFB128, -#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) - POLARSSL_CIPHER_AES_128_CTR, - POLARSSL_CIPHER_AES_192_CTR, - POLARSSL_CIPHER_AES_256_CTR, -#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ - -#endif /* defined(POLARSSL_AES_C) */ - -#if defined(POLARSSL_CAMELLIA_C) - POLARSSL_CIPHER_CAMELLIA_128_CBC, - POLARSSL_CIPHER_CAMELLIA_192_CBC, - POLARSSL_CIPHER_CAMELLIA_256_CBC, - -#if defined(POLARSSL_CIPHER_MODE_CFB) - POLARSSL_CIPHER_CAMELLIA_128_CFB128, - POLARSSL_CIPHER_CAMELLIA_192_CFB128, - POLARSSL_CIPHER_CAMELLIA_256_CFB128, -#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) - POLARSSL_CIPHER_CAMELLIA_128_CTR, - POLARSSL_CIPHER_CAMELLIA_192_CTR, - POLARSSL_CIPHER_CAMELLIA_256_CTR, -#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ - -#endif /* defined(POLARSSL_CAMELLIA_C) */ - -#if defined(POLARSSL_DES_C) - POLARSSL_CIPHER_DES_CBC, - POLARSSL_CIPHER_DES_EDE_CBC, - POLARSSL_CIPHER_DES_EDE3_CBC, -#endif /* defined(POLARSSL_DES_C) */ - -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - POLARSSL_CIPHER_NULL, -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - - 0 -}; - -const int *cipher_list( void ) -{ - return supported_ciphers; -} - -const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type ) -{ - /* Find static cipher information */ - switch ( cipher_type ) - { -#if defined(POLARSSL_AES_C) - case POLARSSL_CIPHER_AES_128_CBC: - return &aes_128_cbc_info; - case POLARSSL_CIPHER_AES_192_CBC: - return &aes_192_cbc_info; - case POLARSSL_CIPHER_AES_256_CBC: - return &aes_256_cbc_info; - -#if defined(POLARSSL_CIPHER_MODE_CFB) - case POLARSSL_CIPHER_AES_128_CFB128: - return &aes_128_cfb128_info; - case POLARSSL_CIPHER_AES_192_CFB128: - return &aes_192_cfb128_info; - case POLARSSL_CIPHER_AES_256_CFB128: - return &aes_256_cfb128_info; -#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) - case POLARSSL_CIPHER_AES_128_CTR: - return &aes_128_ctr_info; - case POLARSSL_CIPHER_AES_192_CTR: - return &aes_192_ctr_info; - case POLARSSL_CIPHER_AES_256_CTR: - return &aes_256_ctr_info; -#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ - -#endif - -#if defined(POLARSSL_CAMELLIA_C) - case POLARSSL_CIPHER_CAMELLIA_128_CBC: - return &camellia_128_cbc_info; - case POLARSSL_CIPHER_CAMELLIA_192_CBC: - return &camellia_192_cbc_info; - case POLARSSL_CIPHER_CAMELLIA_256_CBC: - return &camellia_256_cbc_info; - -#if defined(POLARSSL_CIPHER_MODE_CFB) - case POLARSSL_CIPHER_CAMELLIA_128_CFB128: - return &camellia_128_cfb128_info; - case POLARSSL_CIPHER_CAMELLIA_192_CFB128: - return &camellia_192_cfb128_info; - case POLARSSL_CIPHER_CAMELLIA_256_CFB128: - return &camellia_256_cfb128_info; -#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) - case POLARSSL_CIPHER_CAMELLIA_128_CTR: - return &camellia_128_ctr_info; - case POLARSSL_CIPHER_CAMELLIA_192_CTR: - return &camellia_192_ctr_info; - case POLARSSL_CIPHER_CAMELLIA_256_CTR: - return &camellia_256_ctr_info; -#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ - -#endif - -#if defined(POLARSSL_DES_C) - case POLARSSL_CIPHER_DES_CBC: - return &des_cbc_info; - case POLARSSL_CIPHER_DES_EDE_CBC: - return &des_ede_cbc_info; - case POLARSSL_CIPHER_DES_EDE3_CBC: - return &des_ede3_cbc_info; -#endif - -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - case POLARSSL_CIPHER_NULL: - return &null_cipher_info; -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - - default: - return NULL; - } -} - -const cipher_info_t *cipher_info_from_string( const char *cipher_name ) -{ - if( NULL == cipher_name ) - return NULL; - - /* Get the appropriate cipher information */ -#if defined(POLARSSL_CAMELLIA_C) - if( !strcasecmp( "CAMELLIA-128-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CBC ); - if( !strcasecmp( "CAMELLIA-192-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CBC ); - if( !strcasecmp( "CAMELLIA-256-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CBC ); - -#if defined(POLARSSL_CIPHER_MODE_CFB) - if( !strcasecmp( "CAMELLIA-128-CFB128", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CFB128 ); - if( !strcasecmp( "CAMELLIA-192-CFB128", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CFB128 ); - if( !strcasecmp( "CAMELLIA-256-CFB128", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CFB128 ); -#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) - if( !strcasecmp( "CAMELLIA-128-CTR", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CTR ); - if( !strcasecmp( "CAMELLIA-192-CTR", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CTR ); - if( !strcasecmp( "CAMELLIA-256-CTR", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CTR ); -#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ -#endif - -#if defined(POLARSSL_AES_C) - if( !strcasecmp( "AES-128-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CBC ); - if( !strcasecmp( "AES-192-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CBC ); - if( !strcasecmp( "AES-256-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CBC ); - -#if defined(POLARSSL_CIPHER_MODE_CFB) - if( !strcasecmp( "AES-128-CFB128", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CFB128 ); - if( !strcasecmp( "AES-192-CFB128", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CFB128 ); - if( !strcasecmp( "AES-256-CFB128", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CFB128 ); -#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) - if( !strcasecmp( "AES-128-CTR", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CTR ); - if( !strcasecmp( "AES-192-CTR", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CTR ); - if( !strcasecmp( "AES-256-CTR", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CTR ); -#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ -#endif - -#if defined(POLARSSL_DES_C) - if( !strcasecmp( "DES-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_DES_CBC ); - if( !strcasecmp( "DES-EDE-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE_CBC ); - if( !strcasecmp( "DES-EDE3-CBC", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE3_CBC ); -#endif - -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( !strcasecmp( "NULL", cipher_name ) ) - return cipher_info_from_type( POLARSSL_CIPHER_NULL ); -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - - return NULL; -} - -int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info ) -{ - if( NULL == cipher_info || NULL == ctx ) - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - - memset( ctx, 0, sizeof( cipher_context_t ) ); - - if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) - return POLARSSL_ERR_CIPHER_ALLOC_FAILED; - - ctx->cipher_info = cipher_info; - - return 0; -} - -int cipher_free_ctx( cipher_context_t *ctx ) -{ - if( ctx == NULL || ctx->cipher_info == NULL ) - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - - ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); - - return 0; -} - -int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, - int key_length, const operation_t operation ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - - ctx->key_length = key_length; - ctx->operation = operation; - -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( ctx->cipher_info->mode == POLARSSL_MODE_NULL ) - return 0; -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - - /* - * For CFB128 and CTR mode always use the encryption key schedule - */ - if( POLARSSL_ENCRYPT == operation || - POLARSSL_MODE_CFB128 == ctx->cipher_info->mode || - POLARSSL_MODE_CTR == ctx->cipher_info->mode ) - { - return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, - ctx->key_length ); - } - - if( POLARSSL_DECRYPT == operation ) - return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, - ctx->key_length ); - - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; -} - -int cipher_reset( cipher_context_t *ctx, const unsigned char *iv ) -{ - if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - - ctx->unprocessed_len = 0; - - memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) ); - - return 0; -} - -int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen ) -{ - int ret; - size_t copy_len = 0; - - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen || - input == output ) - { - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - } - - *olen = 0; - -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( ctx->cipher_info->mode == POLARSSL_MODE_NULL ) - { - memcpy( output, input, ilen ); - *olen = ilen; - return 0; - } -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - - if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ) - { - /* - * If there is not enough data for a full block, cache it. - */ - if( ( ctx->operation == POLARSSL_DECRYPT && - ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) || - ( ctx->operation == POLARSSL_ENCRYPT && - ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) ) - { - memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, - ilen ); - - ctx->unprocessed_len += ilen; - return 0; - } - - /* - * Process cached data first - */ - if( ctx->unprocessed_len != 0 ) - { - copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len; - - memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, - copy_len ); - - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, cipher_get_block_size( ctx ), ctx->iv, - ctx->unprocessed_data, output ) ) ) - { - return ret; - } - - *olen += cipher_get_block_size( ctx ); - output += cipher_get_block_size( ctx ); - ctx->unprocessed_len = 0; - - input += copy_len; - ilen -= copy_len; - } - - /* - * Cache final, incomplete block - */ - if( 0 != ilen ) - { - copy_len = ilen % cipher_get_block_size( ctx ); - if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT ) - copy_len = cipher_get_block_size(ctx); - - memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), - copy_len ); - - ctx->unprocessed_len += copy_len; - ilen -= copy_len; - } - - /* - * Process remaining full blocks - */ - if( ilen ) - { - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, ilen, ctx->iv, input, output ) ) ) - { - return ret; - } - *olen += ilen; - } - - return 0; - } - - if( ctx->cipher_info->mode == POLARSSL_MODE_CFB128 ) - { - if( 0 != ( ret = ctx->cipher_info->base->cfb128_func( ctx->cipher_ctx, - ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, - input, output ) ) ) - { - return ret; - } - - *olen = ilen; - - return 0; - } - - if( ctx->cipher_info->mode == POLARSSL_MODE_CTR ) - { - if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, - ilen, &ctx->unprocessed_len, ctx->iv, - ctx->unprocessed_data, input, output ) ) ) - { - return ret; - } - - *olen = ilen; - - return 0; - } - - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; -} - -static void add_pkcs_padding( unsigned char *output, size_t output_len, - size_t data_len ) -{ - size_t padding_len = output_len - data_len; - unsigned char i = 0; - - for( i = 0; i < padding_len; i++ ) - output[data_len + i] = (unsigned char) padding_len; -} - -static int get_pkcs_padding( unsigned char *input, unsigned int input_len, - size_t *data_len) -{ - unsigned int i, padding_len = 0; - - if( NULL == input || NULL == data_len ) - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - - padding_len = input[input_len - 1]; - - if( padding_len > input_len ) - return POLARSSL_ERR_CIPHER_INVALID_PADDING; - - for( i = input_len - padding_len; i < input_len; i++ ) - if( input[i] != padding_len ) - return POLARSSL_ERR_CIPHER_INVALID_PADDING; - - *data_len = input_len - padding_len; - - return 0; -} - -int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen) -{ - int ret = 0; - - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - - *olen = 0; - - if( POLARSSL_MODE_CFB128 == ctx->cipher_info->mode || - POLARSSL_MODE_CTR == ctx->cipher_info->mode || - POLARSSL_MODE_NULL == ctx->cipher_info->mode ) - { - return 0; - } - - if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) - { - if( POLARSSL_ENCRYPT == ctx->operation ) - { - add_pkcs_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ), - ctx->unprocessed_len ); - } - else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len ) - { - /* For decrypt operations, expect a full block */ - return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED; - } - - /* cipher block */ - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, cipher_get_block_size( ctx ), ctx->iv, - ctx->unprocessed_data, output ) ) ) - { - return ret; - } - - /* Set output size for decryption */ - if( POLARSSL_DECRYPT == ctx->operation ) - return get_pkcs_padding( output, cipher_get_block_size( ctx ), olen ); - - /* Set output size for encryption */ - *olen = cipher_get_block_size( ctx ); - return 0; - } - - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; -} - -#if defined(POLARSSL_SELF_TEST) - -#include - -#define ASSERT(x) if (!(x)) { \ - printf( "failed with %i at %s\n", value, (#x) ); \ - return( 1 ); \ -} -/* - * Checkup routine - */ - -int cipher_self_test( int verbose ) -{ - ((void) verbose); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/cipher_wrap.c b/polarssl/src/library/cipher_wrap.c deleted file mode 100644 index 99e5092..0000000 --- a/polarssl/src/library/cipher_wrap.c +++ /dev/null @@ -1,595 +0,0 @@ -/** - * \file md_wrap.c - * - * \brief Generic cipher wrapper for PolarSSL - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_CIPHER_C) - -#include "polarssl/cipher_wrap.h" - -#if defined(POLARSSL_AES_C) -#include "polarssl/aes.h" -#endif - -#if defined(POLARSSL_CAMELLIA_C) -#include "polarssl/camellia.h" -#endif - -#if defined(POLARSSL_DES_C) -#include "polarssl/des.h" -#endif - -#include - -#if defined(POLARSSL_AES_C) - -int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input, output ); -} - -int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length, - size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ -#if defined(POLARSSL_CIPHER_MODE_CFB) - return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv, input, output ); -#else - ((void) ctx); - ((void) operation); - ((void) length); - ((void) iv_off); - ((void) iv); - ((void) input); - ((void) output); - - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; -#endif -} - -int aes_crypt_ctr_wrap( void *ctx, size_t length, - size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ -#if defined(POLARSSL_CIPHER_MODE_CTR) - return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter, - stream_block, input, output ); -#else - ((void) ctx); - ((void) length); - ((void) nc_off); - ((void) nonce_counter); - ((void) stream_block); - ((void) input); - ((void) output); - - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; -#endif -} - -int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - return aes_setkey_dec( (aes_context *) ctx, key, key_length ); -} - -int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - return aes_setkey_enc( (aes_context *) ctx, key, key_length ); -} - -static void * aes_ctx_alloc( void ) -{ - return malloc( sizeof( aes_context ) ); -} - -static void aes_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const cipher_base_t aes_info = { - POLARSSL_CIPHER_ID_AES, - aes_crypt_cbc_wrap, - aes_crypt_cfb128_wrap, - aes_crypt_ctr_wrap, - aes_setkey_enc_wrap, - aes_setkey_dec_wrap, - aes_ctx_alloc, - aes_ctx_free -}; - -const cipher_info_t aes_128_cbc_info = { - POLARSSL_CIPHER_AES_128_CBC, - POLARSSL_MODE_CBC, - 128, - "AES-128-CBC", - 16, - 16, - &aes_info -}; - -const cipher_info_t aes_192_cbc_info = { - POLARSSL_CIPHER_AES_192_CBC, - POLARSSL_MODE_CBC, - 192, - "AES-192-CBC", - 16, - 16, - &aes_info -}; - -const cipher_info_t aes_256_cbc_info = { - POLARSSL_CIPHER_AES_256_CBC, - POLARSSL_MODE_CBC, - 256, - "AES-256-CBC", - 16, - 16, - &aes_info -}; - -#if defined(POLARSSL_CIPHER_MODE_CFB) -const cipher_info_t aes_128_cfb128_info = { - POLARSSL_CIPHER_AES_128_CFB128, - POLARSSL_MODE_CFB128, - 128, - "AES-128-CFB128", - 16, - 16, - &aes_info -}; - -const cipher_info_t aes_192_cfb128_info = { - POLARSSL_CIPHER_AES_192_CFB128, - POLARSSL_MODE_CFB128, - 192, - "AES-192-CFB128", - 16, - 16, - &aes_info -}; - -const cipher_info_t aes_256_cfb128_info = { - POLARSSL_CIPHER_AES_256_CFB128, - POLARSSL_MODE_CFB128, - 256, - "AES-256-CFB128", - 16, - 16, - &aes_info -}; -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -const cipher_info_t aes_128_ctr_info = { - POLARSSL_CIPHER_AES_128_CTR, - POLARSSL_MODE_CTR, - 128, - "AES-128-CTR", - 16, - 16, - &aes_info -}; - -const cipher_info_t aes_192_ctr_info = { - POLARSSL_CIPHER_AES_192_CTR, - POLARSSL_MODE_CTR, - 192, - "AES-192-CTR", - 16, - 16, - &aes_info -}; - -const cipher_info_t aes_256_ctr_info = { - POLARSSL_CIPHER_AES_256_CTR, - POLARSSL_MODE_CTR, - 256, - "AES-256-CTR", - 16, - 16, - &aes_info -}; -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -#endif - -#if defined(POLARSSL_CAMELLIA_C) - -int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv, input, output ); -} - -int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length, - size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ -#if defined(POLARSSL_CIPHER_MODE_CFB) - return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length, iv_off, iv, input, output ); -#else - ((void) ctx); - ((void) operation); - ((void) length); - ((void) iv_off); - ((void) iv); - ((void) input); - ((void) output); - - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; -#endif -} - -int camellia_crypt_ctr_wrap( void *ctx, size_t length, - size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ -#if defined(POLARSSL_CIPHER_MODE_CTR) - return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off, nonce_counter, - stream_block, input, output ); -#else - ((void) ctx); - ((void) length); - ((void) nc_off); - ((void) nonce_counter); - ((void) stream_block); - ((void) input); - ((void) output); - - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; -#endif -} - -int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - return camellia_setkey_dec( (camellia_context *) ctx, key, key_length ); -} - -int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - return camellia_setkey_enc( (camellia_context *) ctx, key, key_length ); -} - -static void * camellia_ctx_alloc( void ) -{ - return malloc( sizeof( camellia_context ) ); -} - -static void camellia_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const cipher_base_t camellia_info = { - POLARSSL_CIPHER_ID_CAMELLIA, - camellia_crypt_cbc_wrap, - camellia_crypt_cfb128_wrap, - camellia_crypt_ctr_wrap, - camellia_setkey_enc_wrap, - camellia_setkey_dec_wrap, - camellia_ctx_alloc, - camellia_ctx_free -}; - -const cipher_info_t camellia_128_cbc_info = { - POLARSSL_CIPHER_CAMELLIA_128_CBC, - POLARSSL_MODE_CBC, - 128, - "CAMELLIA-128-CBC", - 16, - 16, - &camellia_info -}; - -const cipher_info_t camellia_192_cbc_info = { - POLARSSL_CIPHER_CAMELLIA_192_CBC, - POLARSSL_MODE_CBC, - 192, - "CAMELLIA-192-CBC", - 16, - 16, - &camellia_info -}; - -const cipher_info_t camellia_256_cbc_info = { - POLARSSL_CIPHER_CAMELLIA_256_CBC, - POLARSSL_MODE_CBC, - 256, - "CAMELLIA-256-CBC", - 16, - 16, - &camellia_info -}; - -#if defined(POLARSSL_CIPHER_MODE_CFB) -const cipher_info_t camellia_128_cfb128_info = { - POLARSSL_CIPHER_CAMELLIA_128_CFB128, - POLARSSL_MODE_CFB128, - 128, - "CAMELLIA-128-CFB128", - 16, - 16, - &camellia_info -}; - -const cipher_info_t camellia_192_cfb128_info = { - POLARSSL_CIPHER_CAMELLIA_192_CFB128, - POLARSSL_MODE_CFB128, - 192, - "CAMELLIA-192-CFB128", - 16, - 16, - &camellia_info -}; - -const cipher_info_t camellia_256_cfb128_info = { - POLARSSL_CIPHER_CAMELLIA_256_CFB128, - POLARSSL_MODE_CFB128, - 256, - "CAMELLIA-256-CFB128", - 16, - 16, - &camellia_info -}; -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -const cipher_info_t camellia_128_ctr_info = { - POLARSSL_CIPHER_CAMELLIA_128_CTR, - POLARSSL_MODE_CTR, - 128, - "CAMELLIA-128-CTR", - 16, - 16, - &camellia_info -}; - -const cipher_info_t camellia_192_ctr_info = { - POLARSSL_CIPHER_CAMELLIA_192_CTR, - POLARSSL_MODE_CTR, - 192, - "CAMELLIA-192-CTR", - 16, - 16, - &camellia_info -}; - -const cipher_info_t camellia_256_ctr_info = { - POLARSSL_CIPHER_CAMELLIA_256_CTR, - POLARSSL_MODE_CTR, - 256, - "CAMELLIA-256-CTR", - 16, - 16, - &camellia_info -}; -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -#endif - -#if defined(POLARSSL_DES_C) - -int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input, output ); -} - -int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input, output ); -} - -int des_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length, - size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - ((void) ctx); - ((void) operation); - ((void) length); - ((void) iv_off); - ((void) iv); - ((void) input); - ((void) output); - - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; -} - -int des_crypt_ctr_wrap( void *ctx, size_t length, - size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ - ((void) ctx); - ((void) length); - ((void) nc_off); - ((void) nonce_counter); - ((void) stream_block); - ((void) input); - ((void) output); - - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; -} - - -int des_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - ((void) key_length); - - return des_setkey_dec( (des_context *) ctx, key ); -} - -int des_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - ((void) key_length); - - return des_setkey_enc( (des_context *) ctx, key ); -} - -int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - ((void) key_length); - - return des3_set2key_dec( (des3_context *) ctx, key ); -} - -int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - ((void) key_length); - - return des3_set2key_enc( (des3_context *) ctx, key ); -} - -int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - ((void) key_length); - - return des3_set3key_dec( (des3_context *) ctx, key ); -} - -int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - ((void) key_length); - - return des3_set3key_enc( (des3_context *) ctx, key ); -} - -static void * des_ctx_alloc( void ) -{ - return malloc( sizeof( des_context ) ); -} - -static void * des3_ctx_alloc( void ) -{ - return malloc( sizeof( des3_context ) ); -} - -static void des_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const cipher_base_t des_info = { - POLARSSL_CIPHER_ID_DES, - des_crypt_cbc_wrap, - des_crypt_cfb128_wrap, - des_crypt_ctr_wrap, - des_setkey_enc_wrap, - des_setkey_dec_wrap, - des_ctx_alloc, - des_ctx_free -}; - -const cipher_info_t des_cbc_info = { - POLARSSL_CIPHER_DES_CBC, - POLARSSL_MODE_CBC, - POLARSSL_KEY_LENGTH_DES, - "DES-CBC", - 8, - 8, - &des_info -}; - -const cipher_base_t des_ede_info = { - POLARSSL_CIPHER_ID_DES, - des3_crypt_cbc_wrap, - des_crypt_cfb128_wrap, - des_crypt_ctr_wrap, - des3_set2key_enc_wrap, - des3_set2key_dec_wrap, - des3_ctx_alloc, - des_ctx_free -}; - -const cipher_info_t des_ede_cbc_info = { - POLARSSL_CIPHER_DES_EDE_CBC, - POLARSSL_MODE_CBC, - POLARSSL_KEY_LENGTH_DES_EDE, - "DES-EDE-CBC", - 16, - 16, - &des_ede_info -}; - -const cipher_base_t des_ede3_info = { - POLARSSL_CIPHER_ID_DES, - des3_crypt_cbc_wrap, - des_crypt_cfb128_wrap, - des_crypt_ctr_wrap, - des3_set3key_enc_wrap, - des3_set3key_dec_wrap, - des3_ctx_alloc, - des_ctx_free -}; - -const cipher_info_t des_ede3_cbc_info = { - POLARSSL_CIPHER_DES_EDE3_CBC, - POLARSSL_MODE_CBC, - POLARSSL_KEY_LENGTH_DES_EDE3, - "DES-EDE3-CBC", - 8, - 8, - &des_ede3_info -}; -#endif - -#if defined(POLARSSL_CIPHER_NULL_CIPHER) -static void * null_ctx_alloc( void ) -{ - return (void *) 1; -} - - -static void null_ctx_free( void *ctx ) -{ - ((void) ctx); -} - -const cipher_base_t null_base_info = { - POLARSSL_CIPHER_ID_NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - null_ctx_alloc, - null_ctx_free -}; - -const cipher_info_t null_cipher_info = { - POLARSSL_CIPHER_NULL, - POLARSSL_MODE_NULL, - 0, - "NULL", - 1, - 1, - &null_base_info -}; -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - -#endif diff --git a/polarssl/src/library/ctr_drbg.c b/polarssl/src/library/ctr_drbg.c deleted file mode 100644 index 1de7f05..0000000 --- a/polarssl/src/library/ctr_drbg.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The NIST SP 800-90 DRBGs are described in the following publucation. - * - * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_CTR_DRBG_C) - -#include "polarssl/ctr_drbg.h" - -#if defined(POLARSSL_FS_IO) -#include -#endif - -/* - * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST - * tests to succeed (which require known length fixed entropy) - */ -int ctr_drbg_init_entropy_len( - ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len, - size_t entropy_len ) -{ - int ret; - unsigned char key[CTR_DRBG_KEYSIZE]; - - memset( ctx, 0, sizeof(ctr_drbg_context) ); - memset( key, 0, CTR_DRBG_KEYSIZE ); - - ctx->f_entropy = f_entropy; - ctx->p_entropy = p_entropy; - - ctx->entropy_len = entropy_len; - ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL; - - /* - * Initialize with an empty key - */ - aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS ); - - if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -int ctr_drbg_init( ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ) -{ - return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len, - CTR_DRBG_ENTROPY_LEN ) ); -} - -void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance ) -{ - ctx->prediction_resistance = resistance; -} - -void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len ) -{ - ctx->entropy_len = len; -} - -void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval ) -{ - ctx->reseed_interval = interval; -} - -int block_cipher_df( unsigned char *output, - const unsigned char *data, size_t data_len ) -{ - unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16]; - unsigned char tmp[CTR_DRBG_SEEDLEN]; - unsigned char key[CTR_DRBG_KEYSIZE]; - unsigned char chain[CTR_DRBG_BLOCKSIZE]; - unsigned char *p = buf, *iv; - aes_context aes_ctx; - - int i, j, buf_len, use_len; - - memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 ); - - /* - * Construct IV (16 bytes) and S in buffer - * IV = Counter (in 32-bits) padded to 16 with zeroes - * S = Length input string (in 32-bits) || Length of output (in 32-bits) || - * data || 0x80 - * (Total is padded to a multiple of 16-bytes with zeroes) - */ - p = buf + CTR_DRBG_BLOCKSIZE; - *p++ = ( data_len >> 24 ) & 0xff; - *p++ = ( data_len >> 16 ) & 0xff; - *p++ = ( data_len >> 8 ) & 0xff; - *p++ = ( data_len ) & 0xff; - p += 3; - *p++ = CTR_DRBG_SEEDLEN; - memcpy( p, data, data_len ); - p[data_len] = 0x80; - - buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; - - for( i = 0; i < CTR_DRBG_KEYSIZE; i++ ) - key[i] = i; - - aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS ); - - /* - * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data - */ - for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) - { - p = buf; - memset( chain, 0, CTR_DRBG_BLOCKSIZE ); - use_len = buf_len; - - while( use_len > 0 ) - { - for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ ) - chain[i] ^= p[i]; - p += CTR_DRBG_BLOCKSIZE; - use_len -= CTR_DRBG_BLOCKSIZE; - - aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain ); - } - - memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE ); - - /* - * Update IV - */ - buf[3]++; - } - - /* - * Do final encryption with reduced data - */ - aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS ); - iv = tmp + CTR_DRBG_KEYSIZE; - p = output; - - for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) - { - aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv ); - memcpy( p, iv, CTR_DRBG_BLOCKSIZE ); - p += CTR_DRBG_BLOCKSIZE; - } - - return( 0 ); -} - -int ctr_drbg_update_internal( ctr_drbg_context *ctx, - const unsigned char data[CTR_DRBG_SEEDLEN] ) -{ - unsigned char tmp[CTR_DRBG_SEEDLEN]; - unsigned char *p = tmp; - int i, j; - - memset( tmp, 0, CTR_DRBG_SEEDLEN ); - - for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) - { - /* - * Increase counter - */ - for( i = CTR_DRBG_BLOCKSIZE; i >= 0; i-- ) - if( ++ctx->counter[i - 1] != 0 ) - break; - - /* - * Crypt counter block - */ - aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p ); - - p += CTR_DRBG_BLOCKSIZE; - } - - for( i = 0; i < CTR_DRBG_SEEDLEN; i++ ) - tmp[i] ^= data[i]; - - /* - * Update key and counter - */ - aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS ); - memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE ); - - return( 0 ); -} - -void ctr_drbg_update( ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) -{ - unsigned char add_input[CTR_DRBG_SEEDLEN]; - - if( add_len > 0 ) - { - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); - } -} - -int ctr_drbg_reseed( ctr_drbg_context *ctx, - const unsigned char *additional, size_t len ) -{ - unsigned char seed[CTR_DRBG_MAX_SEED_INPUT]; - size_t seedlen = 0; - - if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT ) - return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT ); - - /* - * Gather enropy_len bytes of entropy to seed state - */ - if( 0 != ctx->f_entropy( ctx->p_entropy, seed, - ctx->entropy_len ) ) - { - return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); - } - - seedlen += ctx->entropy_len; - - /* - * Add additional data - */ - if( additional && len ) - { - memcpy( seed + seedlen, additional, len ); - seedlen += len; - } - - /* - * Reduce to 384 bits - */ - block_cipher_df( seed, seed, seedlen ); - - /* - * Update state - */ - ctr_drbg_update_internal( ctx, seed ); - ctx->reseed_counter = 1; - - return( 0 ); -} - -int ctr_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, size_t add_len ) -{ - int ret = 0; - ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng; - unsigned char add_input[CTR_DRBG_SEEDLEN]; - unsigned char *p = output; - unsigned char tmp[CTR_DRBG_BLOCKSIZE]; - int i; - size_t use_len; - - if( output_len > CTR_DRBG_MAX_REQUEST ) - return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG ); - - if( add_len > CTR_DRBG_MAX_INPUT ) - return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - memset( add_input, 0, CTR_DRBG_SEEDLEN ); - - if( ctx->reseed_counter > ctx->reseed_interval || - ctx->prediction_resistance ) - { - if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) - return( ret ); - - add_len = 0; - } - - if( add_len > 0 ) - { - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); - } - - while( output_len > 0 ) - { - /* - * Increase counter - */ - for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- ) - if( ++ctx->counter[i - 1] != 0 ) - break; - - /* - * Crypt counter block - */ - aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp ); - - use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len; - /* - * Copy random block to destination - */ - memcpy( p, tmp, use_len ); - p += use_len; - output_len -= use_len; - } - - ctr_drbg_update_internal( ctx, add_input ); - - ctx->reseed_counter++; - - return( 0 ); -} - -int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) -{ - return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 ); -} - -#if defined(POLARSSL_FS_IO) -int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path ) -{ - int ret; - FILE *f; - unsigned char buf[ CTR_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "wb" ) ) == NULL ) - return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); - - if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 ) - return( ret ); - - if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT ) - { - fclose( f ); - return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); - } - - fclose( f ); - return( 0 ); -} - -int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path ) -{ - FILE *f; - size_t n; - unsigned char buf[ CTR_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > CTR_DRBG_MAX_INPUT ) - return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); - } - - ctr_drbg_update( ctx, buf, n ); - - fclose( f ); - - return( ctr_drbg_write_seed_file( ctx, path ) ); -} -#endif /* POLARSSL_FS_IO */ - -#if defined(POLARSSL_SELF_TEST) - -#include - -unsigned char entropy_source_pr[96] = - { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, - 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, - 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, - 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, - 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, - 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, - 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, - 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, - 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, - 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, - 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, - 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; - -unsigned char entropy_source_nopr[64] = - { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, - 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, - 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, - 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, - 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, - 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, - 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, - 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; - -unsigned char nonce_pers_pr[16] = - { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, - 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; - -unsigned char nonce_pers_nopr[16] = - { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, - 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; - -unsigned char result_pr[16] = - { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, - 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; - -unsigned char result_nopr[16] = - { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, - 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; - -int test_offset; -int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len ) -{ - unsigned char *p = data; - memcpy( buf, p + test_offset, len ); - test_offset += 32; - return( 0 ); -} - -/* - * Checkup routine - */ -int ctr_drbg_self_test( int verbose ) -{ - ctr_drbg_context ctx; - unsigned char buf[16]; - - /* - * Based on a NIST CTR_DRBG test vector (PR = True) - */ - if( verbose != 0 ) - printf( " CTR_DRBG (PR = TRUE) : " ); - - test_offset = 0; - if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON ); - - if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - /* - * Based on a NIST CTR_DRBG test vector (PR = FALSE) - */ - if( verbose != 0 ) - printf( " CTR_DRBG (PR = FALSE): " ); - - test_offset = 0; - if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( ctr_drbg_random( &ctx, buf, 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( ctr_drbg_random( &ctx, buf, 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( memcmp( buf, result_nopr, 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} -#endif - -#endif diff --git a/polarssl/src/library/debug.c b/polarssl/src/library/debug.c deleted file mode 100644 index 687e194..0000000 --- a/polarssl/src/library/debug.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Debugging routines - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_DEBUG_C) - -#include "polarssl/debug.h" - -#include -#include - -#if defined _MSC_VER && !defined snprintf -#define snprintf _snprintf -#endif - -#if defined _MSC_VER && !defined vsnprintf -#define vsnprintf _vsnprintf -#endif - -char *debug_fmt( const char *format, ... ) -{ - va_list argp; - static char str[512]; - int maxlen = sizeof( str ) - 1; - - va_start( argp, format ); - vsnprintf( str, maxlen, format, argp ); - va_end( argp ); - - str[maxlen] = '\0'; - return( str ); -} - -void debug_print_msg( const ssl_context *ssl, int level, - const char *file, int line, const char *text ) -{ - char str[512]; - int maxlen = sizeof( str ) - 1; - - if( ssl->f_dbg == NULL ) - return; - - snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text ); - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); -} - -void debug_print_ret( const ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret ) -{ - char str[512]; - int maxlen = sizeof( str ) - 1; - - if( ssl->f_dbg == NULL ) - return; - - snprintf( str, maxlen, "%s(%04d): %s() returned %d (0x%x)\n", - file, line, text, ret, ret ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); -} - -void debug_print_buf( const ssl_context *ssl, int level, - const char *file, int line, const char *text, - unsigned char *buf, size_t len ) -{ - char str[512]; - size_t i, maxlen = sizeof( str ) - 1; - - if( ssl->f_dbg == NULL ) - return; - - snprintf( str, maxlen, "%s(%04d): dumping '%s' (%d bytes)\n", - file, line, text, (unsigned int) len ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); - - for( i = 0; i < len; i++ ) - { - if( i >= 4096 ) - break; - - if( i % 16 == 0 ) - { - if( i > 0 ) - ssl->f_dbg( ssl->p_dbg, level, "\n" ); - - snprintf( str, maxlen, "%s(%04d): %04x: ", file, line, - (unsigned int) i ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); - } - - snprintf( str, maxlen, " %02x", (unsigned int) buf[i] ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); - } - - if( len > 0 ) - ssl->f_dbg( ssl->p_dbg, level, "\n" ); -} - -void debug_print_mpi( const ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mpi *X ) -{ - char str[512]; - int j, k, maxlen = sizeof( str ) - 1, zeros = 1; - size_t i, n; - - if( ssl->f_dbg == NULL || X == NULL ) - return; - - for( n = X->n - 1; n > 0; n-- ) - if( X->p[n] != 0 ) - break; - - for( j = ( sizeof(t_uint) << 3 ) - 1; j >= 0; j-- ) - if( ( ( X->p[n] >> j ) & 1 ) != 0 ) - break; - - snprintf( str, maxlen, "%s(%04d): value of '%s' (%lu bits) is:\n", - file, line, text, - (unsigned long) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); - - for( i = n + 1, j = 0; i > 0; i-- ) - { - if( zeros && X->p[i - 1] == 0 ) - continue; - - for( k = sizeof( t_uint ) - 1; k >= 0; k-- ) - { - if( zeros && ( ( X->p[i - 1] >> (k << 3) ) & 0xFF ) == 0 ) - continue; - else - zeros = 0; - - if( j % 16 == 0 ) - { - if( j > 0 ) - ssl->f_dbg( ssl->p_dbg, level, "\n" ); - - snprintf( str, maxlen, "%s(%04d): ", file, line ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); - } - - snprintf( str, maxlen, " %02x", (unsigned int) - ( X->p[i - 1] >> (k << 3) ) & 0xFF ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); - - j++; - } - - } - - if( zeros == 1 ) - { - snprintf( str, maxlen, "%s(%04d): ", file, line ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); - ssl->f_dbg( ssl->p_dbg, level, " 00" ); - } - - ssl->f_dbg( ssl->p_dbg, level, "\n" ); -} - -void debug_print_crt( const ssl_context *ssl, int level, - const char *file, int line, - const char *text, const x509_cert *crt ) -{ - char str[1024], prefix[64]; - int i = 0, maxlen = sizeof( prefix ) - 1; - - if( ssl->f_dbg == NULL || crt == NULL ) - return; - - snprintf( prefix, maxlen, "%s(%04d): ", file, line ); - prefix[maxlen] = '\0'; - maxlen = sizeof( str ) - 1; - - while( crt != NULL ) - { - char buf[1024]; - x509parse_cert_info( buf, sizeof( buf ) - 1, prefix, crt ); - - snprintf( str, maxlen, "%s(%04d): %s #%d:\n%s", - file, line, text, ++i, buf ); - - str[maxlen] = '\0'; - ssl->f_dbg( ssl->p_dbg, level, str ); - - debug_print_mpi( ssl, level, file, line, - "crt->rsa.N", &crt->rsa.N ); - - debug_print_mpi( ssl, level, file, line, - "crt->rsa.E", &crt->rsa.E ); - - crt = crt->next; - } -} - -#endif diff --git a/polarssl/src/library/des.c b/polarssl/src/library/des.c deleted file mode 100644 index b40baf8..0000000 --- a/polarssl/src/library/des.c +++ /dev/null @@ -1,993 +0,0 @@ -/* - * FIPS-46-3 compliant Triple-DES implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * DES, on which TDES is based, was originally designed by Horst Feistel - * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). - * - * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_DES_C) - -#include "polarssl/des.h" - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * Expanded DES S-boxes - */ -static const unsigned long SB1[64] = -{ - 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static const unsigned long SB2[64] = -{ - 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static const unsigned long SB3[64] = -{ - 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static const unsigned long SB4[64] = -{ - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static const unsigned long SB5[64] = -{ - 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static const unsigned long SB6[64] = -{ - 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static const unsigned long SB7[64] = -{ - 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static const unsigned long SB8[64] = -{ - 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - -/* - * PC1: left and right halves bit-swap - */ -static const unsigned long LHs[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const unsigned long RHs[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - -/* - * Initial Permutation macro - */ -#define DES_IP(X,Y) \ -{ \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ - X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ -} - -/* - * Final Permutation macro - */ -#define DES_FP(X,Y) \ -{ \ - X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ - Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ -} - -/* - * DES round macro - */ -#define DES_ROUND(X,Y) \ -{ \ - T = *SK++ ^ X; \ - Y ^= SB8[ (T ) & 0x3F ] ^ \ - SB6[ (T >> 8) & 0x3F ] ^ \ - SB4[ (T >> 16) & 0x3F ] ^ \ - SB2[ (T >> 24) & 0x3F ]; \ - \ - T = *SK++ ^ ((X << 28) | (X >> 4)); \ - Y ^= SB7[ (T ) & 0x3F ] ^ \ - SB5[ (T >> 8) & 0x3F ] ^ \ - SB3[ (T >> 16) & 0x3F ] ^ \ - SB1[ (T >> 24) & 0x3F ]; \ -} - -#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } - -static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, - 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, - 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, - 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, - 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, - 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, - 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, - 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, - 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, - 254 }; - -void des_key_set_parity( unsigned char key[DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < DES_KEY_SIZE; i++ ) - key[i] = odd_parity_table[key[i] / 2]; -} - -/* - * Check the given key's parity, returns 1 on failure, 0 on SUCCESS - */ -int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < DES_KEY_SIZE; i++ ) - if ( key[i] != odd_parity_table[key[i] / 2] ) - return( 1 ); - - return( 0 ); -} - -/* - * Table of weak and semi-weak keys - * - * Source: http://en.wikipedia.org/wiki/Weak_key - * - * Weak: - * Alternating ones + zeros (0x0101010101010101) - * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) - * '0xE0E0E0E0F1F1F1F1' - * '0x1F1F1F1F0E0E0E0E' - * - * Semi-weak: - * 0x011F011F010E010E and 0x1F011F010E010E01 - * 0x01E001E001F101F1 and 0xE001E001F101F101 - * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 - * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E - * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E - * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 - * - */ - -#define WEAK_KEY_COUNT 16 - -static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] = -{ - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, - { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, - { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, - - { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, - { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, - { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, - { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, - { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, - { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, - { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, - { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, - { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, - { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, - { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, - { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } -}; - -int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < WEAK_KEY_COUNT; i++ ) - if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0) - return( 1 ); - - return( 0 ); -} - -static void des_setkey( unsigned long SK[32], const unsigned char key[DES_KEY_SIZE] ) -{ - int i; - unsigned long X, Y, T; - - GET_ULONG_BE( X, key, 0 ); - GET_ULONG_BE( Y, key, 4 ); - - /* - * Permuted Choice 1 - */ - T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); - T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); - - X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) - | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) - | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) - | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); - - Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) - | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) - | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) - | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); - - X &= 0x0FFFFFFF; - Y &= 0x0FFFFFFF; - - /* - * calculate subkeys - */ - for( i = 0; i < 16; i++ ) - { - if( i < 2 || i == 8 || i == 15 ) - { - X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; - Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; - } - else - { - X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; - Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; - } - - *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) - | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) - | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) - | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) - | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) - | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) - | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) - | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) - | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) - | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) - | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); - - *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) - | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) - | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) - | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) - | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) - | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) - | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) - | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) - | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) - | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) - | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); - } -} - -/* - * DES key schedule (56-bit, encryption) - */ -int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ) -{ - des_setkey( ctx->sk, key ); - - return( 0 ); -} - -/* - * DES key schedule (56-bit, decryption) - */ -int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ) -{ - int i; - - des_setkey( ctx->sk, key ); - - for( i = 0; i < 16; i += 2 ) - { - SWAP( ctx->sk[i ], ctx->sk[30 - i] ); - SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); - } - - return( 0 ); -} - -static void des3_set2key( unsigned long esk[96], - unsigned long dsk[96], - const unsigned char key[DES_KEY_SIZE*2] ) -{ - int i; - - des_setkey( esk, key ); - des_setkey( dsk + 32, key + 8 ); - - for( i = 0; i < 32; i += 2 ) - { - dsk[i ] = esk[30 - i]; - dsk[i + 1] = esk[31 - i]; - - esk[i + 32] = dsk[62 - i]; - esk[i + 33] = dsk[63 - i]; - - esk[i + 64] = esk[i ]; - esk[i + 65] = esk[i + 1]; - - dsk[i + 64] = dsk[i ]; - dsk[i + 65] = dsk[i + 1]; - } -} - -/* - * Triple-DES key schedule (112-bit, encryption) - */ -int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ) -{ - unsigned long sk[96]; - - des3_set2key( ctx->sk, sk, key ); - memset( sk, 0, sizeof( sk ) ); - - return( 0 ); -} - -/* - * Triple-DES key schedule (112-bit, decryption) - */ -int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ) -{ - unsigned long sk[96]; - - des3_set2key( sk, ctx->sk, key ); - memset( sk, 0, sizeof( sk ) ); - - return( 0 ); -} - -static void des3_set3key( unsigned long esk[96], - unsigned long dsk[96], - const unsigned char key[24] ) -{ - int i; - - des_setkey( esk, key ); - des_setkey( dsk + 32, key + 8 ); - des_setkey( esk + 64, key + 16 ); - - for( i = 0; i < 32; i += 2 ) - { - dsk[i ] = esk[94 - i]; - dsk[i + 1] = esk[95 - i]; - - esk[i + 32] = dsk[62 - i]; - esk[i + 33] = dsk[63 - i]; - - dsk[i + 64] = esk[30 - i]; - dsk[i + 65] = esk[31 - i]; - } -} - -/* - * Triple-DES key schedule (168-bit, encryption) - */ -int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ) -{ - unsigned long sk[96]; - - des3_set3key( ctx->sk, sk, key ); - memset( sk, 0, sizeof( sk ) ); - - return( 0 ); -} - -/* - * Triple-DES key schedule (168-bit, decryption) - */ -int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ) -{ - unsigned long sk[96]; - - des3_set3key( sk, ctx->sk, key ); - memset( sk, 0, sizeof( sk ) ); - - return( 0 ); -} - -/* - * DES-ECB block encryption/decryption - */ -int des_crypt_ecb( des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - unsigned long X, Y, T, *SK; - - SK = ctx->sk; - - GET_ULONG_BE( X, input, 0 ); - GET_ULONG_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_ULONG_BE( Y, output, 0 ); - PUT_ULONG_BE( X, output, 4 ); - - return( 0 ); -} - -/* - * DES-CBC buffer encryption/decryption - */ -int des_crypt_cbc( des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH ); - - if( mode == DES_ENCRYPT ) - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - des_crypt_ecb( ctx, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else /* DES_DECRYPT */ - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - des_crypt_ecb( ctx, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} - -/* - * 3DES-ECB block encryption/decryption - */ -int des3_crypt_ecb( des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - unsigned long X, Y, T, *SK; - - SK = ctx->sk; - - GET_ULONG_BE( X, input, 0 ); - GET_ULONG_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( X, Y ); - DES_ROUND( Y, X ); - } - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_ULONG_BE( Y, output, 0 ); - PUT_ULONG_BE( X, output, 4 ); - - return( 0 ); -} - -/* - * 3DES-CBC buffer encryption/decryption - */ -int des3_crypt_cbc( des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH ); - - if( mode == DES_ENCRYPT ) - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - des3_crypt_ecb( ctx, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else /* DES_DECRYPT */ - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - des3_crypt_ecb( ctx, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include - -/* - * DES and 3DES test vectors from: - * - * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip - */ -static const unsigned char des3_test_keys[24] = -{ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, - 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 -}; - -static const unsigned char des3_test_iv[8] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, -}; - -static const unsigned char des3_test_buf[8] = -{ - 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 -}; - -static const unsigned char des3_test_ecb_dec[3][8] = -{ - { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, - { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, - { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } -}; - -static const unsigned char des3_test_ecb_enc[3][8] = -{ - { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, - { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, - { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } -}; - -static const unsigned char des3_test_cbc_dec[3][8] = -{ - { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, - { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, - { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } -}; - -static const unsigned char des3_test_cbc_enc[3][8] = -{ - { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, - { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, - { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } -}; - -/* - * Checkup routine - */ -int des_self_test( int verbose ) -{ - int i, j, u, v; - des_context ctx; - des3_context ctx3; - unsigned char key[24]; - unsigned char buf[8]; - unsigned char prv[8]; - unsigned char iv[8]; - - memset( key, 0, 24 ); - - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " DES%c-ECB-%3d (%s): ", - ( u == 0 ) ? ' ' : '3', 56 + u * 56, - ( v == DES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( buf, des3_test_buf, 8 ); - - switch( i ) - { - case 0: - des_setkey_dec( &ctx, (unsigned char *) des3_test_keys ); - break; - - case 1: - des_setkey_enc( &ctx, (unsigned char *) des3_test_keys ); - break; - - case 2: - des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys ); - break; - - case 3: - des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys ); - break; - - case 4: - des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys ); - break; - - case 5: - des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys ); - break; - - default: - return( 1 ); - } - - for( j = 0; j < 10000; j++ ) - { - if( u == 0 ) - des_crypt_ecb( &ctx, buf, buf ); - else - des3_crypt_ecb( &ctx3, buf, buf ); - } - - if( ( v == DES_DECRYPT && - memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || - ( v != DES_DECRYPT && - memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " DES%c-CBC-%3d (%s): ", - ( u == 0 ) ? ' ' : '3', 56 + u * 56, - ( v == DES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, des3_test_iv, 8 ); - memcpy( prv, des3_test_iv, 8 ); - memcpy( buf, des3_test_buf, 8 ); - - switch( i ) - { - case 0: - des_setkey_dec( &ctx, (unsigned char *) des3_test_keys ); - break; - - case 1: - des_setkey_enc( &ctx, (unsigned char *) des3_test_keys ); - break; - - case 2: - des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys ); - break; - - case 3: - des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys ); - break; - - case 4: - des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys ); - break; - - case 5: - des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys ); - break; - - default: - return( 1 ); - } - - if( v == DES_DECRYPT ) - { - for( j = 0; j < 10000; j++ ) - { - if( u == 0 ) - des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); - else - des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); - } - } - else - { - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[8]; - - if( u == 0 ) - des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); - else - des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); - - memcpy( tmp, prv, 8 ); - memcpy( prv, buf, 8 ); - memcpy( buf, tmp, 8 ); - } - - memcpy( buf, prv, 8 ); - } - - if( ( v == DES_DECRYPT && - memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || - ( v != DES_DECRYPT && - memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/dhm.c b/polarssl/src/library/dhm.c deleted file mode 100644 index 4a59571..0000000 --- a/polarssl/src/library/dhm.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Diffie-Hellman-Merkle key exchange - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * Reference: - * - * http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12) - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_DHM_C) - -#include "polarssl/dhm.h" - -/* - * helper to validate the mpi size and import it - */ -static int dhm_read_bignum( mpi *X, - unsigned char **p, - const unsigned char *end ) -{ - int ret, n; - - if( end - *p < 2 ) - return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); - - n = ( (*p)[0] << 8 ) | (*p)[1]; - (*p) += 2; - - if( (int)( end - *p ) < n ) - return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); - - if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 ) - return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED + ret ); - - (*p) += n; - - return( 0 ); -} - -/* - * Verify sanity of parameter with regards to P - * - * Parameter should be: 2 <= public_param <= P - 2 - * - * For more information on the attack, see: - * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf - * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 - */ -static int dhm_check_range( const mpi *param, const mpi *P ) -{ - mpi L, U; - int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA; - - mpi_init( &L ); mpi_init( &U ); - mpi_lset( &L, 2 ); - mpi_sub_int( &U, P, 2 ); - - if( mpi_cmp_mpi( param, &L ) >= 0 && - mpi_cmp_mpi( param, &U ) <= 0 ) - { - ret = 0; - } - - mpi_free( &L ); mpi_free( &U ); - - return( ret ); -} - -/* - * Parse the ServerKeyExchange parameters - */ -int dhm_read_params( dhm_context *ctx, - unsigned char **p, - const unsigned char *end ) -{ - int ret; - - memset( ctx, 0, sizeof( dhm_context ) ); - - if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || - ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || - ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) - return( ret ); - - if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) - return( ret ); - - ctx->len = mpi_size( &ctx->P ); - - if( end - *p < 2 ) - return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); - - return( 0 ); -} - -/* - * Setup and write the ServerKeyExchange parameters - */ -int dhm_make_params( dhm_context *ctx, int x_size, - unsigned char *output, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count = 0; - size_t n1, n2, n3; - unsigned char *p; - - /* - * Generate X as large as possible ( < P ) - */ - do - { - mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); - - while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) - mpi_shift_r( &ctx->X, 1 ); - - if( count++ > 10 ) - return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED ); - } - while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); - - /* - * Calculate GX = G^X mod P - */ - MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, - &ctx->P , &ctx->RP ) ); - - if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) - return( ret ); - - /* - * export P, G, GX - */ -#define DHM_MPI_EXPORT(X,n) \ - MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \ - *p++ = (unsigned char)( n >> 8 ); \ - *p++ = (unsigned char)( n ); p += n; - - n1 = mpi_size( &ctx->P ); - n2 = mpi_size( &ctx->G ); - n3 = mpi_size( &ctx->GX ); - - p = output; - DHM_MPI_EXPORT( &ctx->P , n1 ); - DHM_MPI_EXPORT( &ctx->G , n2 ); - DHM_MPI_EXPORT( &ctx->GX, n3 ); - - *olen = p - output; - - ctx->len = n1; - -cleanup: - - if( ret != 0 ) - return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret ); - - return( 0 ); -} - -/* - * Import the peer's public value G^Y - */ -int dhm_read_public( dhm_context *ctx, - const unsigned char *input, size_t ilen ) -{ - int ret; - - if( ctx == NULL || ilen < 1 || ilen > ctx->len ) - return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); - - if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) - return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Create own private value X and export G^X - */ -int dhm_make_public( dhm_context *ctx, int x_size, - unsigned char *output, size_t olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count = 0; - - if( ctx == NULL || olen < 1 || olen > ctx->len ) - return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); - - /* - * generate X and calculate GX = G^X mod P - */ - do - { - mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); - - while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) - mpi_shift_r( &ctx->X, 1 ); - - if( count++ > 10 ) - return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED ); - } - while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); - - MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, - &ctx->P , &ctx->RP ) ); - - if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) - return( ret ); - - MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) ); - -cleanup: - - if( ret != 0 ) - return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Derive and export the shared secret (G^Y)^X mod P - */ -int dhm_calc_secret( dhm_context *ctx, - unsigned char *output, size_t *olen ) -{ - int ret; - - if( ctx == NULL || *olen < ctx->len ) - return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); - - MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X, - &ctx->P, &ctx->RP ) ); - - if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) - return( ret ); - - *olen = mpi_size( &ctx->K ); - - MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) ); - -cleanup: - - if( ret != 0 ) - return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret ); - - return( 0 ); -} - -/* - * Free the components of a DHM key - */ -void dhm_free( dhm_context *ctx ) -{ - mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY ); - mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G ); - mpi_free( &ctx->P ); -} - -#if defined(POLARSSL_SELF_TEST) - -/* - * Checkup routine - */ -int dhm_self_test( int verbose ) -{ - return( verbose++ ); -} - -#endif - -#endif diff --git a/polarssl/src/library/entropy.c b/polarssl/src/library/entropy.c deleted file mode 100644 index 9662454..0000000 --- a/polarssl/src/library/entropy.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Entropy accumulator implementation - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_ENTROPY_C) - -#include "polarssl/entropy.h" -#include "polarssl/entropy_poll.h" - -#if defined(POLARSSL_HAVEGE_C) -#include "polarssl/havege.h" -#endif - -#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ - -void entropy_init( entropy_context *ctx ) -{ - memset( ctx, 0, sizeof(entropy_context) ); - - sha4_starts( &ctx->accumulator, 0 ); -#if defined(POLARSSL_HAVEGE_C) - havege_init( &ctx->havege_data ); -#endif - -#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) -#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) - entropy_add_source( ctx, platform_entropy_poll, NULL, - ENTROPY_MIN_PLATFORM ); -#endif -#if defined(POLARSSL_TIMING_C) - entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK ); -#endif -#if defined(POLARSSL_HAVEGE_C) - entropy_add_source( ctx, havege_poll, &ctx->havege_data, - ENTROPY_MIN_HAVEGE ); -#endif -#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ -} - -int entropy_add_source( entropy_context *ctx, - f_source_ptr f_source, void *p_source, - size_t threshold ) -{ - int index = ctx->source_count; - - if( index >= ENTROPY_MAX_SOURCES ) - return( POLARSSL_ERR_ENTROPY_MAX_SOURCES ); - - ctx->source[index].f_source = f_source; - ctx->source[index].p_source = p_source; - ctx->source[index].threshold = threshold; - - ctx->source_count++; - - return( 0 ); -} - -/* - * Entropy accumulator update - */ -int entropy_update( entropy_context *ctx, unsigned char source_id, - const unsigned char *data, size_t len ) -{ - unsigned char header[2]; - unsigned char tmp[ENTROPY_BLOCK_SIZE]; - size_t use_len = len; - const unsigned char *p = data; - - if( use_len > ENTROPY_BLOCK_SIZE ) - { - sha4( data, len, tmp, 0 ); - - p = tmp; - use_len = ENTROPY_BLOCK_SIZE; - } - - header[0] = source_id; - header[1] = use_len & 0xFF; - - sha4_update( &ctx->accumulator, header, 2 ); - sha4_update( &ctx->accumulator, p, use_len ); - - return( 0 ); -} - -int entropy_update_manual( entropy_context *ctx, - const unsigned char *data, size_t len ) -{ - return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len ); -} - -/* - * Run through the different sources to add entropy to our accumulator - */ -int entropy_gather( entropy_context *ctx ) -{ - int ret, i; - unsigned char buf[ENTROPY_MAX_GATHER]; - size_t olen; - - if( ctx->source_count == 0 ) - return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED ); - - /* - * Run through our entropy sources - */ - for( i = 0; i < ctx->source_count; i++ ) - { - olen = 0; - if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, - buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 ) - { - return( ret ); - } - - /* - * Add if we actually gathered something - */ - if( olen > 0 ) - { - entropy_update( ctx, (unsigned char) i, buf, olen ); - ctx->source[i].size += olen; - } - } - - return( 0 ); -} - -int entropy_func( void *data, unsigned char *output, size_t len ) -{ - int ret, count = 0, i, reached; - entropy_context *ctx = (entropy_context *) data; - unsigned char buf[ENTROPY_BLOCK_SIZE]; - - if( len > ENTROPY_BLOCK_SIZE ) - return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); - - /* - * Always gather extra entropy before a call - */ - do - { - if( count++ > ENTROPY_MAX_LOOP ) - return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); - - if( ( ret = entropy_gather( ctx ) ) != 0 ) - return( ret ); - - reached = 0; - - for( i = 0; i < ctx->source_count; i++ ) - if( ctx->source[i].size >= ctx->source[i].threshold ) - reached++; - } - while( reached != ctx->source_count ); - - memset( buf, 0, ENTROPY_BLOCK_SIZE ); - - sha4_finish( &ctx->accumulator, buf ); - - /* - * Perform second SHA-512 on entropy - */ - sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); - - /* - * Reset accumulator and counters and recycle existing entropy - */ - memset( &ctx->accumulator, 0, sizeof( sha4_context ) ); - sha4_starts( &ctx->accumulator, 0 ); - sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); - - for( i = 0; i < ctx->source_count; i++ ) - ctx->source[i].size = 0; - - memcpy( output, buf, len ); - - return( 0 ); -} - -#endif diff --git a/polarssl/src/library/entropy_poll.c b/polarssl/src/library/entropy_poll.c deleted file mode 100644 index a0c9b7b..0000000 --- a/polarssl/src/library/entropy_poll.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_ENTROPY_C) - -#include "polarssl/entropy.h" -#include "polarssl/entropy_poll.h" - -#if defined(POLARSSL_TIMING_C) -#include "polarssl/timing.h" -#endif -#if defined(POLARSSL_HAVEGE_C) -#include "polarssl/havege.h" -#endif - -#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) -#if defined(_WIN32) - -#include -#if !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0400 -#endif -#include - -int platform_entropy_poll( void *data, unsigned char *output, size_t len, - size_t *olen ) -{ - HCRYPTPROV provider; - ((void) data); - *olen = 0; - - if( CryptAcquireContext( &provider, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) - { - return POLARSSL_ERR_ENTROPY_SOURCE_FAILED; - } - - if( CryptGenRandom( provider, len, output ) == FALSE ) - return POLARSSL_ERR_ENTROPY_SOURCE_FAILED; - - CryptReleaseContext( provider, 0 ); - *olen = len; - - return( 0 ); -} -#else - -#include - -int platform_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - FILE *file; - size_t ret; - ((void) data); - - *olen = 0; - - file = fopen( "/dev/urandom", "rb" ); - if( file == NULL ) - return POLARSSL_ERR_ENTROPY_SOURCE_FAILED; - - ret = fread( output, 1, len, file ); - if( ret != len ) - { - fclose( file ); - return POLARSSL_ERR_ENTROPY_SOURCE_FAILED; - } - - fclose( file ); - *olen = len; - - return( 0 ); -} -#endif -#endif - -#if defined(POLARSSL_TIMING_C) -int hardclock_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - unsigned long timer = hardclock(); - ((void) data); - *olen = 0; - - if( len < sizeof(unsigned long) ) - return( 0 ); - - memcpy( output, &timer, sizeof(unsigned long) ); - *olen = sizeof(unsigned long); - - return( 0 ); -} -#endif - -#if defined(POLARSSL_HAVEGE_C) -int havege_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - havege_state *hs = (havege_state *) data; - *olen = 0; - - if( havege_random( hs, output, len ) != 0 ) - return POLARSSL_ERR_ENTROPY_SOURCE_FAILED; - - *olen = len; - - return( 0 ); -} -#endif - -#endif /* POLARSSL_ENTROPY_C */ diff --git a/polarssl/src/library/error.c b/polarssl/src/library/error.c deleted file mode 100644 index 61ff9c7..0000000 --- a/polarssl/src/library/error.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Error message information - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_ERROR_C) - -#if defined(POLARSSL_AES_C) -#include "polarssl/aes.h" -#endif - -#if defined(POLARSSL_BASE64_C) -#include "polarssl/base64.h" -#endif - -#if defined(POLARSSL_BIGNUM_C) -#include "polarssl/bignum.h" -#endif - -#if defined(POLARSSL_CAMELLIA_C) -#include "polarssl/camellia.h" -#endif - -#if defined(POLARSSL_CIPHER_C) -#include "polarssl/cipher.h" -#endif - -#if defined(POLARSSL_CTR_DRBG_C) -#include "polarssl/ctr_drbg.h" -#endif - -#if defined(POLARSSL_DES_C) -#include "polarssl/des.h" -#endif - -#if defined(POLARSSL_DHM_C) -#include "polarssl/dhm.h" -#endif - -#if defined(POLARSSL_ENTROPY_C) -#include "polarssl/entropy.h" -#endif - -#if defined(POLARSSL_GCM_C) -#include "polarssl/gcm.h" -#endif - -#if defined(POLARSSL_MD_C) -#include "polarssl/md.h" -#endif - -#if defined(POLARSSL_MD2_C) -#include "polarssl/md2.h" -#endif - -#if defined(POLARSSL_MD4_C) -#include "polarssl/md4.h" -#endif - -#if defined(POLARSSL_MD5_C) -#include "polarssl/md5.h" -#endif - -#if defined(POLARSSL_NET_C) -#include "polarssl/net.h" -#endif - -#if defined(POLARSSL_PADLOCK_C) -#include "polarssl/padlock.h" -#endif - -#if defined(POLARSSL_PEM_C) -#include "polarssl/pem.h" -#endif - -#if defined(POLARSSL_RSA_C) -#include "polarssl/rsa.h" -#endif - -#if defined(POLARSSL_SHA1_C) -#include "polarssl/sha1.h" -#endif - -#if defined(POLARSSL_SHA2_C) -#include "polarssl/sha2.h" -#endif - -#if defined(POLARSSL_SHA4_C) -#include "polarssl/sha4.h" -#endif - -#if defined(POLARSSL_SSL_TLS_C) -#include "polarssl/ssl.h" -#endif - -#if defined(POLARSSL_X509_PARSE_C) -#include "polarssl/x509.h" -#endif - -#if defined(POLARSSL_XTEA_C) -#include "polarssl/xtea.h" -#endif - - -#include - -#if defined _MSC_VER && !defined snprintf -#define snprintf _snprintf -#endif - -void error_strerror( int ret, char *buf, size_t buflen ) -{ - size_t len; - int use_ret; - - memset( buf, 0x00, buflen ); - - if( ret < 0 ) - ret = -ret; - - if( ret & 0xFF80 ) - { - use_ret = ret & 0xFF80; - - // High level error codes - // -#if defined(POLARSSL_CIPHER_C) - if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) ) - snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); - if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) ) - snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); - if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) ) - snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); - if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) ) - snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); - if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) - snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); -#endif /* POLARSSL_CIPHER_C */ - -#if defined(POLARSSL_DHM_C) - if( use_ret == -(POLARSSL_ERR_DHM_BAD_INPUT_DATA) ) - snprintf( buf, buflen, "DHM - Bad input parameters to function" ); - if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) ) - snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); - if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) ) - snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); - if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) ) - snprintf( buf, buflen, "DHM - Reading of the public values failed" ); - if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) ) - snprintf( buf, buflen, "DHM - Makeing of the public value failed" ); - if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) ) - snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); -#endif /* POLARSSL_DHM_C */ - -#if defined(POLARSSL_MD_C) - if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) ) - snprintf( buf, buflen, "MD - The selected feature is not available" ); - if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) ) - snprintf( buf, buflen, "MD - Bad input parameters to function" ); - if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) ) - snprintf( buf, buflen, "MD - Failed to allocate memory" ); - if( use_ret == -(POLARSSL_ERR_MD_FILE_IO_ERROR) ) - snprintf( buf, buflen, "MD - Opening or reading of file failed" ); -#endif /* POLARSSL_MD_C */ - -#if defined(POLARSSL_PEM_C) - if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_PRESENT) ) - snprintf( buf, buflen, "PEM - No PEM header found" ); - if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) ) - snprintf( buf, buflen, "PEM - PEM string is not as expected" ); - if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) ) - snprintf( buf, buflen, "PEM - Failed to allocate memory" ); - if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) ) - snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); - if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) ) - snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); - if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) ) - snprintf( buf, buflen, "PEM - Private key password can't be empty" ); - if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) ) - snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); - if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) ) - snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); -#endif /* POLARSSL_PEM_C */ - -#if defined(POLARSSL_RSA_C) - if( use_ret == -(POLARSSL_ERR_RSA_BAD_INPUT_DATA) ) - snprintf( buf, buflen, "RSA - Bad input parameters to function" ); - if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) ) - snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); - if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) ) - snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); - if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) ) - snprintf( buf, buflen, "RSA - Key failed to pass the libraries validity check" ); - if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) ) - snprintf( buf, buflen, "RSA - The public key operation failed" ); - if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) ) - snprintf( buf, buflen, "RSA - The private key operation failed" ); - if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) ) - snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); - if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) ) - snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); - if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) ) - snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); -#endif /* POLARSSL_RSA_C */ - -#if defined(POLARSSL_SSL_TLS_C) - if( use_ret == -(POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE) ) - snprintf( buf, buflen, "SSL - The requested feature is not available" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) ) - snprintf( buf, buflen, "SSL - Bad input parameters to function" ); - if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) ) - snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) ) - snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); - if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) ) - snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); - if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) ) - snprintf( buf, buflen, "SSL - An unknown cipher was received" ); - if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) ) - snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); - if( use_ret == -(POLARSSL_ERR_SSL_NO_SESSION_FOUND) ) - snprintf( buf, buflen, "SSL - No session to recover was found" ); - if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) ) - snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); - if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) ) - snprintf( buf, buflen, "SSL - DESCRIPTION MISSING" ); - if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) ) - snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); - if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) ) - snprintf( buf, buflen, "SSL - The own private key is not set, but needed" ); - if( use_ret == -(POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED) ) - snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); - if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) ) - snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); - if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) ) - snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); - if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) ) - snprintf( buf, buflen, "SSL - Verification of our peer failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) ) - snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO) ) - snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) ) - snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) ) - snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) - snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) - snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) - snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) - snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP) ) - snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Read Public" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS) ) - snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) - snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) - snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) ) - snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_MALLOC_FAILED) ) - snprintf( buf, buflen, "SSL - Memory allocation failed" ); -#endif /* POLARSSL_SSL_TLS_C */ - -#if defined(POLARSSL_X509_PARSE_C) - if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) ) - snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PEM) ) - snprintf( buf, buflen, "X509 - The PEM-encoded certificate contains invalid elements, e.g. invalid character" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_FORMAT) ) - snprintf( buf, buflen, "X509 - The certificate format is invalid, e.g. different type expected" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_VERSION) ) - snprintf( buf, buflen, "X509 - The certificate version element is invalid" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SERIAL) ) - snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_ALG) ) - snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_NAME) ) - snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_DATE) ) - snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PUBKEY) ) - snprintf( buf, buflen, "X509 - The pubkey tag or value is invalid (only RSA is supported)" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE) ) - snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS) ) - snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION) ) - snprintf( buf, buflen, "X509 - Certificate or CRL has an unsupported version number" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG) ) - snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); - if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_PK_ALG) ) - snprintf( buf, buflen, "X509 - Key algorithm is unsupported (only RSA is supported)" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_SIG_MISMATCH) ) - snprintf( buf, buflen, "X509 - Certificate signature algorithms do not match. (see \\c ::x509_cert sig_oid)" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) ) - snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); - if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_VERSION) ) - snprintf( buf, buflen, "X509 - Unsupported RSA key version" ); - if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_FORMAT) ) - snprintf( buf, buflen, "X509 - Invalid RSA key tag or value" ); - if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) ) - snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); - if( use_ret == -(POLARSSL_ERR_X509_INVALID_INPUT) ) - snprintf( buf, buflen, "X509 - Input invalid" ); - if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) ) - snprintf( buf, buflen, "X509 - Allocation of memory failed" ); - if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) ) - snprintf( buf, buflen, "X509 - Read/write of file failed" ); -#endif /* POLARSSL_X509_PARSE_C */ - - if( strlen( buf ) == 0 ) - snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); - } - - use_ret = ret & ~0xFF80; - - if( use_ret == 0 ) - return; - - // If high level code is present, make a concatenation between both - // error strings. - // - len = strlen( buf ); - - if( len > 0 ) - { - if( buflen - len < 5 ) - return; - - snprintf( buf + len, buflen - len, " : " ); - - buf += len + 3; - buflen -= len + 3; - } - - // Low level error codes - // -#if defined(POLARSSL_AES_C) - if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) ) - snprintf( buf, buflen, "AES - Invalid key length" ); - if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) ) - snprintf( buf, buflen, "AES - Invalid data input length" ); -#endif /* POLARSSL_AES_C */ - -#if defined(POLARSSL_ASN1_PARSE_C) - if( use_ret == -(POLARSSL_ERR_ASN1_OUT_OF_DATA) ) - snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); - if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) ) - snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); - if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) ) - snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); - if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) ) - snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); - if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) ) - snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); - if( use_ret == -(POLARSSL_ERR_ASN1_MALLOC_FAILED) ) - snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); - if( use_ret == -(POLARSSL_ERR_ASN1_BUF_TOO_SMALL) ) - snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); -#endif /* POLARSSL_ASN1_PARSE_C */ - -#if defined(POLARSSL_BASE64_C) - if( use_ret == -(POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) ) - snprintf( buf, buflen, "BASE64 - Output buffer too small" ); - if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) ) - snprintf( buf, buflen, "BASE64 - Invalid character in input" ); -#endif /* POLARSSL_BASE64_C */ - -#if defined(POLARSSL_BIGNUM_C) - if( use_ret == -(POLARSSL_ERR_MPI_FILE_IO_ERROR) ) - snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); - if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) ) - snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); - if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) ) - snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); - if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) ) - snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); - if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) ) - snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); - if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) ) - snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); - if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) ) - snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); - if( use_ret == -(POLARSSL_ERR_MPI_MALLOC_FAILED) ) - snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); -#endif /* POLARSSL_BIGNUM_C */ - -#if defined(POLARSSL_CAMELLIA_C) - if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) - snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); - if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) - snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); -#endif /* POLARSSL_CAMELLIA_C */ - -#if defined(POLARSSL_CTR_DRBG_C) - if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) - snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); - if( use_ret == -(POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) - snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" ); - if( use_ret == -(POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG) ) - snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); - if( use_ret == -(POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR) ) - snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" ); -#endif /* POLARSSL_CTR_DRBG_C */ - -#if defined(POLARSSL_DES_C) - if( use_ret == -(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH) ) - snprintf( buf, buflen, "DES - The data input has an invalid length" ); -#endif /* POLARSSL_DES_C */ - -#if defined(POLARSSL_ENTROPY_C) - if( use_ret == -(POLARSSL_ERR_ENTROPY_SOURCE_FAILED) ) - snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); - if( use_ret == -(POLARSSL_ERR_ENTROPY_MAX_SOURCES) ) - snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); - if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) ) - snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); -#endif /* POLARSSL_ENTROPY_C */ - -#if defined(POLARSSL_GCM_C) - if( use_ret == -(POLARSSL_ERR_GCM_AUTH_FAILED) ) - snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); - if( use_ret == -(POLARSSL_ERR_GCM_BAD_INPUT) ) - snprintf( buf, buflen, "GCM - Bad input parameters to function" ); -#endif /* POLARSSL_GCM_C */ - -#if defined(POLARSSL_MD2_C) - if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) ) - snprintf( buf, buflen, "MD2 - Read/write error in file" ); -#endif /* POLARSSL_MD2_C */ - -#if defined(POLARSSL_MD4_C) - if( use_ret == -(POLARSSL_ERR_MD4_FILE_IO_ERROR) ) - snprintf( buf, buflen, "MD4 - Read/write error in file" ); -#endif /* POLARSSL_MD4_C */ - -#if defined(POLARSSL_MD5_C) - if( use_ret == -(POLARSSL_ERR_MD5_FILE_IO_ERROR) ) - snprintf( buf, buflen, "MD5 - Read/write error in file" ); -#endif /* POLARSSL_MD5_C */ - -#if defined(POLARSSL_NET_C) - if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) ) - snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); - if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) ) - snprintf( buf, buflen, "NET - Failed to open a socket" ); - if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) ) - snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); - if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) ) - snprintf( buf, buflen, "NET - Binding of the socket failed" ); - if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) ) - snprintf( buf, buflen, "NET - Could not listen on the socket" ); - if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) ) - snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); - if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) ) - snprintf( buf, buflen, "NET - Reading information from the socket failed" ); - if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) ) - snprintf( buf, buflen, "NET - Sending information through the socket failed" ); - if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) ) - snprintf( buf, buflen, "NET - Connection was reset by peer" ); - if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) ) - snprintf( buf, buflen, "NET - Connection requires a read call" ); - if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) ) - snprintf( buf, buflen, "NET - Connection requires a write call" ); -#endif /* POLARSSL_NET_C */ - -#if defined(POLARSSL_PADLOCK_C) - if( use_ret == -(POLARSSL_ERR_PADLOCK_DATA_MISALIGNED) ) - snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); -#endif /* POLARSSL_PADLOCK_C */ - -#if defined(POLARSSL_SHA1_C) - if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) ) - snprintf( buf, buflen, "SHA1 - Read/write error in file" ); -#endif /* POLARSSL_SHA1_C */ - -#if defined(POLARSSL_SHA2_C) - if( use_ret == -(POLARSSL_ERR_SHA2_FILE_IO_ERROR) ) - snprintf( buf, buflen, "SHA2 - Read/write error in file" ); -#endif /* POLARSSL_SHA2_C */ - -#if defined(POLARSSL_SHA4_C) - if( use_ret == -(POLARSSL_ERR_SHA4_FILE_IO_ERROR) ) - snprintf( buf, buflen, "SHA4 - Read/write error in file" ); -#endif /* POLARSSL_SHA4_C */ - -#if defined(POLARSSL_XTEA_C) - if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) ) - snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); -#endif /* POLARSSL_XTEA_C */ - - if( strlen( buf ) != 0 ) - return; - - snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); -} - -#endif /* POLARSSL_VERBOSE_ERROR */ diff --git a/polarssl/src/library/gcm.c b/polarssl/src/library/gcm.c deleted file mode 100644 index 616f724..0000000 --- a/polarssl/src/library/gcm.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * NIST SP800-38D compliant GCM implementation - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf - */ -#include "polarssl/config.h" - -#if defined(POLARSSL_GCM_C) - -#include "polarssl/gcm.h" - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -static void gcm_gen_table( gcm_context *ctx ) -{ - int i, j; - uint64_t hi, lo; - uint64_t vl, vh; - unsigned char h[16]; - - memset( h, 0, 16 ); - aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, h, h ); - - ctx->HH[0] = 0; - ctx->HL[0] = 0; - - GET_ULONG_BE( hi, h, 0 ); - GET_ULONG_BE( lo, h, 4 ); - vh = (uint64_t) hi << 32 | lo; - - GET_ULONG_BE( hi, h, 8 ); - GET_ULONG_BE( lo, h, 12 ); - vl = (uint64_t) hi << 32 | lo; - - ctx->HL[8] = vl; - ctx->HH[8] = vh; - - for( i = 4; i > 0; i >>= 1 ) - { - uint32_t T = ( vl & 1 ) ? 0xe1000000U : 0; - vl = ( vh << 63 ) | ( vl >> 1 ); - vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); - - ctx->HL[i] = vl; - ctx->HH[i] = vh; - } - - for (i = 2; i < 16; i <<= 1 ) - { - uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; - vh = *HiH; - vl = *HiL; - for( j = 1; j < i; j++ ) - { - HiH[j] = vh ^ ctx->HH[j]; - HiL[j] = vl ^ ctx->HL[j]; - } - } - -} - -int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize ) -{ - int ret; - - memset( ctx, 0, sizeof(gcm_context) ); - - if( ( ret = aes_setkey_enc( &ctx->aes_ctx, key, keysize ) ) != 0 ) - return( ret ); - - gcm_gen_table( ctx ); - - return( 0 ); -} - -static const uint64_t last4[16] = -{ - 0x0000, 0x1c20, 0x3840, 0x2460, - 0x7080, 0x6ca0, 0x48c0, 0x54e0, - 0xe100, 0xfd20, 0xd940, 0xc560, - 0x9180, 0x8da0, 0xa9c0, 0xb5e0 -}; - -void gcm_mult( gcm_context *ctx, const unsigned char x[16], unsigned char output[16] ) -{ - int i = 0; - unsigned char z[16]; - unsigned char v[16]; - unsigned char lo, hi, rem; - uint64_t zh, zl; - - memset( z, 0x00, 16 ); - memcpy( v, x, 16 ); - - lo = x[15] & 0xf; - hi = x[15] >> 4; - - zh = ctx->HH[lo]; - zl = ctx->HL[lo]; - - for( i = 15; i >= 0; i-- ) - { - lo = x[i] & 0xf; - hi = x[i] >> 4; - - if( i != 15 ) - { - rem = zl & 0xf; - zl = ( zh << 60 ) | ( zl >> 4 ); - zh = ( zh >> 4 ); - zh ^= (uint64_t) last4[rem] << 48; - zh ^= ctx->HH[lo]; - zl ^= ctx->HL[lo]; - - } - - rem = zl & 0xf; - zl = ( zh << 60 ) | ( zl >> 4 ); - zh = ( zh >> 4 ); - zh ^= (uint64_t) last4[rem] << 48; - zh ^= ctx->HH[hi]; - zl ^= ctx->HL[hi]; - } - - PUT_ULONG_BE( zh >> 32, output, 0 ); - PUT_ULONG_BE( zh, output, 4 ); - PUT_ULONG_BE( zl >> 32, output, 8 ); - PUT_ULONG_BE( zl, output, 12 ); -} - -int gcm_crypt_and_tag( gcm_context *ctx, - int mode, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *input, - unsigned char *output, - size_t tag_len, - unsigned char *tag ) -{ - unsigned char y[16]; - unsigned char ectr[16]; - unsigned char buf[16]; - unsigned char work_buf[16]; - size_t i; - const unsigned char *p; - unsigned char *out_p = output; - size_t use_len; - size_t orig_len = length * 8; - size_t orig_add_len = add_len * 8; - unsigned char **xor_p; - - memset( y, 0x00, 16 ); - memset( work_buf, 0x00, 16 ); - memset( tag, 0x00, tag_len ); - memset( buf, 0x00, 16 ); - - if( ( mode == GCM_DECRYPT && output <= input && ( input - output ) < 8 ) || - ( output > input && (size_t) ( output - input ) < length ) ) - { - return( POLARSSL_ERR_GCM_BAD_INPUT ); - } - - if( mode == GCM_ENCRYPT ) - xor_p = (unsigned char **) &out_p; - else - xor_p = (unsigned char **) &p; - - if( iv_len == 12 ) - { - memcpy( y, iv, iv_len ); - y[15] = 1; - } - else - { - memset( work_buf, 0x00, 16 ); - PUT_ULONG_BE( iv_len * 8, work_buf, 12 ); - - p = iv; - while( iv_len > 0 ) - { - use_len = ( iv_len < 16 ) ? iv_len : 16; - - if( use_len == 16 ) - { - ((uint64_t *) y)[0] ^= ((uint64_t *) p)[0]; - ((uint64_t *) y)[1] ^= ((uint64_t *) p)[1]; - } - else - for( i = 0; i < use_len; i++ ) - y[i] ^= p[i]; - - gcm_mult( ctx, y, y ); - - iv_len -= use_len; - p += use_len; - } - - ((uint64_t *) y)[0] ^= ((uint64_t *) work_buf)[0]; - ((uint64_t *) y)[1] ^= ((uint64_t *) work_buf)[1]; - - gcm_mult( ctx, y, y ); - } - - aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr ); - memcpy( tag, ectr, tag_len ); - - p = add; - while( add_len > 0 ) - { - use_len = ( add_len < 16 ) ? add_len : 16; - - if( use_len == 16 ) - { - ((uint64_t *) buf)[0] ^= ((uint64_t *) p)[0]; - ((uint64_t *) buf)[1] ^= ((uint64_t *) p)[1]; - } - else - for( i = 0; i < use_len; i++ ) - buf[i] ^= p[i]; - - gcm_mult( ctx, buf, buf ); - - add_len -= use_len; - p += use_len; - } - - p = input; - while( length > 0 ) - { - use_len = ( length < 16 ) ? length : 16; - - for( i = 16; i > 0; i-- ) - if( ++y[i - 1] != 0 ) - break; - - aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr ); - - if( use_len == 16 ) - { - ((uint64_t *) out_p)[0] = ((uint64_t *) ectr)[0] ^ - ((uint64_t *) p)[0]; - ((uint64_t *) buf)[0] ^= ((uint64_t *) (*xor_p))[0]; - - ((uint64_t *) out_p)[1] = ((uint64_t *) ectr)[1] ^ - ((uint64_t *) p)[1]; - ((uint64_t *) buf)[1] ^= ((uint64_t *) (*xor_p))[1]; - } - else - for( i = 0; i < use_len; i++ ) - { - out_p[i] = ectr[i] ^ p[i]; - buf[i] ^= (*xor_p)[i]; - } - - gcm_mult( ctx, buf, buf ); - - length -= use_len; - p += use_len; - out_p += use_len; - } - - if( orig_len || orig_add_len ) - { - memset( work_buf, 0x00, 16 ); - - PUT_ULONG_BE( orig_add_len , work_buf, 4 ); - PUT_ULONG_BE( orig_len , work_buf, 12 ); - - ((uint64_t *) buf)[0] ^= ((uint64_t *) work_buf)[0]; - ((uint64_t *) buf)[1] ^= ((uint64_t *) work_buf)[1]; - - gcm_mult( ctx, buf, buf ); - - if( tag_len == 16 ) - { - ((uint64_t *) tag)[0] ^= ((uint64_t *) buf)[0]; - ((uint64_t *) tag)[1] ^= ((uint64_t *) buf)[1]; - } - else - for( i = 0; i < tag_len; i++ ) - tag[i] ^= buf[i]; - } - - return( 0 ); -} - -int gcm_auth_decrypt( gcm_context *ctx, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *tag, - size_t tag_len, - const unsigned char *input, - unsigned char *output ) -{ - unsigned char check_tag[16]; - - gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag ); - - if( memcmp( check_tag, tag, tag_len ) == 0 ) - return( 0 ); - - memset( output, 0, length ); - - return( POLARSSL_ERR_GCM_AUTH_FAILED ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include - -/* - * GCM test vectors from: - * - * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip - */ -#define MAX_TESTS 6 - -int key_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 1 }; - -unsigned char key[MAX_TESTS][32] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, - 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, -}; - -size_t iv_len[MAX_TESTS] = - { 12, 12, 12, 12, 8, 60 }; - -int iv_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 2 }; - -unsigned char iv[MAX_TESTS][64] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, - 0xde, 0xca, 0xf8, 0x88 }, - { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, - 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, - 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, - 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, - 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, - 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, - 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, - 0xa6, 0x37, 0xb3, 0x9b }, -}; - -size_t add_len[MAX_TESTS] = - { 0, 0, 0, 20, 20, 20 }; - -int add_index[MAX_TESTS] = - { 0, 0, 0, 1, 1, 1 }; - -unsigned char additional[MAX_TESTS][64] = -{ - { 0x00 }, - { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xab, 0xad, 0xda, 0xd2 }, -}; - -size_t pt_len[MAX_TESTS] = - { 0, 16, 64, 60, 60, 60 }; - -int pt_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 1 }; - -unsigned char pt[MAX_TESTS][64] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, - 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, - 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, - 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, - 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, - 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, - 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, - 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, -}; - -unsigned char ct[MAX_TESTS * 3][64] = -{ - { 0x00 }, - { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, - 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, - { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, - { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91 }, - { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, - 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, - 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, - 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, - 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, - 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, - 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, - 0xc2, 0x3f, 0x45, 0x98 }, - { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, - 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, - 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, - 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, - 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, - 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, - 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, - 0x4c, 0x34, 0xae, 0xe5 }, - { 0x00 }, - { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, - 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, - { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, - 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, - 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, - 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, - 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, - 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, - 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, - 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, - { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, - 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, - 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, - 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, - 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, - 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, - 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, - 0xcc, 0xda, 0x27, 0x10 }, - { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, - 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, - 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, - 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, - 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, - 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, - 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, - 0xa0, 0xf0, 0x62, 0xf7 }, - { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, - 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, - 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, - 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, - 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, - 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, - 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, - 0xe9, 0xb7, 0x37, 0x3b }, - { 0x00 }, - { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, - 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, - { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, - 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, - 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, - 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, - 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, - 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, - 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, - 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, - { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, - 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, - 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, - 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, - 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, - 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, - 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, - 0xbc, 0xc9, 0xf6, 0x62 }, - { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, - 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, - 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, - 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, - 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, - 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, - 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, - 0xf4, 0x7c, 0x9b, 0x1f }, - { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, - 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, - 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, - 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, - 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, - 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, - 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, - 0x44, 0xae, 0x7e, 0x3f }, -}; - -unsigned char tag[MAX_TESTS * 3][16] = -{ - { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, - 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, - { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, - 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, - { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, - 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, - { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, - 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, - { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, - 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, - { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, - 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, - { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, - 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, - { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, - 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, - { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, - 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, - { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, - 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, - { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, - 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, - { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, - 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, - { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, - 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, - { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, - 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, - { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, - 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, - { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, - 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, - { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, - 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, - { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, - 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, -}; - -int gcm_self_test( int verbose ) -{ - gcm_context ctx; - unsigned char buf[64]; - unsigned char tag_buf[16]; - int i, j, ret; - - for( j = 0; j < 3; j++ ) - { - int key_len = 128 + 64 * j; - - for( i = 0; i < MAX_TESTS; i++ ) - { - printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "enc" ); - gcm_init( &ctx, key[key_index[i]], key_len ); - - ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT, - pt_len[i], - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i], - pt[pt_index[i]], buf, 16, tag_buf ); - - if( ret != 0 || - memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "dec" ); - gcm_init( &ctx, key[key_index[i]], key_len ); - - ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT, - pt_len[i], - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i], - ct[j * 6 + i], buf, 16, tag_buf ); - - if( ret != 0 || - memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - } - - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/havege.c b/polarssl/src/library/havege.c deleted file mode 100644 index ff302c5..0000000 --- a/polarssl/src/library/havege.c +++ /dev/null @@ -1,231 +0,0 @@ -/** - * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The HAVEGE RNG was designed by Andre Seznec in 2002. - * - * http://www.irisa.fr/caps/projects/hipsor/publi.php - * - * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_HAVEGE_C) - -#include "polarssl/havege.h" -#include "polarssl/timing.h" - -#include -#include - -/* ------------------------------------------------------------------------ - * On average, one iteration accesses two 8-word blocks in the havege WALK - * table, and generates 16 words in the RES array. - * - * The data read in the WALK table is updated and permuted after each use. - * The result of the hardware clock counter read is used for this update. - * - * 25 conditional tests are present. The conditional tests are grouped in - * two nested groups of 12 conditional tests and 1 test that controls the - * permutation; on average, there should be 6 tests executed and 3 of them - * should be mispredicted. - * ------------------------------------------------------------------------ - */ - -#define SWAP(X,Y) { int *T = X; X = Y; Y = T; } - -#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; -#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; - -#define TST1_LEAVE U1++; } -#define TST2_LEAVE U2++; } - -#define ONE_ITERATION \ - \ - PTEST = PT1 >> 20; \ - \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - \ - PTX = (PT1 >> 18) & 7; \ - PT1 &= 0x1FFF; \ - PT2 &= 0x1FFF; \ - CLK = (int) hardclock(); \ - \ - i = 0; \ - A = &WALK[PT1 ]; RES[i++] ^= *A; \ - B = &WALK[PT2 ]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ - \ - IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ - *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ - *B = IN ^ U1; \ - *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ - *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ - B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ - \ - if( PTEST & 1 ) SWAP( A, C ); \ - \ - IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ - *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ - *B = IN; CLK = (int) hardclock(); \ - *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ - *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 4]; \ - B = &WALK[PT2 ^ 1]; \ - \ - PTEST = PT2 >> 1; \ - \ - PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ - PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ - PTY = (PT2 >> 10) & 7; \ - \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - \ - C = &WALK[PT1 ^ 5]; \ - D = &WALK[PT2 ^ 5]; \ - \ - RES[i++] ^= *A; \ - RES[i++] ^= *B; \ - RES[i++] ^= *C; \ - RES[i++] ^= *D; \ - \ - IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ - *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ - *B = IN ^ U2; \ - *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ - *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ - B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ - \ - IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ - *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ - *B = IN; \ - *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ - *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ - \ - PT1 = ( RES[(i - 8) ^ PTX] ^ \ - WALK[PT1 ^ PTX ^ 7] ) & (~1); \ - PT1 ^= (PT2 ^ 0x10) & 0x10; \ - \ - for( n++, i = 0; i < 16; i++ ) \ - hs->pool[n % COLLECT_SIZE] ^= RES[i]; - -/* - * Entropy gathering function - */ -static void havege_fill( havege_state *hs ) -{ - int i, n = 0; - int U1, U2, *A, *B, *C, *D; - int PT1, PT2, *WALK, RES[16]; - int PTX, PTY, CLK, PTEST, IN; - - WALK = hs->WALK; - PT1 = hs->PT1; - PT2 = hs->PT2; - - PTX = U1 = 0; - PTY = U2 = 0; - - memset( RES, 0, sizeof( RES ) ); - - while( n < COLLECT_SIZE * 4 ) - { - ONE_ITERATION - ONE_ITERATION - ONE_ITERATION - ONE_ITERATION - } - - hs->PT1 = PT1; - hs->PT2 = PT2; - - hs->offset[0] = 0; - hs->offset[1] = COLLECT_SIZE / 2; -} - -/* - * HAVEGE initialization - */ -void havege_init( havege_state *hs ) -{ - memset( hs, 0, sizeof( havege_state ) ); - - havege_fill( hs ); -} - -/* - * HAVEGE rand function - */ -int havege_random( void *p_rng, unsigned char *buf, size_t len ) -{ - int val; - size_t use_len; - havege_state *hs = (havege_state *) p_rng; - unsigned char *p = buf; - - while( len > 0 ) - { - use_len = len; - if( use_len > sizeof(int) ) - use_len = sizeof(int); - - if( hs->offset[1] >= COLLECT_SIZE ) - havege_fill( hs ); - - val = hs->pool[hs->offset[0]++]; - val ^= hs->pool[hs->offset[1]++]; - - memcpy( p, &val, use_len ); - - len -= use_len; - p += use_len; - } - - return( 0 ); -} - -#endif diff --git a/polarssl/src/library/md.c b/polarssl/src/library/md.c deleted file mode 100644 index 96065c9..0000000 --- a/polarssl/src/library/md.c +++ /dev/null @@ -1,297 +0,0 @@ -/** - * \file md.c - * - * \brief Generic message digest wrapper for PolarSSL - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_MD_C) - -#include "polarssl/md.h" -#include "polarssl/md_wrap.h" - -#include - -#if defined _MSC_VER && !defined strcasecmp -#define strcasecmp _stricmp -#endif - -static const int supported_digests[] = { - -#if defined(POLARSSL_MD2_C) - POLARSSL_MD_MD2, -#endif - -#if defined(POLARSSL_MD4_C) - POLARSSL_MD_MD4, -#endif - -#if defined(POLARSSL_MD5_C) - POLARSSL_MD_MD5, -#endif - -#if defined(POLARSSL_SHA1_C) - POLARSSL_MD_SHA1, -#endif - -#if defined(POLARSSL_SHA2_C) - POLARSSL_MD_SHA224, - POLARSSL_MD_SHA256, -#endif - -#if defined(POLARSSL_SHA4_C) - POLARSSL_MD_SHA384, - POLARSSL_MD_SHA512, -#endif - - 0 -}; - -const int *md_list( void ) -{ - return supported_digests; -} - -const md_info_t *md_info_from_string( const char *md_name ) -{ - if( NULL == md_name ) - return NULL; - - /* Get the appropriate digest information */ -#if defined(POLARSSL_MD2_C) - if( !strcasecmp( "MD2", md_name ) ) - return md_info_from_type( POLARSSL_MD_MD2 ); -#endif -#if defined(POLARSSL_MD4_C) - if( !strcasecmp( "MD4", md_name ) ) - return md_info_from_type( POLARSSL_MD_MD4 ); -#endif -#if defined(POLARSSL_MD5_C) - if( !strcasecmp( "MD5", md_name ) ) - return md_info_from_type( POLARSSL_MD_MD5 ); -#endif -#if defined(POLARSSL_SHA1_C) - if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) ) - return md_info_from_type( POLARSSL_MD_SHA1 ); -#endif -#if defined(POLARSSL_SHA2_C) - if( !strcasecmp( "SHA224", md_name ) ) - return md_info_from_type( POLARSSL_MD_SHA224 ); - if( !strcasecmp( "SHA256", md_name ) ) - return md_info_from_type( POLARSSL_MD_SHA256 ); -#endif -#if defined(POLARSSL_SHA4_C) - if( !strcasecmp( "SHA384", md_name ) ) - return md_info_from_type( POLARSSL_MD_SHA384 ); - if( !strcasecmp( "SHA512", md_name ) ) - return md_info_from_type( POLARSSL_MD_SHA512 ); -#endif - return NULL; -} - -const md_info_t *md_info_from_type( md_type_t md_type ) -{ - switch( md_type ) - { -#if defined(POLARSSL_MD2_C) - case POLARSSL_MD_MD2: - return &md2_info; -#endif -#if defined(POLARSSL_MD4_C) - case POLARSSL_MD_MD4: - return &md4_info; -#endif -#if defined(POLARSSL_MD5_C) - case POLARSSL_MD_MD5: - return &md5_info; -#endif -#if defined(POLARSSL_SHA1_C) - case POLARSSL_MD_SHA1: - return &sha1_info; -#endif -#if defined(POLARSSL_SHA2_C) - case POLARSSL_MD_SHA224: - return &sha224_info; - case POLARSSL_MD_SHA256: - return &sha256_info; -#endif -#if defined(POLARSSL_SHA4_C) - case POLARSSL_MD_SHA384: - return &sha384_info; - case POLARSSL_MD_SHA512: - return &sha512_info; -#endif - default: - return NULL; - } -} - -int md_init_ctx( md_context_t *ctx, const md_info_t *md_info ) -{ - if( md_info == NULL || ctx == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - memset( ctx, 0, sizeof( md_context_t ) ); - - if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) - return POLARSSL_ERR_MD_ALLOC_FAILED; - - ctx->md_info = md_info; - - md_info->starts_func( ctx->md_ctx ); - - return 0; -} - -int md_free_ctx( md_context_t *ctx ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - ctx->md_info->ctx_free_func( ctx->md_ctx ); - ctx->md_ctx = NULL; - - return 0; -} - -int md_starts( md_context_t *ctx ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - ctx->md_info->starts_func( ctx->md_ctx ); - - return 0; -} - -int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - ctx->md_info->update_func( ctx->md_ctx, input, ilen ); - - return 0; -} - -int md_finish( md_context_t *ctx, unsigned char *output ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - ctx->md_info->finish_func( ctx->md_ctx, output ); - - return 0; -} - -int md( const md_info_t *md_info, const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - if ( md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - md_info->digest_func( input, ilen, output ); - - return 0; -} - -int md_file( const md_info_t *md_info, const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - int ret; -#endif - - if( md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - -#if defined(POLARSSL_FS_IO) - ret = md_info->file_func( path, output ); - if( ret != 0 ) - return( POLARSSL_ERR_MD_FILE_IO_ERROR + ret ); - - return( ret ); -#else - ((void) path); - ((void) output); - - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen); - - return 0; -} - -int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen ); - - return 0; -} - -int md_hmac_finish( md_context_t *ctx, unsigned char *output) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - ctx->md_info->hmac_finish_func( ctx->md_ctx, output); - - return 0; -} - -int md_hmac_reset( md_context_t *ctx ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - ctx->md_info->hmac_reset_func( ctx->md_ctx); - - return 0; -} - -int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - if( md_info == NULL ) - return POLARSSL_ERR_MD_BAD_INPUT_DATA; - - md_info->hmac_func( key, keylen, input, ilen, output ); - - return 0; -} - -#endif diff --git a/polarssl/src/library/md2.c b/polarssl/src/library/md2.c deleted file mode 100644 index 954aa07..0000000 --- a/polarssl/src/library/md2.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * RFC 1115/1319 compliant MD2 implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The MD2 algorithm was designed by Ron Rivest in 1989. - * - * http://www.ietf.org/rfc/rfc1115.txt - * http://www.ietf.org/rfc/rfc1319.txt - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_MD2_C) - -#include "polarssl/md2.h" - -#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) -#include -#endif - -static const unsigned char PI_SUBST[256] = -{ - 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, - 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, - 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, - 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, - 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, - 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, - 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, - 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, - 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, - 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, - 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, - 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, - 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, - 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, - 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, - 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, - 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, - 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, - 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, - 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, - 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, - 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, - 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, - 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, - 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, - 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 -}; - -/* - * MD2 context setup - */ -void md2_starts( md2_context *ctx ) -{ - memset( ctx->cksum, 0, 16 ); - memset( ctx->state, 0, 46 ); - memset( ctx->buffer, 0, 16 ); - ctx->left = 0; -} - -static void md2_process( md2_context *ctx ) -{ - int i, j; - unsigned char t = 0; - - for( i = 0; i < 16; i++ ) - { - ctx->state[i + 16] = ctx->buffer[i]; - ctx->state[i + 32] = - (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); - } - - for( i = 0; i < 18; i++ ) - { - for( j = 0; j < 48; j++ ) - { - ctx->state[j] = (unsigned char) - ( ctx->state[j] ^ PI_SUBST[t] ); - t = ctx->state[j]; - } - - t = (unsigned char)( t + i ); - } - - t = ctx->cksum[15]; - - for( i = 0; i < 16; i++ ) - { - ctx->cksum[i] = (unsigned char) - ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); - t = ctx->cksum[i]; - } -} - -/* - * MD2 process buffer - */ -void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - - while( ilen > 0 ) - { - if( ctx->left + ilen > 16 ) - fill = 16 - ctx->left; - else - fill = ilen; - - memcpy( ctx->buffer + ctx->left, input, fill ); - - ctx->left += fill; - input += fill; - ilen -= fill; - - if( ctx->left == 16 ) - { - ctx->left = 0; - md2_process( ctx ); - } - } -} - -/* - * MD2 final digest - */ -void md2_finish( md2_context *ctx, unsigned char output[16] ) -{ - size_t i; - unsigned char x; - - x = (unsigned char)( 16 - ctx->left ); - - for( i = ctx->left; i < 16; i++ ) - ctx->buffer[i] = x; - - md2_process( ctx ); - - memcpy( ctx->buffer, ctx->cksum, 16 ); - md2_process( ctx ); - - memcpy( output, ctx->state, 16 ); -} - -/* - * output = MD2( input buffer ) - */ -void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - md2_context ctx; - - md2_starts( &ctx ); - md2_update( &ctx, input, ilen ); - md2_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md2_context ) ); -} - -#if defined(POLARSSL_FS_IO) -/* - * output = MD2( file contents ) - */ -int md2_file( const char *path, unsigned char output[16] ) -{ - FILE *f; - size_t n; - md2_context ctx; - unsigned char buf[1024]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); - - md2_starts( &ctx ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - md2_update( &ctx, buf, n ); - - md2_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md2_context ) ); - - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); - } - - fclose( f ); - return( 0 ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * MD2 HMAC context setup - */ -void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen ) -{ - size_t i; - unsigned char sum[16]; - - if( keylen > 16 ) - { - md2( key, keylen, sum ); - keylen = 16; - key = sum; - } - - memset( ctx->ipad, 0x36, 16 ); - memset( ctx->opad, 0x5C, 16 ); - - for( i = 0; i < keylen; i++ ) - { - ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); - ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); - } - - md2_starts( ctx ); - md2_update( ctx, ctx->ipad, 16 ); - - memset( sum, 0, sizeof( sum ) ); -} - -/* - * MD2 HMAC process buffer - */ -void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen ) -{ - md2_update( ctx, input, ilen ); -} - -/* - * MD2 HMAC final digest - */ -void md2_hmac_finish( md2_context *ctx, unsigned char output[16] ) -{ - unsigned char tmpbuf[16]; - - md2_finish( ctx, tmpbuf ); - md2_starts( ctx ); - md2_update( ctx, ctx->opad, 16 ); - md2_update( ctx, tmpbuf, 16 ); - md2_finish( ctx, output ); - - memset( tmpbuf, 0, sizeof( tmpbuf ) ); -} - -/* - * MD2 HMAC context reset - */ -void md2_hmac_reset( md2_context *ctx ) -{ - md2_starts( ctx ); - md2_update( ctx, ctx->ipad, 16 ); -} - -/* - * output = HMAC-MD2( hmac key, input buffer ) - */ -void md2_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[16] ) -{ - md2_context ctx; - - md2_hmac_starts( &ctx, key, keylen ); - md2_hmac_update( &ctx, input, ilen ); - md2_hmac_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md2_context ) ); -} - -#if defined(POLARSSL_SELF_TEST) - -/* - * RFC 1319 test vectors - */ -static const char md2_test_str[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const unsigned char md2_test_sum[7][16] = -{ - { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, - 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, - { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, - 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, - { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, - 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, - { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, - 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, - { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, - 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, - { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, - 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, - { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, - 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } -}; - -/* - * Checkup routine - */ -int md2_self_test( int verbose ) -{ - int i; - unsigned char md2sum[16]; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - printf( " MD2 test #%d: ", i + 1 ); - - md2( (unsigned char *) md2_test_str[i], - strlen( md2_test_str[i] ), md2sum ); - - if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/md4.c b/polarssl/src/library/md4.c deleted file mode 100644 index ad52e5e..0000000 --- a/polarssl/src/library/md4.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * RFC 1186/1320 compliant MD4 implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The MD4 algorithm was designed by Ron Rivest in 1990. - * - * http://www.ietf.org/rfc/rfc1186.txt - * http://www.ietf.org/rfc/rfc1320.txt - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_MD4_C) - -#include "polarssl/md4.h" - -#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) -#include -#endif - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -/* - * MD4 context setup - */ -void md4_starts( md4_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -static void md4_process( md4_context *ctx, const unsigned char data[64] ) -{ - unsigned long X[16], A, B, C, D; - - GET_ULONG_LE( X[ 0], data, 0 ); - GET_ULONG_LE( X[ 1], data, 4 ); - GET_ULONG_LE( X[ 2], data, 8 ); - GET_ULONG_LE( X[ 3], data, 12 ); - GET_ULONG_LE( X[ 4], data, 16 ); - GET_ULONG_LE( X[ 5], data, 20 ); - GET_ULONG_LE( X[ 6], data, 24 ); - GET_ULONG_LE( X[ 7], data, 28 ); - GET_ULONG_LE( X[ 8], data, 32 ); - GET_ULONG_LE( X[ 9], data, 36 ); - GET_ULONG_LE( X[10], data, 40 ); - GET_ULONG_LE( X[11], data, 44 ); - GET_ULONG_LE( X[12], data, 48 ); - GET_ULONG_LE( X[13], data, 52 ); - GET_ULONG_LE( X[14], data, 56 ); - GET_ULONG_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x, y, z) ((x & y) | ((~x) & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 1], 7 ); - P( C, D, A, B, X[ 2], 11 ); - P( B, C, D, A, X[ 3], 19 ); - P( A, B, C, D, X[ 4], 3 ); - P( D, A, B, C, X[ 5], 7 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[ 7], 19 ); - P( A, B, C, D, X[ 8], 3 ); - P( D, A, B, C, X[ 9], 7 ); - P( C, D, A, B, X[10], 11 ); - P( B, C, D, A, X[11], 19 ); - P( A, B, C, D, X[12], 3 ); - P( D, A, B, C, X[13], 7 ); - P( C, D, A, B, X[14], 11 ); - P( B, C, D, A, X[15], 19 ); - -#undef P -#undef F - -#define F(x,y,z) ((x & y) | (x & z) | (y & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 4], 5 ); - P( C, D, A, B, X[ 8], 9 ); - P( B, C, D, A, X[12], 13 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 5], 5 ); - P( C, D, A, B, X[ 9], 9 ); - P( B, C, D, A, X[13], 13 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[ 6], 5 ); - P( C, D, A, B, X[10], 9 ); - P( B, C, D, A, X[14], 13 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[ 7], 5 ); - P( C, D, A, B, X[11], 9 ); - P( B, C, D, A, X[15], 13 ); - -#undef P -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 8], 9 ); - P( C, D, A, B, X[ 4], 11 ); - P( B, C, D, A, X[12], 15 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[10], 9 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[14], 15 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 9], 9 ); - P( C, D, A, B, X[ 5], 11 ); - P( B, C, D, A, X[13], 15 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[11], 9 ); - P( C, D, A, B, X[ 7], 11 ); - P( B, C, D, A, X[15], 15 ); - -#undef F -#undef P - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} - -/* - * MD4 process buffer - */ -void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (unsigned long) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, fill ); - md4_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - md4_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, ilen ); - } -} - -static const unsigned char md4_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD4 final digest - */ -void md4_finish( md4_context *ctx, unsigned char output[16] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_LE( low, msglen, 0 ); - PUT_ULONG_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - md4_update( ctx, (unsigned char *) md4_padding, padn ); - md4_update( ctx, msglen, 8 ); - - PUT_ULONG_LE( ctx->state[0], output, 0 ); - PUT_ULONG_LE( ctx->state[1], output, 4 ); - PUT_ULONG_LE( ctx->state[2], output, 8 ); - PUT_ULONG_LE( ctx->state[3], output, 12 ); -} - -/* - * output = MD4( input buffer ) - */ -void md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - md4_context ctx; - - md4_starts( &ctx ); - md4_update( &ctx, input, ilen ); - md4_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md4_context ) ); -} - -#if defined(POLARSSL_FS_IO) -/* - * output = MD4( file contents ) - */ -int md4_file( const char *path, unsigned char output[16] ) -{ - FILE *f; - size_t n; - md4_context ctx; - unsigned char buf[1024]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_MD4_FILE_IO_ERROR ); - - md4_starts( &ctx ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - md4_update( &ctx, buf, n ); - - md4_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md4_context ) ); - - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_MD4_FILE_IO_ERROR ); - } - - fclose( f ); - return( 0 ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * MD4 HMAC context setup - */ -void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen ) -{ - size_t i; - unsigned char sum[16]; - - if( keylen > 64 ) - { - md4( key, keylen, sum ); - keylen = 16; - key = sum; - } - - memset( ctx->ipad, 0x36, 64 ); - memset( ctx->opad, 0x5C, 64 ); - - for( i = 0; i < keylen; i++ ) - { - ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); - ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); - } - - md4_starts( ctx ); - md4_update( ctx, ctx->ipad, 64 ); - - memset( sum, 0, sizeof( sum ) ); -} - -/* - * MD4 HMAC process buffer - */ -void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen ) -{ - md4_update( ctx, input, ilen ); -} - -/* - * MD4 HMAC final digest - */ -void md4_hmac_finish( md4_context *ctx, unsigned char output[16] ) -{ - unsigned char tmpbuf[16]; - - md4_finish( ctx, tmpbuf ); - md4_starts( ctx ); - md4_update( ctx, ctx->opad, 64 ); - md4_update( ctx, tmpbuf, 16 ); - md4_finish( ctx, output ); - - memset( tmpbuf, 0, sizeof( tmpbuf ) ); -} - -/* - * MD4 HMAC context reset - */ -void md4_hmac_reset( md4_context *ctx ) -{ - md4_starts( ctx ); - md4_update( ctx, ctx->ipad, 64 ); -} - -/* - * output = HMAC-MD4( hmac key, input buffer ) - */ -void md4_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[16] ) -{ - md4_context ctx; - - md4_hmac_starts( &ctx, key, keylen ); - md4_hmac_update( &ctx, input, ilen ); - md4_hmac_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md4_context ) ); -} - -#if defined(POLARSSL_SELF_TEST) - -/* - * RFC 1320 test vectors - */ -static const char md4_test_str[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const unsigned char md4_test_sum[7][16] = -{ - { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, - 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, - { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, - 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, - { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, - 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, - { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, - 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, - { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, - 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, - { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, - 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, - { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, - 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } -}; - -/* - * Checkup routine - */ -int md4_self_test( int verbose ) -{ - int i; - unsigned char md4sum[16]; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - printf( " MD4 test #%d: ", i + 1 ); - - md4( (unsigned char *) md4_test_str[i], - strlen( md4_test_str[i] ), md4sum ); - - if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/md5.c b/polarssl/src/library/md5.c deleted file mode 100644 index 7a449b2..0000000 --- a/polarssl/src/library/md5.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * RFC 1321 compliant MD5 implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The MD5 algorithm was designed by Ron Rivest in 1991. - * - * http://www.ietf.org/rfc/rfc1321.txt - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_MD5_C) - -#include "polarssl/md5.h" - -#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) -#include -#endif - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -/* - * MD5 context setup - */ -void md5_starts( md5_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -static void md5_process( md5_context *ctx, const unsigned char data[64] ) -{ - unsigned long X[16], A, B, C, D; - - GET_ULONG_LE( X[ 0], data, 0 ); - GET_ULONG_LE( X[ 1], data, 4 ); - GET_ULONG_LE( X[ 2], data, 8 ); - GET_ULONG_LE( X[ 3], data, 12 ); - GET_ULONG_LE( X[ 4], data, 16 ); - GET_ULONG_LE( X[ 5], data, 20 ); - GET_ULONG_LE( X[ 6], data, 24 ); - GET_ULONG_LE( X[ 7], data, 28 ); - GET_ULONG_LE( X[ 8], data, 32 ); - GET_ULONG_LE( X[ 9], data, 36 ); - GET_ULONG_LE( X[10], data, 40 ); - GET_ULONG_LE( X[11], data, 44 ); - GET_ULONG_LE( X[12], data, 48 ); - GET_ULONG_LE( X[13], data, 52 ); - GET_ULONG_LE( X[14], data, 56 ); - GET_ULONG_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define P(a,b,c,d,k,s,t) \ -{ \ - a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) - - P( A, B, C, D, 0, 7, 0xD76AA478 ); - P( D, A, B, C, 1, 12, 0xE8C7B756 ); - P( C, D, A, B, 2, 17, 0x242070DB ); - P( B, C, D, A, 3, 22, 0xC1BDCEEE ); - P( A, B, C, D, 4, 7, 0xF57C0FAF ); - P( D, A, B, C, 5, 12, 0x4787C62A ); - P( C, D, A, B, 6, 17, 0xA8304613 ); - P( B, C, D, A, 7, 22, 0xFD469501 ); - P( A, B, C, D, 8, 7, 0x698098D8 ); - P( D, A, B, C, 9, 12, 0x8B44F7AF ); - P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); - P( B, C, D, A, 11, 22, 0x895CD7BE ); - P( A, B, C, D, 12, 7, 0x6B901122 ); - P( D, A, B, C, 13, 12, 0xFD987193 ); - P( C, D, A, B, 14, 17, 0xA679438E ); - P( B, C, D, A, 15, 22, 0x49B40821 ); - -#undef F - -#define F(x,y,z) (y ^ (z & (x ^ y))) - - P( A, B, C, D, 1, 5, 0xF61E2562 ); - P( D, A, B, C, 6, 9, 0xC040B340 ); - P( C, D, A, B, 11, 14, 0x265E5A51 ); - P( B, C, D, A, 0, 20, 0xE9B6C7AA ); - P( A, B, C, D, 5, 5, 0xD62F105D ); - P( D, A, B, C, 10, 9, 0x02441453 ); - P( C, D, A, B, 15, 14, 0xD8A1E681 ); - P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); - P( A, B, C, D, 9, 5, 0x21E1CDE6 ); - P( D, A, B, C, 14, 9, 0xC33707D6 ); - P( C, D, A, B, 3, 14, 0xF4D50D87 ); - P( B, C, D, A, 8, 20, 0x455A14ED ); - P( A, B, C, D, 13, 5, 0xA9E3E905 ); - P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); - P( C, D, A, B, 7, 14, 0x676F02D9 ); - P( B, C, D, A, 12, 20, 0x8D2A4C8A ); - -#undef F - -#define F(x,y,z) (x ^ y ^ z) - - P( A, B, C, D, 5, 4, 0xFFFA3942 ); - P( D, A, B, C, 8, 11, 0x8771F681 ); - P( C, D, A, B, 11, 16, 0x6D9D6122 ); - P( B, C, D, A, 14, 23, 0xFDE5380C ); - P( A, B, C, D, 1, 4, 0xA4BEEA44 ); - P( D, A, B, C, 4, 11, 0x4BDECFA9 ); - P( C, D, A, B, 7, 16, 0xF6BB4B60 ); - P( B, C, D, A, 10, 23, 0xBEBFBC70 ); - P( A, B, C, D, 13, 4, 0x289B7EC6 ); - P( D, A, B, C, 0, 11, 0xEAA127FA ); - P( C, D, A, B, 3, 16, 0xD4EF3085 ); - P( B, C, D, A, 6, 23, 0x04881D05 ); - P( A, B, C, D, 9, 4, 0xD9D4D039 ); - P( D, A, B, C, 12, 11, 0xE6DB99E5 ); - P( C, D, A, B, 15, 16, 0x1FA27CF8 ); - P( B, C, D, A, 2, 23, 0xC4AC5665 ); - -#undef F - -#define F(x,y,z) (y ^ (x | ~z)) - - P( A, B, C, D, 0, 6, 0xF4292244 ); - P( D, A, B, C, 7, 10, 0x432AFF97 ); - P( C, D, A, B, 14, 15, 0xAB9423A7 ); - P( B, C, D, A, 5, 21, 0xFC93A039 ); - P( A, B, C, D, 12, 6, 0x655B59C3 ); - P( D, A, B, C, 3, 10, 0x8F0CCC92 ); - P( C, D, A, B, 10, 15, 0xFFEFF47D ); - P( B, C, D, A, 1, 21, 0x85845DD1 ); - P( A, B, C, D, 8, 6, 0x6FA87E4F ); - P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); - P( C, D, A, B, 6, 15, 0xA3014314 ); - P( B, C, D, A, 13, 21, 0x4E0811A1 ); - P( A, B, C, D, 4, 6, 0xF7537E82 ); - P( D, A, B, C, 11, 10, 0xBD3AF235 ); - P( C, D, A, B, 2, 15, 0x2AD7D2BB ); - P( B, C, D, A, 9, 21, 0xEB86D391 ); - -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} - -/* - * MD5 process buffer - */ -void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (unsigned long) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, fill ); - md5_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - md5_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, ilen ); - } -} - -static const unsigned char md5_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD5 final digest - */ -void md5_finish( md5_context *ctx, unsigned char output[16] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_LE( low, msglen, 0 ); - PUT_ULONG_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - md5_update( ctx, (unsigned char *) md5_padding, padn ); - md5_update( ctx, msglen, 8 ); - - PUT_ULONG_LE( ctx->state[0], output, 0 ); - PUT_ULONG_LE( ctx->state[1], output, 4 ); - PUT_ULONG_LE( ctx->state[2], output, 8 ); - PUT_ULONG_LE( ctx->state[3], output, 12 ); -} - -/* - * output = MD5( input buffer ) - */ -void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - md5_context ctx; - - md5_starts( &ctx ); - md5_update( &ctx, input, ilen ); - md5_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md5_context ) ); -} - -#if defined(POLARSSL_FS_IO) -/* - * output = MD5( file contents ) - */ -int md5_file( const char *path, unsigned char output[16] ) -{ - FILE *f; - size_t n; - md5_context ctx; - unsigned char buf[1024]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_MD5_FILE_IO_ERROR ); - - md5_starts( &ctx ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - md5_update( &ctx, buf, n ); - - md5_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md5_context ) ); - - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_MD5_FILE_IO_ERROR ); - } - - fclose( f ); - return( 0 ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * MD5 HMAC context setup - */ -void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen ) -{ - size_t i; - unsigned char sum[16]; - - if( keylen > 64 ) - { - md5( key, keylen, sum ); - keylen = 16; - key = sum; - } - - memset( ctx->ipad, 0x36, 64 ); - memset( ctx->opad, 0x5C, 64 ); - - for( i = 0; i < keylen; i++ ) - { - ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); - ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); - } - - md5_starts( ctx ); - md5_update( ctx, ctx->ipad, 64 ); - - memset( sum, 0, sizeof( sum ) ); -} - -/* - * MD5 HMAC process buffer - */ -void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen ) -{ - md5_update( ctx, input, ilen ); -} - -/* - * MD5 HMAC final digest - */ -void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ) -{ - unsigned char tmpbuf[16]; - - md5_finish( ctx, tmpbuf ); - md5_starts( ctx ); - md5_update( ctx, ctx->opad, 64 ); - md5_update( ctx, tmpbuf, 16 ); - md5_finish( ctx, output ); - - memset( tmpbuf, 0, sizeof( tmpbuf ) ); -} - -/* - * MD5 HMAC context reset - */ -void md5_hmac_reset( md5_context *ctx ) -{ - md5_starts( ctx ); - md5_update( ctx, ctx->ipad, 64 ); -} - -/* - * output = HMAC-MD5( hmac key, input buffer ) - */ -void md5_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[16] ) -{ - md5_context ctx; - - md5_hmac_starts( &ctx, key, keylen ); - md5_hmac_update( &ctx, input, ilen ); - md5_hmac_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( md5_context ) ); -} - -#if defined(POLARSSL_SELF_TEST) -/* - * RFC 1321 test vectors - */ -static unsigned char md5_test_buf[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const int md5_test_buflen[7] = -{ - 0, 1, 3, 14, 26, 62, 80 -}; - -static const unsigned char md5_test_sum[7][16] = -{ - { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, - 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, - { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, - 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, - { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, - 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, - { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, - 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, - { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, - 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, - { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, - 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, - { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, - 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } -}; - -/* - * RFC 2202 test vectors - */ -static unsigned char md5_hmac_test_key[7][26] = -{ - { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" }, - { "Jefe" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" }, - { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, - { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" }, - { "" }, /* 0xAA 80 times */ - { "" } -}; - -static const int md5_hmac_test_keylen[7] = -{ - 16, 4, 16, 25, 16, 80, 80 -}; - -static unsigned char md5_hmac_test_buf[7][74] = -{ - { "Hi There" }, - { "what do ya want for nothing?" }, - { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, - { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, - { "Test With Truncation" }, - { "Test Using Larger Than Block-Size Key - Hash Key First" }, - { "Test Using Larger Than Block-Size Key and Larger" - " Than One Block-Size Data" } -}; - -static const int md5_hmac_test_buflen[7] = -{ - 8, 28, 50, 50, 20, 54, 73 -}; - -static const unsigned char md5_hmac_test_sum[7][16] = -{ - { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C, - 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D }, - { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03, - 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 }, - { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88, - 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 }, - { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA, - 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 }, - { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00, - 0xF9, 0xBA, 0xB9, 0x95 }, - { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F, - 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD }, - { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE, - 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E } -}; - -/* - * Checkup routine - */ -int md5_self_test( int verbose ) -{ - int i, buflen; - unsigned char buf[1024]; - unsigned char md5sum[16]; - md5_context ctx; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - printf( " MD5 test #%d: ", i + 1 ); - - md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); - - if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - printf( " HMAC-MD5 test #%d: ", i + 1 ); - - if( i == 5 || i == 6 ) - { - memset( buf, '\xAA', buflen = 80 ); - md5_hmac_starts( &ctx, buf, buflen ); - } - else - md5_hmac_starts( &ctx, md5_hmac_test_key[i], - md5_hmac_test_keylen[i] ); - - md5_hmac_update( &ctx, md5_hmac_test_buf[i], - md5_hmac_test_buflen[i] ); - - md5_hmac_finish( &ctx, md5sum ); - - buflen = ( i == 4 ) ? 12 : 16; - - if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/md_wrap.c b/polarssl/src/library/md_wrap.c deleted file mode 100644 index f276db5..0000000 --- a/polarssl/src/library/md_wrap.c +++ /dev/null @@ -1,733 +0,0 @@ -/** - * \file md_wrap.c - - * \brief Generic message digest wrapper for PolarSSL - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_MD_C) - -#include "polarssl/md_wrap.h" - -#if defined(POLARSSL_MD2_C) -#include "polarssl/md2.h" -#endif - -#if defined(POLARSSL_MD4_C) -#include "polarssl/md4.h" -#endif - -#if defined(POLARSSL_MD5_C) -#include "polarssl/md5.h" -#endif - -#if defined(POLARSSL_SHA1_C) -#include "polarssl/sha1.h" -#endif - -#if defined(POLARSSL_SHA2_C) -#include "polarssl/sha2.h" -#endif - -#if defined(POLARSSL_SHA4_C) -#include "polarssl/sha4.h" -#endif - -#include - -#if defined(POLARSSL_MD2_C) - -static void md2_starts_wrap( void *ctx ) -{ - md2_starts( (md2_context *) ctx ); -} - -static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - md2_update( (md2_context *) ctx, input, ilen ); -} - -static void md2_finish_wrap( void *ctx, unsigned char *output ) -{ - md2_finish( (md2_context *) ctx, output ); -} - -int md2_file_wrap( const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - return md2_file( path, output ); -#else - ((void) path); - ((void) output); - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen ) -{ - md2_hmac_starts( (md2_context *) ctx, key, keylen ); -} - -static void md2_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - md2_hmac_update( (md2_context *) ctx, input, ilen ); -} - -static void md2_hmac_finish_wrap( void *ctx, unsigned char *output ) -{ - md2_hmac_finish( (md2_context *) ctx, output ); -} - -static void md2_hmac_reset_wrap( void *ctx ) -{ - md2_hmac_reset( (md2_context *) ctx ); -} - -static void * md2_ctx_alloc( void ) -{ - return malloc( sizeof( md2_context ) ); -} - -static void md2_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const md_info_t md2_info = { - POLARSSL_MD_MD2, - "MD2", - 16, - md2_starts_wrap, - md2_update_wrap, - md2_finish_wrap, - md2, - md2_file_wrap, - md2_hmac_starts_wrap, - md2_hmac_update_wrap, - md2_hmac_finish_wrap, - md2_hmac_reset_wrap, - md2_hmac, - md2_ctx_alloc, - md2_ctx_free, -}; - -#endif - -#if defined(POLARSSL_MD4_C) - -void md4_starts_wrap( void *ctx ) -{ - md4_starts( (md4_context *) ctx ); -} - -void md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - md4_update( (md4_context *) ctx, input, ilen ); -} - -void md4_finish_wrap( void *ctx, unsigned char *output ) -{ - md4_finish( (md4_context *) ctx, output ); -} - -int md4_file_wrap( const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - return md4_file( path, output ); -#else - ((void) path); - ((void) output); - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -void md4_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen ) -{ - md4_hmac_starts( (md4_context *) ctx, key, keylen ); -} - -void md4_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - md4_hmac_update( (md4_context *) ctx, input, ilen ); -} - -void md4_hmac_finish_wrap( void *ctx, unsigned char *output ) -{ - md4_hmac_finish( (md4_context *) ctx, output ); -} - -void md4_hmac_reset_wrap( void *ctx ) -{ - md4_hmac_reset( (md4_context *) ctx ); -} - -void *md4_ctx_alloc( void ) -{ - return malloc( sizeof( md4_context ) ); -} - -void md4_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const md_info_t md4_info = { - POLARSSL_MD_MD4, - "MD4", - 16, - md4_starts_wrap, - md4_update_wrap, - md4_finish_wrap, - md4, - md4_file_wrap, - md4_hmac_starts_wrap, - md4_hmac_update_wrap, - md4_hmac_finish_wrap, - md4_hmac_reset_wrap, - md4_hmac, - md4_ctx_alloc, - md4_ctx_free, -}; - -#endif - -#if defined(POLARSSL_MD5_C) - -static void md5_starts_wrap( void *ctx ) -{ - md5_starts( (md5_context *) ctx ); -} - -static void md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - md5_update( (md5_context *) ctx, input, ilen ); -} - -static void md5_finish_wrap( void *ctx, unsigned char *output ) -{ - md5_finish( (md5_context *) ctx, output ); -} - -int md5_file_wrap( const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - return md5_file( path, output ); -#else - ((void) path); - ((void) output); - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen ) -{ - md5_hmac_starts( (md5_context *) ctx, key, keylen ); -} - -static void md5_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - md5_hmac_update( (md5_context *) ctx, input, ilen ); -} - -static void md5_hmac_finish_wrap( void *ctx, unsigned char *output ) -{ - md5_hmac_finish( (md5_context *) ctx, output ); -} - -static void md5_hmac_reset_wrap( void *ctx ) -{ - md5_hmac_reset( (md5_context *) ctx ); -} - -static void * md5_ctx_alloc( void ) -{ - return malloc( sizeof( md5_context ) ); -} - -static void md5_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const md_info_t md5_info = { - POLARSSL_MD_MD5, - "MD5", - 16, - md5_starts_wrap, - md5_update_wrap, - md5_finish_wrap, - md5, - md5_file_wrap, - md5_hmac_starts_wrap, - md5_hmac_update_wrap, - md5_hmac_finish_wrap, - md5_hmac_reset_wrap, - md5_hmac, - md5_ctx_alloc, - md5_ctx_free, -}; - -#endif - -#if defined(POLARSSL_SHA1_C) - -void sha1_starts_wrap( void *ctx ) -{ - sha1_starts( (sha1_context *) ctx ); -} - -void sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha1_update( (sha1_context *) ctx, input, ilen ); -} - -void sha1_finish_wrap( void *ctx, unsigned char *output ) -{ - sha1_finish( (sha1_context *) ctx, output ); -} - -int sha1_file_wrap( const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - return sha1_file( path, output ); -#else - ((void) path); - ((void) output); - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen ) -{ - sha1_hmac_starts( (sha1_context *) ctx, key, keylen ); -} - -void sha1_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha1_hmac_update( (sha1_context *) ctx, input, ilen ); -} - -void sha1_hmac_finish_wrap( void *ctx, unsigned char *output ) -{ - sha1_hmac_finish( (sha1_context *) ctx, output ); -} - -void sha1_hmac_reset_wrap( void *ctx ) -{ - sha1_hmac_reset( (sha1_context *) ctx ); -} - -void * sha1_ctx_alloc( void ) -{ - return malloc( sizeof( sha1_context ) ); -} - -void sha1_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const md_info_t sha1_info = { - POLARSSL_MD_SHA1, - "SHA1", - 20, - sha1_starts_wrap, - sha1_update_wrap, - sha1_finish_wrap, - sha1, - sha1_file_wrap, - sha1_hmac_starts_wrap, - sha1_hmac_update_wrap, - sha1_hmac_finish_wrap, - sha1_hmac_reset_wrap, - sha1_hmac, - sha1_ctx_alloc, - sha1_ctx_free, -}; - -#endif - -/* - * Wrappers for generic message digests - */ -#if defined(POLARSSL_SHA2_C) - -void sha224_starts_wrap( void *ctx ) -{ - sha2_starts( (sha2_context *) ctx, 1 ); -} - -void sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha2_update( (sha2_context *) ctx, input, ilen ); -} - -void sha224_finish_wrap( void *ctx, unsigned char *output ) -{ - sha2_finish( (sha2_context *) ctx, output ); -} - -void sha224_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - sha2( input, ilen, output, 1 ); -} - -int sha224_file_wrap( const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - return sha2_file( path, output, 1 ); -#else - ((void) path); - ((void) output); - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen ) -{ - sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 1 ); -} - -void sha224_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha2_hmac_update( (sha2_context *) ctx, input, ilen ); -} - -void sha224_hmac_finish_wrap( void *ctx, unsigned char *output ) -{ - sha2_hmac_finish( (sha2_context *) ctx, output ); -} - -void sha224_hmac_reset_wrap( void *ctx ) -{ - sha2_hmac_reset( (sha2_context *) ctx ); -} - -void sha224_hmac_wrap( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - sha2_hmac( key, keylen, input, ilen, output, 1 ); -} - -void * sha224_ctx_alloc( void ) -{ - return malloc( sizeof( sha2_context ) ); -} - -void sha224_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const md_info_t sha224_info = { - POLARSSL_MD_SHA224, - "SHA224", - 28, - sha224_starts_wrap, - sha224_update_wrap, - sha224_finish_wrap, - sha224_wrap, - sha224_file_wrap, - sha224_hmac_starts_wrap, - sha224_hmac_update_wrap, - sha224_hmac_finish_wrap, - sha224_hmac_reset_wrap, - sha224_hmac_wrap, - sha224_ctx_alloc, - sha224_ctx_free, -}; - -void sha256_starts_wrap( void *ctx ) -{ - sha2_starts( (sha2_context *) ctx, 0 ); -} - -void sha256_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha2_update( (sha2_context *) ctx, input, ilen ); -} - -void sha256_finish_wrap( void *ctx, unsigned char *output ) -{ - sha2_finish( (sha2_context *) ctx, output ); -} - -void sha256_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - sha2( input, ilen, output, 0 ); -} - -int sha256_file_wrap( const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - return sha2_file( path, output, 0 ); -#else - ((void) path); - ((void) output); - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen ) -{ - sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 0 ); -} - -void sha256_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha2_hmac_update( (sha2_context *) ctx, input, ilen ); -} - -void sha256_hmac_finish_wrap( void *ctx, unsigned char *output ) -{ - sha2_hmac_finish( (sha2_context *) ctx, output ); -} - -void sha256_hmac_reset_wrap( void *ctx ) -{ - sha2_hmac_reset( (sha2_context *) ctx ); -} - -void sha256_hmac_wrap( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - sha2_hmac( key, keylen, input, ilen, output, 0 ); -} - -void * sha256_ctx_alloc( void ) -{ - return malloc( sizeof( sha2_context ) ); -} - -void sha256_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const md_info_t sha256_info = { - POLARSSL_MD_SHA256, - "SHA256", - 32, - sha256_starts_wrap, - sha256_update_wrap, - sha256_finish_wrap, - sha256_wrap, - sha256_file_wrap, - sha256_hmac_starts_wrap, - sha256_hmac_update_wrap, - sha256_hmac_finish_wrap, - sha256_hmac_reset_wrap, - sha256_hmac_wrap, - sha256_ctx_alloc, - sha256_ctx_free, -}; - -#endif - -#if defined(POLARSSL_SHA4_C) - -void sha384_starts_wrap( void *ctx ) -{ - sha4_starts( (sha4_context *) ctx, 1 ); -} - -void sha384_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha4_update( (sha4_context *) ctx, input, ilen ); -} - -void sha384_finish_wrap( void *ctx, unsigned char *output ) -{ - sha4_finish( (sha4_context *) ctx, output ); -} - -void sha384_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - sha4( input, ilen, output, 1 ); -} - -int sha384_file_wrap( const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - return sha4_file( path, output, 1 ); -#else - ((void) path); - ((void) output); - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen ) -{ - sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 1 ); -} - -void sha384_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha4_hmac_update( (sha4_context *) ctx, input, ilen ); -} - -void sha384_hmac_finish_wrap( void *ctx, unsigned char *output ) -{ - sha4_hmac_finish( (sha4_context *) ctx, output ); -} - -void sha384_hmac_reset_wrap( void *ctx ) -{ - sha4_hmac_reset( (sha4_context *) ctx ); -} - -void sha384_hmac_wrap( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - sha4_hmac( key, keylen, input, ilen, output, 1 ); -} - -void * sha384_ctx_alloc( void ) -{ - return malloc( sizeof( sha4_context ) ); -} - -void sha384_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const md_info_t sha384_info = { - POLARSSL_MD_SHA384, - "SHA384", - 48, - sha384_starts_wrap, - sha384_update_wrap, - sha384_finish_wrap, - sha384_wrap, - sha384_file_wrap, - sha384_hmac_starts_wrap, - sha384_hmac_update_wrap, - sha384_hmac_finish_wrap, - sha384_hmac_reset_wrap, - sha384_hmac_wrap, - sha384_ctx_alloc, - sha384_ctx_free, -}; - -void sha512_starts_wrap( void *ctx ) -{ - sha4_starts( (sha4_context *) ctx, 0 ); -} - -void sha512_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha4_update( (sha4_context *) ctx, input, ilen ); -} - -void sha512_finish_wrap( void *ctx, unsigned char *output ) -{ - sha4_finish( (sha4_context *) ctx, output ); -} - -void sha512_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - sha4( input, ilen, output, 0 ); -} - -int sha512_file_wrap( const char *path, unsigned char *output ) -{ -#if defined(POLARSSL_FS_IO) - return sha4_file( path, output, 0 ); -#else - ((void) path); - ((void) output); - return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE; -#endif -} - -void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen ) -{ - sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 0 ); -} - -void sha512_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) -{ - sha4_hmac_update( (sha4_context *) ctx, input, ilen ); -} - -void sha512_hmac_finish_wrap( void *ctx, unsigned char *output ) -{ - sha4_hmac_finish( (sha4_context *) ctx, output ); -} - -void sha512_hmac_reset_wrap( void *ctx ) -{ - sha4_hmac_reset( (sha4_context *) ctx ); -} - -void sha512_hmac_wrap( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - sha4_hmac( key, keylen, input, ilen, output, 0 ); -} - -void * sha512_ctx_alloc( void ) -{ - return malloc( sizeof( sha4_context ) ); -} - -void sha512_ctx_free( void *ctx ) -{ - free( ctx ); -} - -const md_info_t sha512_info = { - POLARSSL_MD_SHA512, - "SHA512", - 64, - sha512_starts_wrap, - sha512_update_wrap, - sha512_finish_wrap, - sha512_wrap, - sha512_file_wrap, - sha512_hmac_starts_wrap, - sha512_hmac_update_wrap, - sha512_hmac_finish_wrap, - sha512_hmac_reset_wrap, - sha512_hmac_wrap, - sha512_ctx_alloc, - sha512_ctx_free, -}; - -#endif - -#endif diff --git a/polarssl/src/library/net.c b/polarssl/src/library/net.c deleted file mode 100644 index e30aebb..0000000 --- a/polarssl/src/library/net.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * TCP networking functions - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_NET_C) - -#include "polarssl/net.h" - -#if defined(_WIN32) || defined(_WIN32_WCE) - -#include -#include - -#if defined(_WIN32_WCE) -#pragma comment( lib, "ws2.lib" ) -#else -#pragma comment( lib, "ws2_32.lib" ) -#endif - -#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0) -#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0) -#define close(fd) closesocket(fd) - -static int wsa_init_done = 0; - -#else - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__FreeBSD__) || defined(__OpenBSD__) -#include -#elif defined(__APPLE__) -#include -#elif defined(sun) -#include -#else -#include -#endif - -#endif - -#include -#include -#include - -/* - * htons() is not always available. - * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and __BIG_ENDIAN - * to help determine endianess. - */ -#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN -#define POLARSSL_HTONS(n) (n) -#else -#define POLARSSL_HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8)) -#endif - -unsigned short net_htons(unsigned short n); -#define net_htons(n) POLARSSL_HTONS(n) - -/* - * Initiate a TCP connection with host:port - */ -int net_connect( int *fd, const char *host, int port ) -{ - struct sockaddr_in server_addr; - struct hostent *server_host; - -#if defined(_WIN32) || defined(_WIN32_WCE) - WSADATA wsaData; - - if( wsa_init_done == 0 ) - { - if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR ) - return( POLARSSL_ERR_NET_SOCKET_FAILED ); - - wsa_init_done = 1; - } -#else - signal( SIGPIPE, SIG_IGN ); -#endif - - if( ( server_host = gethostbyname( host ) ) == NULL ) - return( POLARSSL_ERR_NET_UNKNOWN_HOST ); - - if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) - return( POLARSSL_ERR_NET_SOCKET_FAILED ); - - memcpy( (void *) &server_addr.sin_addr, - (void *) server_host->h_addr, - server_host->h_length ); - - server_addr.sin_family = AF_INET; - server_addr.sin_port = net_htons( port ); - - if( connect( *fd, (struct sockaddr *) &server_addr, - sizeof( server_addr ) ) < 0 ) - { - close( *fd ); - return( POLARSSL_ERR_NET_CONNECT_FAILED ); - } - - return( 0 ); -} - -/* - * Create a listening socket on bind_ip:port - */ -int net_bind( int *fd, const char *bind_ip, int port ) -{ - int n, c[4]; - struct sockaddr_in server_addr; - -#if defined(_WIN32) || defined(_WIN32_WCE) - WSADATA wsaData; - - if( wsa_init_done == 0 ) - { - if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR ) - return( POLARSSL_ERR_NET_SOCKET_FAILED ); - - wsa_init_done = 1; - } -#else - signal( SIGPIPE, SIG_IGN ); -#endif - - if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) - return( POLARSSL_ERR_NET_SOCKET_FAILED ); - - n = 1; - setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR, - (const char *) &n, sizeof( n ) ); - - server_addr.sin_addr.s_addr = INADDR_ANY; - server_addr.sin_family = AF_INET; - server_addr.sin_port = net_htons( port ); - - if( bind_ip != NULL ) - { - memset( c, 0, sizeof( c ) ); - sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] ); - - for( n = 0; n < 4; n++ ) - if( c[n] < 0 || c[n] > 255 ) - break; - - if( n == 4 ) - server_addr.sin_addr.s_addr = - ( (unsigned long) c[0] << 24 ) | - ( (unsigned long) c[1] << 16 ) | - ( (unsigned long) c[2] << 8 ) | - ( (unsigned long) c[3] ); - } - - if( bind( *fd, (struct sockaddr *) &server_addr, - sizeof( server_addr ) ) < 0 ) - { - close( *fd ); - return( POLARSSL_ERR_NET_BIND_FAILED ); - } - - if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 ) - { - close( *fd ); - return( POLARSSL_ERR_NET_LISTEN_FAILED ); - } - - return( 0 ); -} - -/* - * Check if the current operation is blocking - */ -static int net_is_blocking( void ) -{ -#if defined(_WIN32) || defined(_WIN32_WCE) - return( WSAGetLastError() == WSAEWOULDBLOCK ); -#else - switch( errno ) - { -#if defined EAGAIN - case EAGAIN: -#endif -#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: -#endif - return( 1 ); - } - return( 0 ); -#endif -} - -/* - * Accept a connection from a remote client - */ -int net_accept( int bind_fd, int *client_fd, void *client_ip ) -{ - struct sockaddr_in client_addr; - -#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ - defined(_SOCKLEN_T_DECLARED) - socklen_t n = (socklen_t) sizeof( client_addr ); -#else - int n = (int) sizeof( client_addr ); -#endif - - *client_fd = accept( bind_fd, (struct sockaddr *) - &client_addr, &n ); - - if( *client_fd < 0 ) - { - if( net_is_blocking() != 0 ) - return( POLARSSL_ERR_NET_WANT_READ ); - - return( POLARSSL_ERR_NET_ACCEPT_FAILED ); - } - - if( client_ip != NULL ) - memcpy( client_ip, &client_addr.sin_addr.s_addr, - sizeof( client_addr.sin_addr.s_addr ) ); - - return( 0 ); -} - -/* - * Set the socket blocking or non-blocking - */ -int net_set_block( int fd ) -{ -#if defined(_WIN32) || defined(_WIN32_WCE) - u_long n = 0; - return( ioctlsocket( fd, FIONBIO, &n ) ); -#else - return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) ); -#endif -} - -int net_set_nonblock( int fd ) -{ -#if defined(_WIN32) || defined(_WIN32_WCE) - u_long n = 1; - return( ioctlsocket( fd, FIONBIO, &n ) ); -#else - return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) ); -#endif -} - -/* - * Portable usleep helper - */ -void net_usleep( unsigned long usec ) -{ - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = usec; - select( 0, NULL, NULL, NULL, &tv ); -} - -/* - * Read at most 'len' characters - */ -int net_recv( void *ctx, unsigned char *buf, size_t len ) -{ - int ret = read( *((int *) ctx), buf, len ); - - if( ret < 0 ) - { - if( net_is_blocking() != 0 ) - return( POLARSSL_ERR_NET_WANT_READ ); - -#if defined(_WIN32) || defined(_WIN32_WCE) - if( WSAGetLastError() == WSAECONNRESET ) - return( POLARSSL_ERR_NET_CONN_RESET ); -#else - if( errno == EPIPE || errno == ECONNRESET ) - return( POLARSSL_ERR_NET_CONN_RESET ); - - if( errno == EINTR ) - return( POLARSSL_ERR_NET_WANT_READ ); -#endif - - return( POLARSSL_ERR_NET_RECV_FAILED ); - } - - return( ret ); -} - -/* - * Write at most 'len' characters - */ -int net_send( void *ctx, const unsigned char *buf, size_t len ) -{ - int ret = write( *((int *) ctx), buf, len ); - - if( ret < 0 ) - { - if( net_is_blocking() != 0 ) - return( POLARSSL_ERR_NET_WANT_WRITE ); - -#if defined(_WIN32) || defined(_WIN32_WCE) - if( WSAGetLastError() == WSAECONNRESET ) - return( POLARSSL_ERR_NET_CONN_RESET ); -#else - if( errno == EPIPE || errno == ECONNRESET ) - return( POLARSSL_ERR_NET_CONN_RESET ); - - if( errno == EINTR ) - return( POLARSSL_ERR_NET_WANT_WRITE ); -#endif - - return( POLARSSL_ERR_NET_SEND_FAILED ); - } - - return( ret ); -} - -/* - * Gracefully close the connection - */ -void net_close( int fd ) -{ - shutdown( fd, 2 ); - close( fd ); -} - -#endif diff --git a/polarssl/src/library/padlock.c b/polarssl/src/library/padlock.c deleted file mode 100644 index 2e2e477..0000000 --- a/polarssl/src/library/padlock.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * VIA PadLock support functions - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * This implementation is based on the VIA PadLock Programming Guide: - * - * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ - * programming_guide.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_PADLOCK_C) - -#include "polarssl/padlock.h" - -#if defined(POLARSSL_HAVE_X86) - -/* - * PadLock detection routine - */ -int padlock_supports( int feature ) -{ - static int flags = -1; - int ebx, edx; - - if( flags == -1 ) - { - asm( "movl %%ebx, %0 \n" \ - "movl $0xC0000000, %%eax \n" \ - "cpuid \n" \ - "cmpl $0xC0000001, %%eax \n" \ - "movl $0, %%edx \n" \ - "jb unsupported \n" \ - "movl $0xC0000001, %%eax \n" \ - "cpuid \n" \ - "unsupported: \n" \ - "movl %%edx, %1 \n" \ - "movl %2, %%ebx \n" - : "=m" (ebx), "=m" (edx) - : "m" (ebx) - : "eax", "ecx", "edx" ); - - flags = edx; - } - - return( flags & feature ); -} - -/* - * PadLock AES-ECB block en(de)cryption - */ -int padlock_xcryptecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int ebx; - unsigned long *rk; - unsigned long *blk; - unsigned long *ctrl; - unsigned char buf[256]; - - rk = ctx->rk; - blk = PADLOCK_ALIGN16( buf ); - memcpy( blk, input, 16 ); - - ctrl = blk + 4; - *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); - - asm( "pushfl; popfl \n" \ - "movl %%ebx, %0 \n" \ - "movl $1, %%ecx \n" \ - "movl %2, %%edx \n" \ - "movl %3, %%ebx \n" \ - "movl %4, %%esi \n" \ - "movl %4, %%edi \n" \ - ".byte 0xf3,0x0f,0xa7,0xc8\n" \ - "movl %1, %%ebx \n" - : "=m" (ebx) - : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) - : "ecx", "edx", "esi", "edi" ); - - memcpy( output, blk, 16 ); - - return( 0 ); -} - -/* - * PadLock AES-CBC buffer en(de)cryption - */ -int padlock_xcryptcbc( aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int ebx; - size_t count; - unsigned long *rk; - unsigned long *iw; - unsigned long *ctrl; - unsigned char buf[256]; - - if( ( (long) input & 15 ) != 0 || - ( (long) output & 15 ) != 0 ) - return( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED ); - - rk = ctx->rk; - iw = PADLOCK_ALIGN16( buf ); - memcpy( iw, iv, 16 ); - - ctrl = iw + 4; - *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 ); - - count = (length + 15) >> 4; - - asm( "pushfl; popfl \n" \ - "movl %%ebx, %0 \n" \ - "movl %2, %%ecx \n" \ - "movl %3, %%edx \n" \ - "movl %4, %%ebx \n" \ - "movl %5, %%esi \n" \ - "movl %6, %%edi \n" \ - "movl %7, %%eax \n" \ - ".byte 0xf3,0x0f,0xa7,0xd0\n" \ - "movl %1, %%ebx \n" - : "=m" (ebx) - : "m" (ebx), "m" (count), "m" (ctrl), - "m" (rk), "m" (input), "m" (output), "m" (iw) - : "eax", "ecx", "edx", "esi", "edi" ); - - memcpy( iv, iw, 16 ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/pem.c b/polarssl/src/library/pem.c deleted file mode 100644 index 33e74ab..0000000 --- a/polarssl/src/library/pem.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Privacy Enhanced Mail (PEM) decoding - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_PEM_C) - -#include "polarssl/pem.h" -#include "polarssl/base64.h" -#include "polarssl/des.h" -#include "polarssl/aes.h" -#include "polarssl/md5.h" -#include "polarssl/cipher.h" - -#include - -void pem_init( pem_context *ctx ) -{ - memset( ctx, 0, sizeof( pem_context ) ); -} - -#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C)) -/* - * Read a 16-byte hex string and convert it to binary - */ -static int pem_get_iv( const unsigned char *s, unsigned char *iv, size_t iv_len ) -{ - size_t i, j, k; - - memset( iv, 0, iv_len ); - - for( i = 0; i < iv_len * 2; i++, s++ ) - { - if( *s >= '0' && *s <= '9' ) j = *s - '0'; else - if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else - if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else - return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); - - k = ( ( i & 1 ) != 0 ) ? j : j << 4; - - iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); - } - - return( 0 ); -} - -static void pem_pbkdf1( unsigned char *key, size_t keylen, - unsigned char *iv, - const unsigned char *pwd, size_t pwdlen ) -{ - md5_context md5_ctx; - unsigned char md5sum[16]; - size_t use_len; - - /* - * key[ 0..15] = MD5(pwd || IV) - */ - md5_starts( &md5_ctx ); - md5_update( &md5_ctx, pwd, pwdlen ); - md5_update( &md5_ctx, iv, 8 ); - md5_finish( &md5_ctx, md5sum ); - - if( keylen <= 16 ) - { - memcpy( key, md5sum, keylen ); - - memset( &md5_ctx, 0, sizeof( md5_ctx ) ); - memset( md5sum, 0, 16 ); - return; - } - - memcpy( key, md5sum, 16 ); - - /* - * key[16..23] = MD5(key[ 0..15] || pwd || IV]) - */ - md5_starts( &md5_ctx ); - md5_update( &md5_ctx, md5sum, 16 ); - md5_update( &md5_ctx, pwd, pwdlen ); - md5_update( &md5_ctx, iv, 8 ); - md5_finish( &md5_ctx, md5sum ); - - use_len = 16; - if( keylen < 32 ) - use_len = keylen - 16; - - memcpy( key + 16, md5sum, use_len ); - - memset( &md5_ctx, 0, sizeof( md5_ctx ) ); - memset( md5sum, 0, 16 ); -} - -#if defined(POLARSSL_DES_C) -/* - * Decrypt with DES-CBC, using PBKDF1 for key derivation - */ -static void pem_des_decrypt( unsigned char des_iv[8], - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - des_context des_ctx; - unsigned char des_key[8]; - - pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); - - des_setkey_dec( &des_ctx, des_key ); - des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen, - des_iv, buf, buf ); - - memset( &des_ctx, 0, sizeof( des_ctx ) ); - memset( des_key, 0, 8 ); -} - -/* - * Decrypt with 3DES-CBC, using PBKDF1 for key derivation - */ -static void pem_des3_decrypt( unsigned char des3_iv[8], - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - des3_context des3_ctx; - unsigned char des3_key[24]; - - pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); - - des3_set3key_dec( &des3_ctx, des3_key ); - des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen, - des3_iv, buf, buf ); - - memset( &des3_ctx, 0, sizeof( des3_ctx ) ); - memset( des3_key, 0, 24 ); -} -#endif /* POLARSSL_DES_C */ - -#if defined(POLARSSL_AES_C) -/* - * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation - */ -static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - aes_context aes_ctx; - unsigned char aes_key[32]; - - pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); - - aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); - aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen, - aes_iv, buf, buf ); - - memset( &aes_ctx, 0, sizeof( aes_ctx ) ); - memset( aes_key, 0, keylen ); -} -#endif /* POLARSSL_AES_C */ - -#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */ - -int pem_read_buffer( pem_context *ctx, char *header, char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len ) -{ - int ret, enc; - size_t len; - unsigned char *buf; - unsigned char *s1, *s2; -#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C)) - unsigned char pem_iv[16]; - cipher_type_t enc_alg = POLARSSL_CIPHER_NONE; -#else - ((void) pwd); - ((void) pwdlen); -#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */ - - if( ctx == NULL ) - return( POLARSSL_ERR_PEM_INVALID_DATA ); - - s1 = (unsigned char *) strstr( (char *) data, header ); - - if( s1 == NULL ) - return( POLARSSL_ERR_PEM_NO_HEADER_PRESENT ); - - s2 = (unsigned char *) strstr( (char *) data, footer ); - - if( s2 == NULL || s2 <= s1 ) - return( POLARSSL_ERR_PEM_INVALID_DATA ); - - s1 += strlen( header ); - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( POLARSSL_ERR_PEM_INVALID_DATA ); - - enc = 0; - - if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) - { -#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C)) - enc++; - - s1 += 22; - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( POLARSSL_ERR_PEM_INVALID_DATA ); - - -#if defined(POLARSSL_DES_C) - if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) - { - enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC; - - s1 += 23; - if( pem_get_iv( s1, pem_iv, 8 ) != 0 ) - return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); - - s1 += 16; - } - else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) - { - enc_alg = POLARSSL_CIPHER_DES_CBC; - - s1 += 18; - if( pem_get_iv( s1, pem_iv, 8) != 0 ) - return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); - - s1 += 16; - } -#endif /* POLARSSL_DES_C */ - -#if defined(POLARSSL_AES_C) - if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) - { - if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) - enc_alg = POLARSSL_CIPHER_AES_128_CBC; - else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) - enc_alg = POLARSSL_CIPHER_AES_192_CBC; - else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) - enc_alg = POLARSSL_CIPHER_AES_256_CBC; - else - return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG ); - - s1 += 22; - if( pem_get_iv( s1, pem_iv, 16 ) != 0 ) - return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); - - s1 += 32; - } -#endif /* POLARSSL_AES_C */ - - if( enc_alg == POLARSSL_CIPHER_NONE ) - return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG ); - - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( POLARSSL_ERR_PEM_INVALID_DATA ); -#else - return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); -#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */ - } - - len = 0; - ret = base64_decode( NULL, &len, s1, s2 - s1 ); - - if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER ) - return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); - - if( ( buf = (unsigned char *) malloc( len ) ) == NULL ) - return( POLARSSL_ERR_PEM_MALLOC_FAILED ); - - if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 ) - { - free( buf ); - return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); - } - - if( enc != 0 ) - { -#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C)) - if( pwd == NULL ) - { - free( buf ); - return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED ); - } - -#if defined(POLARSSL_DES_C) - if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC ) - pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); - else if( enc_alg == POLARSSL_CIPHER_DES_CBC ) - pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); -#endif /* POLARSSL_DES_C */ - -#if defined(POLARSSL_AES_C) - if( enc_alg == POLARSSL_CIPHER_AES_128_CBC ) - pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); - else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC ) - pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); - else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC ) - pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); -#endif /* POLARSSL_AES_C */ - - if( buf[0] != 0x30 || buf[1] != 0x82 || - buf[4] != 0x02 || buf[5] != 0x01 ) - { - free( buf ); - return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH ); - } -#else - return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); -#endif - } - - ctx->buf = buf; - ctx->buflen = len; - s2 += strlen( footer ); - if( *s2 == '\r' ) s2++; - if( *s2 == '\n' ) s2++; - *use_len = s2 - data; - - return( 0 ); -} - -void pem_free( pem_context *ctx ) -{ - if( ctx->buf ) - free( ctx->buf ); - - if( ctx->info ) - free( ctx->info ); - - memset( ctx, 0, sizeof( pem_context ) ); -} - -#endif diff --git a/polarssl/src/library/pkcs11.c b/polarssl/src/library/pkcs11.c deleted file mode 100644 index b71415a..0000000 --- a/polarssl/src/library/pkcs11.c +++ /dev/null @@ -1,238 +0,0 @@ -/** - * \file pkcs11.c - * - * \brief Wrapper for PKCS#11 library libpkcs11-helper - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/pkcs11.h" - -#if defined(POLARSSL_PKCS11_C) - -#include - -int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11_cert ) -{ - int ret = 1; - unsigned char *cert_blob = NULL; - size_t cert_blob_size = 0; - - if( cert == NULL ) - { - ret = 2; - goto cleanup; - } - - if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, &cert_blob_size ) != CKR_OK ) - { - ret = 3; - goto cleanup; - } - - cert_blob = malloc( cert_blob_size ); - if( NULL == cert_blob ) - { - ret = 4; - goto cleanup; - } - - if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, &cert_blob_size ) != CKR_OK ) - { - ret = 5; - goto cleanup; - } - - if( 0 != x509parse_crt(cert, cert_blob, cert_blob_size ) ) - { - ret = 6; - goto cleanup; - } - - ret = 0; - -cleanup: - if( NULL != cert_blob ) - free( cert_blob ); - - return ret; -} - - -int pkcs11_priv_key_init( pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert ) -{ - int ret = 1; - x509_cert cert; - - memset( &cert, 0, sizeof( cert ) ); - - if( priv_key == NULL ) - goto cleanup; - - if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) ) - goto cleanup; - - priv_key->len = cert.rsa.len; - priv_key->pkcs11h_cert = pkcs11_cert; - - ret = 0; - -cleanup: - x509_free( &cert ); - - return ret; -} - -void pkcs11_priv_key_free( pkcs11_context *priv_key ) -{ - if( NULL != priv_key ) - pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); -} - -int pkcs11_decrypt( pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - unsigned int output_max_len ) -{ - size_t input_len, output_len; - - if( NULL == ctx ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - if( RSA_PUBLIC == mode ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - output_len = input_len = ctx->len; - - if( input_len < 16 || input_len > output_max_len ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - /* Determine size of output buffer */ - if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, - input_len, NULL, &output_len ) != CKR_OK ) - { - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - if( output_len > output_max_len ) - return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); - - if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, - input_len, output, &output_len ) != CKR_OK ) - { - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - *olen = output_len; - return( 0 ); -} - -int pkcs11_sign( pkcs11_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t olen, asn_len; - unsigned char *p = sig; - - if( NULL == ctx ) - return POLARSSL_ERR_RSA_BAD_INPUT_DATA; - - if( RSA_PUBLIC == mode ) - return POLARSSL_ERR_RSA_BAD_INPUT_DATA; - - olen = ctx->len; - - switch( hash_id ) - { - case SIG_RSA_RAW: - asn_len = 0; - memcpy( p, hash, hashlen ); - break; - - case SIG_RSA_MD2: - asn_len = OID_SIZE(ASN1_HASH_MDX); - memcpy( p, ASN1_HASH_MDX, asn_len ); - memcpy( p + asn_len, hash, hashlen ); - p[13] = 2; break; - - case SIG_RSA_MD4: - asn_len = OID_SIZE(ASN1_HASH_MDX); - memcpy( p, ASN1_HASH_MDX, asn_len ); - memcpy( p + asn_len, hash, hashlen ); - p[13] = 4; break; - - case SIG_RSA_MD5: - asn_len = OID_SIZE(ASN1_HASH_MDX); - memcpy( p, ASN1_HASH_MDX, asn_len ); - memcpy( p + asn_len, hash, hashlen ); - p[13] = 5; break; - - case SIG_RSA_SHA1: - asn_len = OID_SIZE(ASN1_HASH_SHA1); - memcpy( p, ASN1_HASH_SHA1, asn_len ); - memcpy( p + 15, hash, hashlen ); - break; - - case SIG_RSA_SHA224: - asn_len = OID_SIZE(ASN1_HASH_SHA2X); - memcpy( p, ASN1_HASH_SHA2X, asn_len ); - memcpy( p + asn_len, hash, hashlen ); - p[1] += hashlen; p[14] = 4; p[18] += hashlen; break; - - case SIG_RSA_SHA256: - asn_len = OID_SIZE(ASN1_HASH_SHA2X); - memcpy( p, ASN1_HASH_SHA2X, asn_len ); - memcpy( p + asn_len, hash, hashlen ); - p[1] += hashlen; p[14] = 1; p[18] += hashlen; break; - - case SIG_RSA_SHA384: - asn_len = OID_SIZE(ASN1_HASH_SHA2X); - memcpy( p, ASN1_HASH_SHA2X, asn_len ); - memcpy( p + asn_len, hash, hashlen ); - p[1] += hashlen; p[14] = 2; p[18] += hashlen; break; - - case SIG_RSA_SHA512: - asn_len = OID_SIZE(ASN1_HASH_SHA2X); - memcpy( p, ASN1_HASH_SHA2X, asn_len ); - memcpy( p + asn_len, hash, hashlen ); - p[1] += hashlen; p[14] = 3; p[18] += hashlen; break; - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, - asn_len + hashlen, sig, &olen ) != CKR_OK ) - { - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - return( 0 ); -} - -#endif /* defined(POLARSSL_PKCS11_C) */ diff --git a/polarssl/src/library/rsa.c b/polarssl/src/library/rsa.c deleted file mode 100644 index 72806e1..0000000 --- a/polarssl/src/library/rsa.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* - * The RSA public-key cryptosystem - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. - * - * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf - * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_RSA_C) - -#include "polarssl/rsa.h" -#include "polarssl/md.h" - -#include -#include - -/* - * Initialize an RSA context - */ -void rsa_init( rsa_context *ctx, - int padding, - int hash_id ) -{ - memset( ctx, 0, sizeof( rsa_context ) ); - - ctx->padding = padding; - ctx->hash_id = hash_id; -} - -#if defined(POLARSSL_GENPRIME) - -/* - * Generate an RSA keypair - */ -int rsa_gen_key( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ) -{ - int ret; - mpi P1, Q1, H, G; - - if( f_rng == NULL || nbits < 128 || exponent < 3 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G ); - - /* - * find primes P and Q with Q < P so that: - * GCD( E, (P-1)*(Q-1) ) == 1 - */ - MPI_CHK( mpi_lset( &ctx->E, exponent ) ); - - do - { - MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, - f_rng, p_rng ) ); - - MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, - f_rng, p_rng ) ); - - if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) - mpi_swap( &ctx->P, &ctx->Q ); - - if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) - continue; - - MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); - if( mpi_msb( &ctx->N ) != nbits ) - continue; - - MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); - MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); - MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); - } - while( mpi_cmp_int( &G, 1 ) != 0 ); - - /* - * D = E^-1 mod ((P-1)*(Q-1)) - * DP = D mod (P - 1) - * DQ = D mod (Q - 1) - * QP = Q^-1 mod P - */ - MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); - MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); - MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); - MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); - - ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; - -cleanup: - - mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G ); - - if( ret != 0 ) - { - rsa_free( ctx ); - return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret ); - } - - return( 0 ); -} - -#endif - -/* - * Check a public RSA key - */ -int rsa_check_pubkey( const rsa_context *ctx ) -{ - if( !ctx->N.p || !ctx->E.p ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( ( ctx->N.p[0] & 1 ) == 0 || - ( ctx->E.p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( mpi_msb( &ctx->N ) < 128 || - mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( mpi_msb( &ctx->E ) < 2 || - mpi_msb( &ctx->E ) > 64 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - return( 0 ); -} - -/* - * Check a private RSA key - */ -int rsa_check_privkey( const rsa_context *ctx ) -{ - int ret; - mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2; - - if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) - return( ret ); - - if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 ); - mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 ); - mpi_init( &L1 ); mpi_init( &L2 ); - - MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); - MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); - MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); - MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); - MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); - - MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) ); - MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) ); - MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) ); - - /* - * Check for a valid PKCS1v2 private key - */ - if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || - mpi_cmp_int( &L2, 0 ) != 0 || - mpi_cmp_int( &I, 1 ) != 0 || - mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED; - } - - -cleanup: - - mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 ); - mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 ); - mpi_free( &L1 ); mpi_free( &L2 ); - - if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED ) - return( ret ); - - if( ret != 0 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret ); - - return( 0 ); -} - -/* - * Do an RSA public key operation - */ -int rsa_public( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - size_t olen; - mpi T; - - mpi_init( &T ); - - MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); - - if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - mpi_free( &T ); - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - olen = ctx->len; - MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); - MPI_CHK( mpi_write_binary( &T, output, olen ) ); - -cleanup: - - mpi_free( &T ); - - if( ret != 0 ) - return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Do an RSA private key operation - */ -int rsa_private( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - size_t olen; - mpi T, T1, T2; - - mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); - - MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); - - if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - mpi_free( &T ); - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - -#if defined(POLARSSL_RSA_NO_CRT) - MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); -#else - /* - * faster decryption using the CRT - * - * T1 = input ^ dP mod P - * T2 = input ^ dQ mod Q - */ - MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); - MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); - - /* - * T = (T1 - T2) * (Q^-1 mod P) mod P - */ - MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); - MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); - MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); - - /* - * output = T2 + T * Q - */ - MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); - MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); -#endif - - olen = ctx->len; - MPI_CHK( mpi_write_binary( &T, output, olen ) ); - -cleanup: - - mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 ); - - if( ret != 0 ) - return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret ); - - return( 0 ); -} - -#if defined(POLARSSL_PKCS1_V21) -/** - * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. - * - * \param dst buffer to mask - * \param dlen length of destination buffer - * \param src source of the mask generation - * \param slen length of the source buffer - * \param md_ctx message digest context to use - */ -static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen, - md_context_t *md_ctx ) -{ - unsigned char mask[POLARSSL_MD_MAX_SIZE]; - unsigned char counter[4]; - unsigned char *p; - unsigned int hlen; - size_t i, use_len; - - memset( mask, 0, POLARSSL_MD_MAX_SIZE ); - memset( counter, 0, 4 ); - - hlen = md_ctx->md_info->size; - - // Generate and apply dbMask - // - p = dst; - - while( dlen > 0 ) - { - use_len = hlen; - if( dlen < hlen ) - use_len = dlen; - - md_starts( md_ctx ); - md_update( md_ctx, src, slen ); - md_update( md_ctx, counter, 4 ); - md_finish( md_ctx, mask ); - - for( i = 0; i < use_len; ++i ) - *p++ ^= mask[i]; - - counter[3]++; - - dlen -= use_len; - } -} -#endif - -/* - * Add the message padding, then do an RSA operation - */ -int rsa_pkcs1_encrypt( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - size_t nb_pad, olen; - int ret; - unsigned char *p = output; -#if defined(POLARSSL_PKCS1_V21) - unsigned int hlen; - const md_info_t *md_info; - md_context_t md_ctx; -#endif - - olen = ctx->len; - - if( f_rng == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - switch( ctx->padding ) - { - case RSA_PKCS_V15: - - if( olen < ilen + 11 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - nb_pad = olen - 3 - ilen; - - *p++ = 0; - *p++ = RSA_CRYPT; - - while( nb_pad-- > 0 ) - { - int rng_dl = 100; - - do { - ret = f_rng( p_rng, p, 1 ); - } while( *p == 0 && --rng_dl && ret == 0 ); - - // Check if RNG failed to generate data - // - if( rng_dl == 0 || ret != 0) - return POLARSSL_ERR_RSA_RNG_FAILED + ret; - - p++; - } - *p++ = 0; - memcpy( p, input, ilen ); - break; - -#if defined(POLARSSL_PKCS1_V21) - case RSA_PKCS_V21: - - md_info = md_info_from_type( ctx->hash_id ); - if( md_info == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - hlen = md_get_size( md_info ); - - if( olen < ilen + 2 * hlen + 2 || f_rng == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - memset( output, 0, olen ); - memset( &md_ctx, 0, sizeof( md_context_t ) ); - - md_init_ctx( &md_ctx, md_info ); - - *p++ = 0; - - // Generate a random octet string seed - // - if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) - return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); - - p += hlen; - - // Construct DB - // - md( md_info, p, 0, p ); - p += hlen; - p += olen - 2 * hlen - 2 - ilen; - *p++ = 1; - memcpy( p, input, ilen ); - - // maskedDB: Apply dbMask to DB - // - mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, - &md_ctx ); - - // maskedSeed: Apply seedMask to seed - // - mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, - &md_ctx ); - break; -#endif - - default: - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - return( ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, output, output ) - : rsa_private( ctx, output, output ) ); -} - -/* - * Do an RSA operation, then remove the message padding - */ -int rsa_pkcs1_decrypt( rsa_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - int ret; - size_t ilen; - unsigned char *p; - unsigned char buf[1024]; -#if defined(POLARSSL_PKCS1_V21) - unsigned char lhash[POLARSSL_MD_MAX_SIZE]; - unsigned int hlen; - const md_info_t *md_info; - md_context_t md_ctx; -#endif - - ilen = ctx->len; - - if( ilen < 16 || ilen > sizeof( buf ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, input, buf ) - : rsa_private( ctx, input, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - switch( ctx->padding ) - { - case RSA_PKCS_V15: - - if( *p++ != 0 || *p++ != RSA_CRYPT ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - while( *p != 0 ) - { - if( p >= buf + ilen - 1 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - p++; - } - p++; - break; - -#if defined(POLARSSL_PKCS1_V21) - case RSA_PKCS_V21: - - if( *p++ != 0 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - md_info = md_info_from_type( ctx->hash_id ); - if( md_info == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - hlen = md_get_size( md_info ); - memset( &md_ctx, 0, sizeof( md_context_t ) ); - - md_init_ctx( &md_ctx, md_info ); - - // Generate lHash - // - md( md_info, lhash, 0, lhash ); - - // seed: Apply seedMask to maskedSeed - // - mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, - &md_ctx ); - - // DB: Apply dbMask to maskedDB - // - mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, - &md_ctx ); - - p += hlen; - - // Check validity - // - if( memcmp( lhash, p, hlen ) != 0 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - p += hlen; - - while( *p == 0 && p < buf + ilen ) - p++; - - if( p == buf + ilen ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - if( *p++ != 0x01 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - break; -#endif - - default: - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - if (ilen - (p - buf) > output_max_len) - return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); - - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); - - return( 0 ); -} - -/* - * Do an RSA operation to sign the message digest - */ -int rsa_pkcs1_sign( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t nb_pad, olen; - unsigned char *p = sig; -#if defined(POLARSSL_PKCS1_V21) - unsigned char salt[POLARSSL_MD_MAX_SIZE]; - unsigned int slen, hlen, offset = 0; - int ret; - size_t msb; - const md_info_t *md_info; - md_context_t md_ctx; -#else - (void) f_rng; - (void) p_rng; -#endif - - olen = ctx->len; - - switch( ctx->padding ) - { - case RSA_PKCS_V15: - - switch( hash_id ) - { - case SIG_RSA_RAW: - nb_pad = olen - 3 - hashlen; - break; - - case SIG_RSA_MD2: - case SIG_RSA_MD4: - case SIG_RSA_MD5: - nb_pad = olen - 3 - 34; - break; - - case SIG_RSA_SHA1: - nb_pad = olen - 3 - 35; - break; - - case SIG_RSA_SHA224: - nb_pad = olen - 3 - 47; - break; - - case SIG_RSA_SHA256: - nb_pad = olen - 3 - 51; - break; - - case SIG_RSA_SHA384: - nb_pad = olen - 3 - 67; - break; - - case SIG_RSA_SHA512: - nb_pad = olen - 3 - 83; - break; - - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - if( nb_pad < 8 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - *p++ = 0; - *p++ = RSA_SIGN; - memset( p, 0xFF, nb_pad ); - p += nb_pad; - *p++ = 0; - - switch( hash_id ) - { - case SIG_RSA_RAW: - memcpy( p, hash, hashlen ); - break; - - case SIG_RSA_MD2: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 2; break; - - case SIG_RSA_MD4: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 4; break; - - case SIG_RSA_MD5: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 5; break; - - case SIG_RSA_SHA1: - memcpy( p, ASN1_HASH_SHA1, 15 ); - memcpy( p + 15, hash, 20 ); - break; - - case SIG_RSA_SHA224: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 28 ); - p[1] += 28; p[14] = 4; p[18] += 28; break; - - case SIG_RSA_SHA256: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 32 ); - p[1] += 32; p[14] = 1; p[18] += 32; break; - - case SIG_RSA_SHA384: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 48 ); - p[1] += 48; p[14] = 2; p[18] += 48; break; - - case SIG_RSA_SHA512: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 64 ); - p[1] += 64; p[14] = 3; p[18] += 64; break; - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - break; - -#if defined(POLARSSL_PKCS1_V21) - case RSA_PKCS_V21: - - if( f_rng == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - switch( hash_id ) - { - case SIG_RSA_MD2: - case SIG_RSA_MD4: - case SIG_RSA_MD5: - hashlen = 16; - break; - - case SIG_RSA_SHA1: - hashlen = 20; - break; - - case SIG_RSA_SHA224: - hashlen = 28; - break; - - case SIG_RSA_SHA256: - hashlen = 32; - break; - - case SIG_RSA_SHA384: - hashlen = 48; - break; - - case SIG_RSA_SHA512: - hashlen = 64; - break; - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - md_info = md_info_from_type( ctx->hash_id ); - if( md_info == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - hlen = md_get_size( md_info ); - slen = hlen; - - memset( sig, 0, olen ); - memset( &md_ctx, 0, sizeof( md_context_t ) ); - - md_init_ctx( &md_ctx, md_info ); - - msb = mpi_msb( &ctx->N ) - 1; - - // Generate salt of length slen - // - if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) - return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); - - // Note: EMSA-PSS encoding is over the length of N - 1 bits - // - msb = mpi_msb( &ctx->N ) - 1; - p += olen - hlen * 2 - 2; - *p++ = 0x01; - memcpy( p, salt, slen ); - p += slen; - - // Generate H = Hash( M' ) - // - md_starts( &md_ctx ); - md_update( &md_ctx, p, 8 ); - md_update( &md_ctx, hash, hashlen ); - md_update( &md_ctx, salt, slen ); - md_finish( &md_ctx, p ); - - // Compensate for boundary condition when applying mask - // - if( msb % 8 == 0 ) - offset = 1; - - // maskedDB: Apply dbMask to DB - // - mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); - - msb = mpi_msb( &ctx->N ) - 1; - sig[0] &= 0xFF >> ( olen * 8 - msb ); - - p += hlen; - *p++ = 0xBC; - break; -#endif - - default: - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - return( ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, sig, sig ) - : rsa_private( ctx, sig, sig ) ); -} - -/* - * Do an RSA operation and check the message digest - */ -int rsa_pkcs1_verify( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - int ret; - size_t len, siglen; - unsigned char *p, c; - unsigned char buf[1024]; -#if defined(POLARSSL_PKCS1_V21) - unsigned char result[POLARSSL_MD_MAX_SIZE]; - unsigned char zeros[8]; - unsigned int hlen; - size_t slen, msb; - const md_info_t *md_info; - md_context_t md_ctx; -#endif - siglen = ctx->len; - - if( siglen < 16 || siglen > sizeof( buf ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, sig, buf ) - : rsa_private( ctx, sig, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - switch( ctx->padding ) - { - case RSA_PKCS_V15: - - if( *p++ != 0 || *p++ != RSA_SIGN ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - while( *p != 0 ) - { - if( p >= buf + siglen - 1 || *p != 0xFF ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - p++; - } - p++; - - len = siglen - ( p - buf ); - - if( len == 33 && hash_id == SIG_RSA_SHA1 ) - { - if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 && - memcmp( p + 13, hash, 20 ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - if( len == 34 ) - { - c = p[13]; - p[13] = 0; - - if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 ) - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - - if( ( c == 2 && hash_id == SIG_RSA_MD2 ) || - ( c == 4 && hash_id == SIG_RSA_MD4 ) || - ( c == 5 && hash_id == SIG_RSA_MD5 ) ) - { - if( memcmp( p + 18, hash, 16 ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - } - - if( len == 35 && hash_id == SIG_RSA_SHA1 ) - { - if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 && - memcmp( p + 15, hash, 20 ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) || - ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) || - ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) || - ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) ) - { - c = p[1] - 17; - p[1] = 17; - p[14] = 0; - - if( p[18] == c && - memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 && - memcmp( p + 19, hash, c ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - - if( len == hashlen && hash_id == SIG_RSA_RAW ) - { - if( memcmp( p, hash, hashlen ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - - break; - -#if defined(POLARSSL_PKCS1_V21) - case RSA_PKCS_V21: - - if( buf[siglen - 1] != 0xBC ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - switch( hash_id ) - { - case SIG_RSA_MD2: - case SIG_RSA_MD4: - case SIG_RSA_MD5: - hashlen = 16; - break; - - case SIG_RSA_SHA1: - hashlen = 20; - break; - - case SIG_RSA_SHA224: - hashlen = 28; - break; - - case SIG_RSA_SHA256: - hashlen = 32; - break; - - case SIG_RSA_SHA384: - hashlen = 48; - break; - - case SIG_RSA_SHA512: - hashlen = 64; - break; - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - md_info = md_info_from_type( ctx->hash_id ); - if( md_info == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - hlen = md_get_size( md_info ); - slen = siglen - hlen - 1; - - memset( &md_ctx, 0, sizeof( md_context_t ) ); - memset( zeros, 0, 8 ); - - md_init_ctx( &md_ctx, md_info ); - - // Note: EMSA-PSS verification is over the length of N - 1 bits - // - msb = mpi_msb( &ctx->N ) - 1; - - // Compensate for boundary condition when applying mask - // - if( msb % 8 == 0 ) - { - p++; - siglen -= 1; - } - if( buf[0] >> ( 8 - siglen * 8 + msb ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); - - buf[0] &= 0xFF >> ( siglen * 8 - msb ); - - while( *p == 0 && p < buf + siglen ) - p++; - - if( p == buf + siglen ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - if( *p++ != 0x01 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - slen -= p - buf; - - // Generate H = Hash( M' ) - // - md_starts( &md_ctx ); - md_update( &md_ctx, zeros, 8 ); - md_update( &md_ctx, hash, hashlen ); - md_update( &md_ctx, p, slen ); - md_finish( &md_ctx, result ); - - if( memcmp( p + slen, result, hlen ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); -#endif - - default: - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); -} - -/* - * Free the components of an RSA key - */ -void rsa_free( rsa_context *ctx ) -{ - mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN ); - mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP ); - mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D ); - mpi_free( &ctx->E ); mpi_free( &ctx->N ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include "polarssl/sha1.h" - -/* - * Example RSA-1024 keypair, for test purposes - */ -#define KEY_LEN 128 - -#define RSA_N "9292758453063D803DD603D5E777D788" \ - "8ED1D5BF35786190FA2F23EBC0848AEA" \ - "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ - "7130B9CED7ACDF54CFC7555AC14EEBAB" \ - "93A89813FBF3C4F8066D2D800F7C38A8" \ - "1AE31942917403FF4946B0A83D3D3E05" \ - "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ - "5E94BB77B07507233A0BC7BAC8F90F79" - -#define RSA_E "10001" - -#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ - "66CA472BC44D253102F8B4A9D3BFA750" \ - "91386C0077937FE33FA3252D28855837" \ - "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ - "DF79C5CE07EE72C7F123142198164234" \ - "CABB724CF78B8173B9F880FC86322407" \ - "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ - "071513A1E85B5DFA031F21ECAE91A34D" - -#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ - "2C01CAD19EA484A87EA4377637E75500" \ - "FCB2005C5C7DD6EC4AC023CDA285D796" \ - "C3D9E75E1EFC42488BB4F1D13AC30A57" - -#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ - "E211C2B9E5DB1ED0BF61D0D9899620F4" \ - "910E4168387E3C30AA1E00C339A79508" \ - "8452DD96A9A5EA5D9DCA68DA636032AF" - -#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ - "3C94D22288ACD763FD8E5600ED4A702D" \ - "F84198A5F06C2E72236AE490C93F07F8" \ - "3CC559CD27BC2D1CA488811730BB5725" - -#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ - "D8AAEA56749EA28623272E4F7D0592AF" \ - "7C1F1313CAC9471B5C523BFE592F517B" \ - "407A1BD76C164B93DA2D32A383E58357" - -#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ - "F38D18D2B2F0E2DD275AA977E2BF4411" \ - "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ - "A74206CEC169D74BF5A8C50D6F48EA08" - -#define PT_LEN 24 -#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ - "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" - -static int myrand( void *rng_state, unsigned char *output, size_t len ) -{ - size_t i; - - if( rng_state != NULL ) - rng_state = NULL; - - for( i = 0; i < len; ++i ) - output[i] = rand(); - - return( 0 ); -} - -/* - * Checkup routine - */ -int rsa_self_test( int verbose ) -{ - size_t len; - rsa_context rsa; - unsigned char rsa_plaintext[PT_LEN]; - unsigned char rsa_decrypted[PT_LEN]; - unsigned char rsa_ciphertext[KEY_LEN]; -#if defined(POLARSSL_SHA1_C) - unsigned char sha1sum[20]; -#endif - - rsa_init( &rsa, RSA_PKCS_V15, 0 ); - - rsa.len = KEY_LEN; - mpi_read_string( &rsa.N , 16, RSA_N ); - mpi_read_string( &rsa.E , 16, RSA_E ); - mpi_read_string( &rsa.D , 16, RSA_D ); - mpi_read_string( &rsa.P , 16, RSA_P ); - mpi_read_string( &rsa.Q , 16, RSA_Q ); - mpi_read_string( &rsa.DP, 16, RSA_DP ); - mpi_read_string( &rsa.DQ, 16, RSA_DQ ); - mpi_read_string( &rsa.QP, 16, RSA_QP ); - - if( verbose != 0 ) - printf( " RSA key validation: " ); - - if( rsa_check_pubkey( &rsa ) != 0 || - rsa_check_privkey( &rsa ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 encryption : " ); - - memcpy( rsa_plaintext, RSA_PT, PT_LEN ); - - if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN, - rsa_plaintext, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 decryption : " ); - - if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len, - rsa_ciphertext, rsa_decrypted, - sizeof(rsa_decrypted) ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - -#if defined(POLARSSL_SHA1_C) - if( verbose != 0 ) - printf( "passed\n PKCS#1 data sign : " ); - - sha1( rsa_plaintext, PT_LEN, sha1sum ); - - if( rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 sig. verify: " ); - - if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n\n" ); -#endif /* POLARSSL_SHA1_C */ - - rsa_free( &rsa ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/sha1.c b/polarssl/src/library/sha1.c deleted file mode 100644 index 72ca063..0000000 --- a/polarssl/src/library/sha1.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * FIPS-180-1 compliant SHA-1 implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The SHA-1 standard was published by NIST in 1993. - * - * http://www.itl.nist.gov/fipspubs/fip180-1.htm - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_SHA1_C) - -#include "polarssl/sha1.h" - -#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) -#include -#endif - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * SHA-1 context setup - */ -void sha1_starts( sha1_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) -{ - unsigned long temp, W[16], A, B, C, D, E; - - GET_ULONG_BE( W[ 0], data, 0 ); - GET_ULONG_BE( W[ 1], data, 4 ); - GET_ULONG_BE( W[ 2], data, 8 ); - GET_ULONG_BE( W[ 3], data, 12 ); - GET_ULONG_BE( W[ 4], data, 16 ); - GET_ULONG_BE( W[ 5], data, 20 ); - GET_ULONG_BE( W[ 6], data, 24 ); - GET_ULONG_BE( W[ 7], data, 28 ); - GET_ULONG_BE( W[ 8], data, 32 ); - GET_ULONG_BE( W[ 9], data, 36 ); - GET_ULONG_BE( W[10], data, 40 ); - GET_ULONG_BE( W[11], data, 44 ); - GET_ULONG_BE( W[12], data, 48 ); - GET_ULONG_BE( W[13], data, 52 ); - GET_ULONG_BE( W[14], data, 56 ); - GET_ULONG_BE( W[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define R(t) \ -( \ - temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ - W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ - ( W[t & 0x0F] = S(temp,1) ) \ -) - -#define P(a,b,c,d,e,x) \ -{ \ - e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define K 0x5A827999 - - P( A, B, C, D, E, W[0] ); - P( E, A, B, C, D, W[1] ); - P( D, E, A, B, C, W[2] ); - P( C, D, E, A, B, W[3] ); - P( B, C, D, E, A, W[4] ); - P( A, B, C, D, E, W[5] ); - P( E, A, B, C, D, W[6] ); - P( D, E, A, B, C, W[7] ); - P( C, D, E, A, B, W[8] ); - P( B, C, D, E, A, W[9] ); - P( A, B, C, D, E, W[10] ); - P( E, A, B, C, D, W[11] ); - P( D, E, A, B, C, W[12] ); - P( C, D, E, A, B, W[13] ); - P( B, C, D, E, A, W[14] ); - P( A, B, C, D, E, W[15] ); - P( E, A, B, C, D, R(16) ); - P( D, E, A, B, C, R(17) ); - P( C, D, E, A, B, R(18) ); - P( B, C, D, E, A, R(19) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0x6ED9EBA1 - - P( A, B, C, D, E, R(20) ); - P( E, A, B, C, D, R(21) ); - P( D, E, A, B, C, R(22) ); - P( C, D, E, A, B, R(23) ); - P( B, C, D, E, A, R(24) ); - P( A, B, C, D, E, R(25) ); - P( E, A, B, C, D, R(26) ); - P( D, E, A, B, C, R(27) ); - P( C, D, E, A, B, R(28) ); - P( B, C, D, E, A, R(29) ); - P( A, B, C, D, E, R(30) ); - P( E, A, B, C, D, R(31) ); - P( D, E, A, B, C, R(32) ); - P( C, D, E, A, B, R(33) ); - P( B, C, D, E, A, R(34) ); - P( A, B, C, D, E, R(35) ); - P( E, A, B, C, D, R(36) ); - P( D, E, A, B, C, R(37) ); - P( C, D, E, A, B, R(38) ); - P( B, C, D, E, A, R(39) ); - -#undef K -#undef F - -#define F(x,y,z) ((x & y) | (z & (x | y))) -#define K 0x8F1BBCDC - - P( A, B, C, D, E, R(40) ); - P( E, A, B, C, D, R(41) ); - P( D, E, A, B, C, R(42) ); - P( C, D, E, A, B, R(43) ); - P( B, C, D, E, A, R(44) ); - P( A, B, C, D, E, R(45) ); - P( E, A, B, C, D, R(46) ); - P( D, E, A, B, C, R(47) ); - P( C, D, E, A, B, R(48) ); - P( B, C, D, E, A, R(49) ); - P( A, B, C, D, E, R(50) ); - P( E, A, B, C, D, R(51) ); - P( D, E, A, B, C, R(52) ); - P( C, D, E, A, B, R(53) ); - P( B, C, D, E, A, R(54) ); - P( A, B, C, D, E, R(55) ); - P( E, A, B, C, D, R(56) ); - P( D, E, A, B, C, R(57) ); - P( C, D, E, A, B, R(58) ); - P( B, C, D, E, A, R(59) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0xCA62C1D6 - - P( A, B, C, D, E, R(60) ); - P( E, A, B, C, D, R(61) ); - P( D, E, A, B, C, R(62) ); - P( C, D, E, A, B, R(63) ); - P( B, C, D, E, A, R(64) ); - P( A, B, C, D, E, R(65) ); - P( E, A, B, C, D, R(66) ); - P( D, E, A, B, C, R(67) ); - P( C, D, E, A, B, R(68) ); - P( B, C, D, E, A, R(69) ); - P( A, B, C, D, E, R(70) ); - P( E, A, B, C, D, R(71) ); - P( D, E, A, B, C, R(72) ); - P( C, D, E, A, B, R(73) ); - P( B, C, D, E, A, R(74) ); - P( A, B, C, D, E, R(75) ); - P( E, A, B, C, D, R(76) ); - P( D, E, A, B, C, R(77) ); - P( C, D, E, A, B, R(78) ); - P( B, C, D, E, A, R(79) ); - -#undef K -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; -} - -/* - * SHA-1 process buffer - */ -void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (unsigned long) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, fill ); - sha1_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - sha1_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, ilen ); - } -} - -static const unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-1 final digest - */ -void sha1_finish( sha1_context *ctx, unsigned char output[20] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_BE( high, msglen, 0 ); - PUT_ULONG_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - sha1_update( ctx, (unsigned char *) sha1_padding, padn ); - sha1_update( ctx, msglen, 8 ); - - PUT_ULONG_BE( ctx->state[0], output, 0 ); - PUT_ULONG_BE( ctx->state[1], output, 4 ); - PUT_ULONG_BE( ctx->state[2], output, 8 ); - PUT_ULONG_BE( ctx->state[3], output, 12 ); - PUT_ULONG_BE( ctx->state[4], output, 16 ); -} - -/* - * output = SHA-1( input buffer ) - */ -void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) -{ - sha1_context ctx; - - sha1_starts( &ctx ); - sha1_update( &ctx, input, ilen ); - sha1_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha1_context ) ); -} - -#if defined(POLARSSL_FS_IO) -/* - * output = SHA-1( file contents ) - */ -int sha1_file( const char *path, unsigned char output[20] ) -{ - FILE *f; - size_t n; - sha1_context ctx; - unsigned char buf[1024]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); - - sha1_starts( &ctx ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - sha1_update( &ctx, buf, n ); - - sha1_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha1_context ) ); - - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); - } - - fclose( f ); - return( 0 ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * SHA-1 HMAC context setup - */ -void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ) -{ - size_t i; - unsigned char sum[20]; - - if( keylen > 64 ) - { - sha1( key, keylen, sum ); - keylen = 20; - key = sum; - } - - memset( ctx->ipad, 0x36, 64 ); - memset( ctx->opad, 0x5C, 64 ); - - for( i = 0; i < keylen; i++ ) - { - ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); - ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); - } - - sha1_starts( ctx ); - sha1_update( ctx, ctx->ipad, 64 ); - - memset( sum, 0, sizeof( sum ) ); -} - -/* - * SHA-1 HMAC process buffer - */ -void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) -{ - sha1_update( ctx, input, ilen ); -} - -/* - * SHA-1 HMAC final digest - */ -void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) -{ - unsigned char tmpbuf[20]; - - sha1_finish( ctx, tmpbuf ); - sha1_starts( ctx ); - sha1_update( ctx, ctx->opad, 64 ); - sha1_update( ctx, tmpbuf, 20 ); - sha1_finish( ctx, output ); - - memset( tmpbuf, 0, sizeof( tmpbuf ) ); -} - -/* - * SHA1 HMAC context reset - */ -void sha1_hmac_reset( sha1_context *ctx ) -{ - sha1_starts( ctx ); - sha1_update( ctx, ctx->ipad, 64 ); -} - -/* - * output = HMAC-SHA-1( hmac key, input buffer ) - */ -void sha1_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[20] ) -{ - sha1_context ctx; - - sha1_hmac_starts( &ctx, key, keylen ); - sha1_hmac_update( &ctx, input, ilen ); - sha1_hmac_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha1_context ) ); -} - -#if defined(POLARSSL_SELF_TEST) -/* - * FIPS-180-1 test vectors - */ -static unsigned char sha1_test_buf[3][57] = -{ - { "abc" }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, - { "" } -}; - -static const int sha1_test_buflen[3] = -{ - 3, 56, 1000 -}; - -static const unsigned char sha1_test_sum[3][20] = -{ - { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, - 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, - { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, - 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, - { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, - 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } -}; - -/* - * RFC 2202 test vectors - */ -static unsigned char sha1_hmac_test_key[7][26] = -{ - { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" - "\x0B\x0B\x0B\x0B" }, - { "Jefe" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA" }, - { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, - { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" - "\x0C\x0C\x0C\x0C" }, - { "" }, /* 0xAA 80 times */ - { "" } -}; - -static const int sha1_hmac_test_keylen[7] = -{ - 20, 4, 20, 25, 20, 80, 80 -}; - -static unsigned char sha1_hmac_test_buf[7][74] = -{ - { "Hi There" }, - { "what do ya want for nothing?" }, - { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, - { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, - { "Test With Truncation" }, - { "Test Using Larger Than Block-Size Key - Hash Key First" }, - { "Test Using Larger Than Block-Size Key and Larger" - " Than One Block-Size Data" } -}; - -static const int sha1_hmac_test_buflen[7] = -{ - 8, 28, 50, 50, 20, 54, 73 -}; - -static const unsigned char sha1_hmac_test_sum[7][20] = -{ - { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B, - 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 }, - { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74, - 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 }, - { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3, - 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 }, - { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84, - 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA }, - { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2, - 0x7B, 0xE1 }, - { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70, - 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 }, - { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B, - 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 } -}; - -/* - * Checkup routine - */ -int sha1_self_test( int verbose ) -{ - int i, j, buflen; - unsigned char buf[1024]; - unsigned char sha1sum[20]; - sha1_context ctx; - - /* - * SHA-1 - */ - for( i = 0; i < 3; i++ ) - { - if( verbose != 0 ) - printf( " SHA-1 test #%d: ", i + 1 ); - - sha1_starts( &ctx ); - - if( i == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - sha1_update( &ctx, buf, buflen ); - } - else - sha1_update( &ctx, sha1_test_buf[i], - sha1_test_buflen[i] ); - - sha1_finish( &ctx, sha1sum ); - - if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - printf( " HMAC-SHA-1 test #%d: ", i + 1 ); - - if( i == 5 || i == 6 ) - { - memset( buf, '\xAA', buflen = 80 ); - sha1_hmac_starts( &ctx, buf, buflen ); - } - else - sha1_hmac_starts( &ctx, sha1_hmac_test_key[i], - sha1_hmac_test_keylen[i] ); - - sha1_hmac_update( &ctx, sha1_hmac_test_buf[i], - sha1_hmac_test_buflen[i] ); - - sha1_hmac_finish( &ctx, sha1sum ); - - buflen = ( i == 4 ) ? 12 : 20; - - if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/sha2.c b/polarssl/src/library/sha2.c deleted file mode 100644 index 4b5e696..0000000 --- a/polarssl/src/library/sha2.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * FIPS-180-2 compliant SHA-256 implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The SHA-256 Secure Hash Standard was published by NIST in 2002. - * - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_SHA2_C) - -#include "polarssl/sha2.h" - -#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) -#include -#endif - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * SHA-256 context setup - */ -void sha2_starts( sha2_context *ctx, int is224 ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - if( is224 == 0 ) - { - /* SHA-256 */ - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; - } - else - { - /* SHA-224 */ - ctx->state[0] = 0xC1059ED8; - ctx->state[1] = 0x367CD507; - ctx->state[2] = 0x3070DD17; - ctx->state[3] = 0xF70E5939; - ctx->state[4] = 0xFFC00B31; - ctx->state[5] = 0x68581511; - ctx->state[6] = 0x64F98FA7; - ctx->state[7] = 0xBEFA4FA4; - } - - ctx->is224 = is224; -} - -static void sha2_process( sha2_context *ctx, const unsigned char data[64] ) -{ - unsigned long temp1, temp2, W[64]; - unsigned long A, B, C, D, E, F, G, H; - - GET_ULONG_BE( W[ 0], data, 0 ); - GET_ULONG_BE( W[ 1], data, 4 ); - GET_ULONG_BE( W[ 2], data, 8 ); - GET_ULONG_BE( W[ 3], data, 12 ); - GET_ULONG_BE( W[ 4], data, 16 ); - GET_ULONG_BE( W[ 5], data, 20 ); - GET_ULONG_BE( W[ 6], data, 24 ); - GET_ULONG_BE( W[ 7], data, 28 ); - GET_ULONG_BE( W[ 8], data, 32 ); - GET_ULONG_BE( W[ 9], data, 36 ); - GET_ULONG_BE( W[10], data, 40 ); - GET_ULONG_BE( W[11], data, 44 ); - GET_ULONG_BE( W[12], data, 48 ); - GET_ULONG_BE( W[13], data, 52 ); - GET_ULONG_BE( W[14], data, 56 ); - GET_ULONG_BE( W[15], data, 60 ); - -#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) - -#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) - -#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define R(t) \ -( \ - W[t] = S1(W[t - 2]) + W[t - 7] + \ - S0(W[t - 15]) + W[t - 16] \ -) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - F = ctx->state[5]; - G = ctx->state[6]; - H = ctx->state[7]; - - P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 ); - P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 ); - P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF ); - P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 ); - P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B ); - P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 ); - P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 ); - P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 ); - P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 ); - P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 ); - P( G, H, A, B, C, D, E, F, W[10], 0x243185BE ); - P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 ); - P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 ); - P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE ); - P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 ); - P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 ); - P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 ); - P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 ); - P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 ); - P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC ); - P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F ); - P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA ); - P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC ); - P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA ); - P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 ); - P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D ); - P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 ); - P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 ); - P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 ); - P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 ); - P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 ); - P( B, C, D, E, F, G, H, A, R(31), 0x14292967 ); - P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 ); - P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 ); - P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC ); - P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 ); - P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 ); - P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB ); - P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E ); - P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 ); - P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 ); - P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B ); - P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 ); - P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 ); - P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 ); - P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 ); - P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 ); - P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 ); - P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 ); - P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 ); - P( G, H, A, B, C, D, E, F, R(50), 0x2748774C ); - P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 ); - P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 ); - P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A ); - P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F ); - P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 ); - P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE ); - P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F ); - P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 ); - P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 ); - P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA ); - P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB ); - P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 ); - P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 ); - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; - ctx->state[5] += F; - ctx->state[6] += G; - ctx->state[7] += H; -} - -/* - * SHA-256 process buffer - */ -void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (unsigned long) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, fill ); - sha2_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - sha2_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, ilen ); - } -} - -static const unsigned char sha2_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-256 final digest - */ -void sha2_finish( sha2_context *ctx, unsigned char output[32] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_BE( high, msglen, 0 ); - PUT_ULONG_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - sha2_update( ctx, (unsigned char *) sha2_padding, padn ); - sha2_update( ctx, msglen, 8 ); - - PUT_ULONG_BE( ctx->state[0], output, 0 ); - PUT_ULONG_BE( ctx->state[1], output, 4 ); - PUT_ULONG_BE( ctx->state[2], output, 8 ); - PUT_ULONG_BE( ctx->state[3], output, 12 ); - PUT_ULONG_BE( ctx->state[4], output, 16 ); - PUT_ULONG_BE( ctx->state[5], output, 20 ); - PUT_ULONG_BE( ctx->state[6], output, 24 ); - - if( ctx->is224 == 0 ) - PUT_ULONG_BE( ctx->state[7], output, 28 ); -} - -/* - * output = SHA-256( input buffer ) - */ -void sha2( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ) -{ - sha2_context ctx; - - sha2_starts( &ctx, is224 ); - sha2_update( &ctx, input, ilen ); - sha2_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha2_context ) ); -} - -#if defined(POLARSSL_FS_IO) -/* - * output = SHA-256( file contents ) - */ -int sha2_file( const char *path, unsigned char output[32], int is224 ) -{ - FILE *f; - size_t n; - sha2_context ctx; - unsigned char buf[1024]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_SHA2_FILE_IO_ERROR ); - - sha2_starts( &ctx, is224 ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - sha2_update( &ctx, buf, n ); - - sha2_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha2_context ) ); - - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_SHA2_FILE_IO_ERROR ); - } - - fclose( f ); - return( 0 ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * SHA-256 HMAC context setup - */ -void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen, - int is224 ) -{ - size_t i; - unsigned char sum[32]; - - if( keylen > 64 ) - { - sha2( key, keylen, sum, is224 ); - keylen = ( is224 ) ? 28 : 32; - key = sum; - } - - memset( ctx->ipad, 0x36, 64 ); - memset( ctx->opad, 0x5C, 64 ); - - for( i = 0; i < keylen; i++ ) - { - ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); - ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); - } - - sha2_starts( ctx, is224 ); - sha2_update( ctx, ctx->ipad, 64 ); - - memset( sum, 0, sizeof( sum ) ); -} - -/* - * SHA-256 HMAC process buffer - */ -void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) -{ - sha2_update( ctx, input, ilen ); -} - -/* - * SHA-256 HMAC final digest - */ -void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] ) -{ - int is224, hlen; - unsigned char tmpbuf[32]; - - is224 = ctx->is224; - hlen = ( is224 == 0 ) ? 32 : 28; - - sha2_finish( ctx, tmpbuf ); - sha2_starts( ctx, is224 ); - sha2_update( ctx, ctx->opad, 64 ); - sha2_update( ctx, tmpbuf, hlen ); - sha2_finish( ctx, output ); - - memset( tmpbuf, 0, sizeof( tmpbuf ) ); -} - -/* - * SHA-256 HMAC context reset - */ -void sha2_hmac_reset( sha2_context *ctx ) -{ - sha2_starts( ctx, ctx->is224 ); - sha2_update( ctx, ctx->ipad, 64 ); -} - -/* - * output = HMAC-SHA-256( hmac key, input buffer ) - */ -void sha2_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ) -{ - sha2_context ctx; - - sha2_hmac_starts( &ctx, key, keylen, is224 ); - sha2_hmac_update( &ctx, input, ilen ); - sha2_hmac_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha2_context ) ); -} - -#if defined(POLARSSL_SELF_TEST) -/* - * FIPS-180-2 test vectors - */ -static unsigned char sha2_test_buf[3][57] = -{ - { "abc" }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, - { "" } -}; - -static const int sha2_test_buflen[3] = -{ - 3, 56, 1000 -}; - -static const unsigned char sha2_test_sum[6][32] = -{ - /* - * SHA-224 test vectors - */ - { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, - 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, - 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, - 0xE3, 0x6C, 0x9D, 0xA7 }, - { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, - 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, - 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, - 0x52, 0x52, 0x25, 0x25 }, - { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, - 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, - 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, - 0x4E, 0xE7, 0xAD, 0x67 }, - - /* - * SHA-256 test vectors - */ - { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, - 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, - 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, - 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, - { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, - 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, - 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, - 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, - { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, - 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, - 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, - 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } -}; - -/* - * RFC 4231 test vectors - */ -static unsigned char sha2_hmac_test_key[7][26] = -{ - { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" - "\x0B\x0B\x0B\x0B" }, - { "Jefe" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA" }, - { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, - { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" - "\x0C\x0C\x0C\x0C" }, - { "" }, /* 0xAA 131 times */ - { "" } -}; - -static const int sha2_hmac_test_keylen[7] = -{ - 20, 4, 20, 25, 20, 131, 131 -}; - -static unsigned char sha2_hmac_test_buf[7][153] = -{ - { "Hi There" }, - { "what do ya want for nothing?" }, - { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, - { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, - { "Test With Truncation" }, - { "Test Using Larger Than Block-Size Key - Hash Key First" }, - { "This is a test using a larger than block-size key " - "and a larger than block-size data. The key needs to " - "be hashed before being used by the HMAC algorithm." } -}; - -static const int sha2_hmac_test_buflen[7] = -{ - 8, 28, 50, 50, 20, 54, 152 -}; - -static const unsigned char sha2_hmac_test_sum[14][32] = -{ - /* - * HMAC-SHA-224 test vectors - */ - { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19, - 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F, - 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F, - 0x53, 0x68, 0x4B, 0x22 }, - { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF, - 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F, - 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00, - 0x8F, 0xD0, 0x5E, 0x44 }, - { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6, - 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64, - 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1, - 0xEC, 0x83, 0x33, 0xEA }, - { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC, - 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C, - 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D, - 0xE7, 0xAF, 0xEC, 0x5A }, - { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37, - 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 }, - { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD, - 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2, - 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27, - 0x3F, 0xA6, 0x87, 0x0E }, - { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02, - 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD, - 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9, - 0xF6, 0xF5, 0x65, 0xD1 }, - - /* - * HMAC-SHA-256 test vectors - */ - { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53, - 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B, - 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7, - 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 }, - { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E, - 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7, - 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83, - 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 }, - { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46, - 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7, - 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22, - 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE }, - { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E, - 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A, - 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07, - 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B }, - { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0, - 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B }, - { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F, - 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F, - 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14, - 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 }, - { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB, - 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44, - 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93, - 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 } -}; - -/* - * Checkup routine - */ -int sha2_self_test( int verbose ) -{ - int i, j, k, buflen; - unsigned char buf[1024]; - unsigned char sha2sum[32]; - sha2_context ctx; - - for( i = 0; i < 6; i++ ) - { - j = i % 3; - k = i < 3; - - if( verbose != 0 ) - printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); - - sha2_starts( &ctx, k ); - - if( j == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - sha2_update( &ctx, buf, buflen ); - } - else - sha2_update( &ctx, sha2_test_buf[j], - sha2_test_buflen[j] ); - - sha2_finish( &ctx, sha2sum ); - - if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - for( i = 0; i < 14; i++ ) - { - j = i % 7; - k = i < 7; - - if( verbose != 0 ) - printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 ); - - if( j == 5 || j == 6 ) - { - memset( buf, '\xAA', buflen = 131 ); - sha2_hmac_starts( &ctx, buf, buflen, k ); - } - else - sha2_hmac_starts( &ctx, sha2_hmac_test_key[j], - sha2_hmac_test_keylen[j], k ); - - sha2_hmac_update( &ctx, sha2_hmac_test_buf[j], - sha2_hmac_test_buflen[j] ); - - sha2_hmac_finish( &ctx, sha2sum ); - - buflen = ( j == 4 ) ? 16 : 32 - k * 4; - - if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/sha4.c b/polarssl/src/library/sha4.c deleted file mode 100644 index cf54d11..0000000 --- a/polarssl/src/library/sha4.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - * FIPS-180-2 compliant SHA-384/512 implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The SHA-512 Secure Hash Standard was published by NIST in 2002. - * - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_SHA4_C) - -#include "polarssl/sha4.h" - -#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) -#include -#endif - -/* - * 64-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT64_BE -#define GET_UINT64_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long64) (b)[(i) ] << 56 ) \ - | ( (unsigned long64) (b)[(i) + 1] << 48 ) \ - | ( (unsigned long64) (b)[(i) + 2] << 40 ) \ - | ( (unsigned long64) (b)[(i) + 3] << 32 ) \ - | ( (unsigned long64) (b)[(i) + 4] << 24 ) \ - | ( (unsigned long64) (b)[(i) + 5] << 16 ) \ - | ( (unsigned long64) (b)[(i) + 6] << 8 ) \ - | ( (unsigned long64) (b)[(i) + 7] ); \ -} -#endif - -#ifndef PUT_UINT64_BE -#define PUT_UINT64_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ - (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 7] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * Round constants - */ -static const unsigned long64 K[80] = -{ - UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), - UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), - UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), - UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), - UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), - UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), - UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), - UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), - UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), - UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), - UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), - UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), - UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), - UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), - UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), - UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), - UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), - UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), - UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), - UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), - UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), - UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), - UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), - UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), - UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), - UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), - UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), - UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), - UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), - UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), - UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), - UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), - UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), - UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), - UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), - UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), - UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), - UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), - UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), - UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) -}; - -/* - * SHA-512 context setup - */ -void sha4_starts( sha4_context *ctx, int is384 ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - if( is384 == 0 ) - { - /* SHA-512 */ - ctx->state[0] = UL64(0x6A09E667F3BCC908); - ctx->state[1] = UL64(0xBB67AE8584CAA73B); - ctx->state[2] = UL64(0x3C6EF372FE94F82B); - ctx->state[3] = UL64(0xA54FF53A5F1D36F1); - ctx->state[4] = UL64(0x510E527FADE682D1); - ctx->state[5] = UL64(0x9B05688C2B3E6C1F); - ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); - ctx->state[7] = UL64(0x5BE0CD19137E2179); - } - else - { - /* SHA-384 */ - ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); - ctx->state[1] = UL64(0x629A292A367CD507); - ctx->state[2] = UL64(0x9159015A3070DD17); - ctx->state[3] = UL64(0x152FECD8F70E5939); - ctx->state[4] = UL64(0x67332667FFC00B31); - ctx->state[5] = UL64(0x8EB44A8768581511); - ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); - ctx->state[7] = UL64(0x47B5481DBEFA4FA4); - } - - ctx->is384 = is384; -} - -static void sha4_process( sha4_context *ctx, const unsigned char data[128] ) -{ - int i; - unsigned long64 temp1, temp2, W[80]; - unsigned long64 A, B, C, D, E, F, G, H; - -#define SHR(x,n) (x >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) - -#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) -#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) - -#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) -#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - - for( i = 0; i < 16; i++ ) - { - GET_UINT64_BE( W[i], data, i << 3 ); - } - - for( ; i < 80; i++ ) - { - W[i] = S1(W[i - 2]) + W[i - 7] + - S0(W[i - 15]) + W[i - 16]; - } - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - F = ctx->state[5]; - G = ctx->state[6]; - H = ctx->state[7]; - i = 0; - - do - { - P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; - P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; - P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; - P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; - P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; - P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; - P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; - P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; - } - while( i < 80 ); - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; - ctx->state[5] += F; - ctx->state[6] += G; - ctx->state[7] += H; -} - -/* - * SHA-512 process buffer - */ -void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - unsigned int left; - - if( ilen <= 0 ) - return; - - left = (unsigned int) (ctx->total[0] & 0x7F); - fill = 128 - left; - - ctx->total[0] += (unsigned long64) ilen; - - if( ctx->total[0] < (unsigned long64) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, fill ); - sha4_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 128 ) - { - sha4_process( ctx, input ); - input += 128; - ilen -= 128; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, ilen ); - } -} - -static const unsigned char sha4_padding[128] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-512 final digest - */ -void sha4_finish( sha4_context *ctx, unsigned char output[64] ) -{ - size_t last, padn; - unsigned long64 high, low; - unsigned char msglen[16]; - - high = ( ctx->total[0] >> 61 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT64_BE( high, msglen, 0 ); - PUT_UINT64_BE( low, msglen, 8 ); - - last = (size_t)( ctx->total[0] & 0x7F ); - padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); - - sha4_update( ctx, (unsigned char *) sha4_padding, padn ); - sha4_update( ctx, msglen, 16 ); - - PUT_UINT64_BE( ctx->state[0], output, 0 ); - PUT_UINT64_BE( ctx->state[1], output, 8 ); - PUT_UINT64_BE( ctx->state[2], output, 16 ); - PUT_UINT64_BE( ctx->state[3], output, 24 ); - PUT_UINT64_BE( ctx->state[4], output, 32 ); - PUT_UINT64_BE( ctx->state[5], output, 40 ); - - if( ctx->is384 == 0 ) - { - PUT_UINT64_BE( ctx->state[6], output, 48 ); - PUT_UINT64_BE( ctx->state[7], output, 56 ); - } -} - -/* - * output = SHA-512( input buffer ) - */ -void sha4( const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ) -{ - sha4_context ctx; - - sha4_starts( &ctx, is384 ); - sha4_update( &ctx, input, ilen ); - sha4_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha4_context ) ); -} - -#if defined(POLARSSL_FS_IO) -/* - * output = SHA-512( file contents ) - */ -int sha4_file( const char *path, unsigned char output[64], int is384 ) -{ - FILE *f; - size_t n; - sha4_context ctx; - unsigned char buf[1024]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_SHA4_FILE_IO_ERROR ); - - sha4_starts( &ctx, is384 ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - sha4_update( &ctx, buf, n ); - - sha4_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha4_context ) ); - - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_SHA4_FILE_IO_ERROR ); - } - - fclose( f ); - return( 0 ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * SHA-512 HMAC context setup - */ -void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen, - int is384 ) -{ - size_t i; - unsigned char sum[64]; - - if( keylen > 128 ) - { - sha4( key, keylen, sum, is384 ); - keylen = ( is384 ) ? 48 : 64; - key = sum; - } - - memset( ctx->ipad, 0x36, 128 ); - memset( ctx->opad, 0x5C, 128 ); - - for( i = 0; i < keylen; i++ ) - { - ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); - ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); - } - - sha4_starts( ctx, is384 ); - sha4_update( ctx, ctx->ipad, 128 ); - - memset( sum, 0, sizeof( sum ) ); -} - -/* - * SHA-512 HMAC process buffer - */ -void sha4_hmac_update( sha4_context *ctx, - const unsigned char *input, size_t ilen ) -{ - sha4_update( ctx, input, ilen ); -} - -/* - * SHA-512 HMAC final digest - */ -void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] ) -{ - int is384, hlen; - unsigned char tmpbuf[64]; - - is384 = ctx->is384; - hlen = ( is384 == 0 ) ? 64 : 48; - - sha4_finish( ctx, tmpbuf ); - sha4_starts( ctx, is384 ); - sha4_update( ctx, ctx->opad, 128 ); - sha4_update( ctx, tmpbuf, hlen ); - sha4_finish( ctx, output ); - - memset( tmpbuf, 0, sizeof( tmpbuf ) ); -} - -/* - * SHA-512 HMAC context reset - */ -void sha4_hmac_reset( sha4_context *ctx ) -{ - sha4_starts( ctx, ctx->is384 ); - sha4_update( ctx, ctx->ipad, 128 ); -} - -/* - * output = HMAC-SHA-512( hmac key, input buffer ) - */ -void sha4_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ) -{ - sha4_context ctx; - - sha4_hmac_starts( &ctx, key, keylen, is384 ); - sha4_hmac_update( &ctx, input, ilen ); - sha4_hmac_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha4_context ) ); -} - -#if defined(POLARSSL_SELF_TEST) - -/* - * FIPS-180-2 test vectors - */ -static unsigned char sha4_test_buf[3][113] = -{ - { "abc" }, - { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, - { "" } -}; - -static const int sha4_test_buflen[3] = -{ - 3, 112, 1000 -}; - -static const unsigned char sha4_test_sum[6][64] = -{ - /* - * SHA-384 test vectors - */ - { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, - 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, - 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, - 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, - 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, - 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, - { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, - 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, - 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, - 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, - 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, - 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, - { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, - 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, - 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, - 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, - 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, - 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, - - /* - * SHA-512 test vectors - */ - { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, - 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, - 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, - 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, - 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, - 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, - 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, - 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, - { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, - 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, - 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, - 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, - 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, - 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, - 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, - 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, - { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, - 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, - 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, - 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, - 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, - 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, - 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, - 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } -}; - -/* - * RFC 4231 test vectors - */ -static unsigned char sha4_hmac_test_key[7][26] = -{ - { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" - "\x0B\x0B\x0B\x0B" }, - { "Jefe" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA" }, - { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, - { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" - "\x0C\x0C\x0C\x0C" }, - { "" }, /* 0xAA 131 times */ - { "" } -}; - -static const int sha4_hmac_test_keylen[7] = -{ - 20, 4, 20, 25, 20, 131, 131 -}; - -static unsigned char sha4_hmac_test_buf[7][153] = -{ - { "Hi There" }, - { "what do ya want for nothing?" }, - { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, - { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, - { "Test With Truncation" }, - { "Test Using Larger Than Block-Size Key - Hash Key First" }, - { "This is a test using a larger than block-size key " - "and a larger than block-size data. The key needs to " - "be hashed before being used by the HMAC algorithm." } -}; - -static const int sha4_hmac_test_buflen[7] = -{ - 8, 28, 50, 50, 20, 54, 152 -}; - -static const unsigned char sha4_hmac_test_sum[14][64] = -{ - /* - * HMAC-SHA-384 test vectors - */ - { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62, - 0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F, - 0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6, - 0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C, - 0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F, - 0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 }, - { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31, - 0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B, - 0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47, - 0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E, - 0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7, - 0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 }, - { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A, - 0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F, - 0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB, - 0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B, - 0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9, - 0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 }, - { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85, - 0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7, - 0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C, - 0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E, - 0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79, - 0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB }, - { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23, - 0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 }, - { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90, - 0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4, - 0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F, - 0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6, - 0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82, - 0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 }, - { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D, - 0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C, - 0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A, - 0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5, - 0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D, - 0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E }, - - /* - * HMAC-SHA-512 test vectors - */ - { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D, - 0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0, - 0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78, - 0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE, - 0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02, - 0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4, - 0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70, - 0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 }, - { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2, - 0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3, - 0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6, - 0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54, - 0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A, - 0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD, - 0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B, - 0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 }, - { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84, - 0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9, - 0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36, - 0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39, - 0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8, - 0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07, - 0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26, - 0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB }, - { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69, - 0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7, - 0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D, - 0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB, - 0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4, - 0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63, - 0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D, - 0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD }, - { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53, - 0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 }, - { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB, - 0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4, - 0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1, - 0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52, - 0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98, - 0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52, - 0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC, - 0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 }, - { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA, - 0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD, - 0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86, - 0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44, - 0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1, - 0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15, - 0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60, - 0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 } -}; - -/* - * Checkup routine - */ -int sha4_self_test( int verbose ) -{ - int i, j, k, buflen; - unsigned char buf[1024]; - unsigned char sha4sum[64]; - sha4_context ctx; - - for( i = 0; i < 6; i++ ) - { - j = i % 3; - k = i < 3; - - if( verbose != 0 ) - printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); - - sha4_starts( &ctx, k ); - - if( j == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - sha4_update( &ctx, buf, buflen ); - } - else - sha4_update( &ctx, sha4_test_buf[j], - sha4_test_buflen[j] ); - - sha4_finish( &ctx, sha4sum ); - - if( memcmp( sha4sum, sha4_test_sum[i], 64 - k * 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - for( i = 0; i < 14; i++ ) - { - j = i % 7; - k = i < 7; - - if( verbose != 0 ) - printf( " HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 ); - - if( j == 5 || j == 6 ) - { - memset( buf, '\xAA', buflen = 131 ); - sha4_hmac_starts( &ctx, buf, buflen, k ); - } - else - sha4_hmac_starts( &ctx, sha4_hmac_test_key[j], - sha4_hmac_test_keylen[j], k ); - - sha4_hmac_update( &ctx, sha4_hmac_test_buf[j], - sha4_hmac_test_buflen[j] ); - - sha4_hmac_finish( &ctx, sha4sum ); - - buflen = ( j == 4 ) ? 16 : 64 - k * 16; - - if( memcmp( sha4sum, sha4_hmac_test_sum[i], buflen ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/polarssl/src/library/ssl_cli.c b/polarssl/src/library/ssl_cli.c deleted file mode 100644 index 99120d5..0000000 --- a/polarssl/src/library/ssl_cli.c +++ /dev/null @@ -1,1130 +0,0 @@ -/* - * SSLv3/TLSv1 client-side functions - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_SSL_CLI_C) - -#include "polarssl/debug.h" -#include "polarssl/ssl.h" - -#if defined(POLARSSL_PKCS11_C) -#include "polarssl/pkcs11.h" -#endif /* defined(POLARSSL_PKCS11_C) */ - -#include -#include -#include - -#if defined(POLARSSL_SHA4_C) -#include "polarssl/sha4.h" -#endif - -static int ssl_write_client_hello( ssl_context *ssl ) -{ - int ret; - size_t i, n, ext_len = 0; - unsigned char *buf; - unsigned char *p; - time_t t; - unsigned char sig_alg_list[20]; - size_t sig_alg_len = 0; - - SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); - - ssl->major_ver = SSL_MAJOR_VERSION_3; - ssl->minor_ver = SSL_MINOR_VERSION_0; - - if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 ) - { - ssl->max_major_ver = SSL_MAJOR_VERSION_3; - ssl->max_minor_ver = SSL_MINOR_VERSION_3; - } - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 highest version supported - * 6 . 9 current UNIX time - * 10 . 37 random bytes - */ - buf = ssl->out_msg; - p = buf + 4; - - *p++ = (unsigned char) ssl->max_major_ver; - *p++ = (unsigned char) ssl->max_minor_ver; - - SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", - buf[4], buf[5] ) ); - - t = time( NULL ); - *p++ = (unsigned char)( t >> 24 ); - *p++ = (unsigned char)( t >> 16 ); - *p++ = (unsigned char)( t >> 8 ); - *p++ = (unsigned char)( t ); - - SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); - - if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 ) - return( ret ); - - p += 28; - - memcpy( ssl->randbytes, buf + 6, 32 ); - - SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 ); - - /* - * 38 . 38 session id length - * 39 . 39+n session id - * 40+n . 41+n ciphersuitelist length - * 42+n . .. ciphersuitelist - * .. . .. compression methods length - * .. . .. compression methods - * .. . .. extensions length - * .. . .. extensions - */ - n = ssl->session->length; - - if( n < 16 || n > 32 || ssl->resume == 0 || - ( ssl->timeout != 0 && t - ssl->session->start > ssl->timeout ) ) - n = 0; - - *p++ = (unsigned char) n; - - for( i = 0; i < n; i++ ) - *p++ = ssl->session->id[i]; - - SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); - SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); - - for( n = 0; ssl->ciphersuites[n] != 0; n++ ); - *p++ = (unsigned char)( n >> 7 ); - *p++ = (unsigned char)( n << 1 ); - - SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); - - for( i = 0; i < n; i++ ) - { - SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d", - ssl->ciphersuites[i] ) ); - - *p++ = (unsigned char)( ssl->ciphersuites[i] >> 8 ); - *p++ = (unsigned char)( ssl->ciphersuites[i] ); - } - - SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); - SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", 0 ) ); - - *p++ = 1; - *p++ = SSL_COMPRESS_NULL; - - if ( ssl->hostname != NULL ) - { - SSL_DEBUG_MSG( 3, ( "client hello, prepping for server name extension: %s", - ssl->hostname ) ); - - ext_len += ssl->hostname_len + 9; - } - - /* - * Prepare signature_algorithms extension (TLS 1.2) - */ - if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 ) - { -#if defined(POLARSSL_SHA4_C) - sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512; - sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; - sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384; - sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; -#endif -#if defined(POLARSSL_SHA2_C) - sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256; - sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; - sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224; - sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; -#endif -#if defined(POLARSSL_SHA1_C) - sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1; - sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; -#endif -#if defined(POLARSSL_MD5_C) - sig_alg_list[sig_alg_len++] = SSL_HASH_MD5; - sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; -#endif - ext_len = 6 + sig_alg_len; - } - - SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", - ext_len ) ); - - *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ext_len ) & 0xFF ); - - if ( ssl->hostname != NULL ) - { - /* - * struct { - * NameType name_type; - * select (name_type) { - * case host_name: HostName; - * } name; - * } ServerName; - * - * enum { - * host_name(0), (255) - * } NameType; - * - * opaque HostName<1..2^16-1>; - * - * struct { - * ServerName server_name_list<1..2^16-1> - * } ServerNameList; - */ - SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", - ssl->hostname ) ); - - *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME ) & 0xFF ); - - *p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( (ssl->hostname_len + 5) ) & 0xFF ); - - *p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( (ssl->hostname_len + 3) ) & 0xFF ); - - *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); - *p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ssl->hostname_len ) & 0xFF ); - - memcpy( p, ssl->hostname, ssl->hostname_len ); - - p += ssl->hostname_len; - } - - if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 ) - { - /* - * enum { - * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), - * sha512(6), (255) - * } HashAlgorithm; - * - * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } - * SignatureAlgorithm; - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - * - * SignatureAndHashAlgorithm - * supported_signature_algorithms<2..2^16-2>; - */ - SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); - - *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG ) & 0xFF ); - - *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); - - *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); - - memcpy( p, sig_alg_list, sig_alg_len ); - - p += sig_alg_len; - } - - ssl->out_msglen = p - buf; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_CLIENT_HELLO; - - ssl->state++; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); - - return( 0 ); -} - -static int ssl_parse_server_hello( ssl_context *ssl ) -{ -#if defined(POLARSSL_DEBUG_C) - time_t t; -#endif - int ret, i; - size_t n; - int ext_len; - unsigned char *buf; - - SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 protocol version - * 6 . 9 UNIX time() - * 10 . 37 random bytes - */ - buf = ssl->in_msg; - - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", - buf[4], buf[5] ) ); - - if( ssl->in_hslen < 42 || - buf[0] != SSL_HS_SERVER_HELLO || - buf[4] != SSL_MAJOR_VERSION_3 ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - if( buf[5] > ssl->max_minor_ver ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ssl->minor_ver = buf[5]; - -#if defined(POLARSSL_DEBUG_C) - t = ( (time_t) buf[6] << 24 ) - | ( (time_t) buf[7] << 16 ) - | ( (time_t) buf[8] << 8 ) - | ( (time_t) buf[9] ); -#endif - - memcpy( ssl->randbytes + 32, buf + 6, 32 ); - - n = buf[38]; - - SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); - SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); - - /* - * 38 . 38 session id length - * 39 . 38+n session id - * 39+n . 40+n chosen ciphersuite - * 41+n . 41+n chosen compression alg. - * 42+n . 43+n extensions length - * 44+n . 44+n+m extensions - */ - if( n > 32 || ssl->in_hslen > 42 + n ) - { - ext_len = ( ( buf[42 + n] << 8 ) - | ( buf[43 + n] ) ) + 2; - } - else - { - ext_len = 0; - } - - if( n > 32 || ssl->in_hslen != 42 + n + ext_len ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - i = ( buf[39 + n] << 8 ) | buf[40 + n]; - - /* - * Initialize update checksum functions - */ - ssl_kickstart_checksum( ssl, i, buf, ssl->in_hslen ); - - SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); - SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); - - /* - * Check if the session can be resumed - */ - if( ssl->resume == 0 || n == 0 || - ssl->session->ciphersuite != i || - ssl->session->length != n || - memcmp( ssl->session->id, buf + 39, n ) != 0 ) - { - ssl->state++; - ssl->resume = 0; - ssl->session->start = time( NULL ); - ssl->session->ciphersuite = i; - ssl->session->length = n; - memcpy( ssl->session->id, buf + 39, n ); - } - else - { - ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC; - - if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); - return( ret ); - } - } - - SSL_DEBUG_MSG( 3, ( "%s session has been resumed", - ssl->resume ? "a" : "no" ) ); - - SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) ); - SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) ); - - i = 0; - while( 1 ) - { - if( ssl->ciphersuites[i] == 0 ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - if( ssl->ciphersuites[i++] == ssl->session->ciphersuite ) - break; - } - - if( buf[41 + n] != SSL_COMPRESS_NULL ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - /* TODO: Process extensions */ - - SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); - - return( 0 ); -} - -static int ssl_parse_server_key_exchange( ssl_context *ssl ) -{ -#if defined(POLARSSL_DHM_C) - int ret; - size_t n; - unsigned char *p, *end; - unsigned char hash[64]; - md5_context md5; - sha1_context sha1; - int hash_id = SIG_RSA_RAW; - unsigned int hashlen = 0; -#endif - - SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); - - if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { - SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); - ssl->state++; - return( 0 ); - } - -#if !defined(POLARSSL_DHM_C) - SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); -#else - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE ) - { - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - SSL_DEBUG_BUF( 3, "server key exchange", ssl->in_msg + 4, ssl->in_hslen - 4 ); - - /* - * Ephemeral DH parameters: - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - p = ssl->in_msg + 4; - end = ssl->in_msg + ssl->in_hslen; - - if( ( ret = dhm_read_params( &ssl->dhm_ctx, &p, end ) ) != 0 ) - { - SSL_DEBUG_MSG( 2, ( "DHM Read Params returned -0x%x", -ret ) ); - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) - { - if( p[1] != SSL_SIG_RSA ) - { - SSL_DEBUG_MSG( 2, ( "Server used unsupported SignatureAlgorithm %d", p[1] ) ); - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - switch( p[0] ) - { -#if defined(POLARSSL_MD5_C) - case SSL_HASH_MD5: - hash_id = SIG_RSA_MD5; - break; -#endif -#if defined(POLARSSL_SHA1_C) - case SSL_HASH_SHA1: - hash_id = SIG_RSA_SHA1; - break; -#endif -#if defined(POLARSSL_SHA2_C) - case SSL_HASH_SHA224: - hash_id = SIG_RSA_SHA224; - break; - case SSL_HASH_SHA256: - hash_id = SIG_RSA_SHA256; - break; -#endif -#if defined(POLARSSL_SHA4_C) - case SSL_HASH_SHA384: - hash_id = SIG_RSA_SHA384; - break; - case SSL_HASH_SHA512: - hash_id = SIG_RSA_SHA512; - break; -#endif - default: - SSL_DEBUG_MSG( 2, ( "Server used unsupported HashAlgorithm %d", p[0] ) ); - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", p[1] ) ); - SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", p[0] ) ); - p += 2; - } - - n = ( p[0] << 8 ) | p[1]; - p += 2; - - if( end != p + n ) - { - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - if( (unsigned int)( end - p ) != ssl->peer_cert->rsa.len ) - { - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - if( ssl->dhm_ctx.len < 64 || ssl->dhm_ctx.len > 512 ) - { - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P ); - SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G ); - SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY ); - - if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) - { - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); - */ - n = ssl->in_hslen - ( end - p ) - 6; - - md5_starts( &md5 ); - md5_update( &md5, ssl->randbytes, 64 ); - md5_update( &md5, ssl->in_msg + 4, n ); - md5_finish( &md5, hash ); - - sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->randbytes, 64 ); - sha1_update( &sha1, ssl->in_msg + 4, n ); - sha1_finish( &sha1, hash + 16 ); - - hash_id = SIG_RSA_RAW; - hashlen = 36; - } - else - { - sha2_context sha2; - sha4_context sha4; - - n = ssl->in_hslen - ( end - p ) - 8; - - /* - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * }; - */ - switch( hash_id ) - { -#if defined(POLARSSL_MD5_C) - case SIG_RSA_MD5: - md5_starts( &md5 ); - md5_update( &md5, ssl->randbytes, 64 ); - md5_update( &md5, ssl->in_msg + 4, n ); - md5_finish( &md5, hash ); - hashlen = 16; - break; -#endif -#if defined(POLARSSL_SHA1_C) - case SIG_RSA_SHA1: - sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->randbytes, 64 ); - sha1_update( &sha1, ssl->in_msg + 4, n ); - sha1_finish( &sha1, hash ); - hashlen = 20; - break; -#endif -#if defined(POLARSSL_SHA2_C) - case SIG_RSA_SHA224: - sha2_starts( &sha2, 1 ); - sha2_update( &sha2, ssl->randbytes, 64 ); - sha2_update( &sha2, ssl->in_msg + 4, n ); - sha2_finish( &sha2, hash ); - hashlen = 28; - break; - case SIG_RSA_SHA256: - sha2_starts( &sha2, 0 ); - sha2_update( &sha2, ssl->randbytes, 64 ); - sha2_update( &sha2, ssl->in_msg + 4, n ); - sha2_finish( &sha2, hash ); - hashlen = 32; - break; -#endif -#if defined(POLARSSL_SHA4_C) - case SIG_RSA_SHA384: - sha4_starts( &sha4, 1 ); - sha4_update( &sha4, ssl->randbytes, 64 ); - sha4_update( &sha4, ssl->in_msg + 4, n ); - sha4_finish( &sha4, hash ); - hashlen = 48; - break; - case SIG_RSA_SHA512: - sha4_starts( &sha4, 0 ); - sha4_update( &sha4, ssl->randbytes, 64 ); - sha4_update( &sha4, ssl->in_msg + 4, n ); - sha4_finish( &sha4, hash ); - hashlen = 64; - break; -#endif - } - } - - SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); - - if( ( ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC, - hash_id, hashlen, hash, p ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret ); - return( ret ); - } - - ssl->state++; - - SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); - - return( 0 ); -#endif -} - -static int ssl_parse_certificate_request( ssl_context *ssl ) -{ - int ret; - - SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 SSL version - * 6 . 6 cert type count - * 7 .. n-1 cert types - * n .. n+1 length of all DNs - * n+2 .. n+3 length of DN 1 - * n+4 .. ... Distinguished Name #1 - * ... .. ... length of DN 2, etc. - */ - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - ssl->client_auth = 0; - ssl->state++; - - if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST ) - ssl->client_auth++; - - SSL_DEBUG_MSG( 3, ( "got %s certificate request", - ssl->client_auth ? "a" : "no" ) ); - - SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); - - return( 0 ); -} - -static int ssl_parse_server_hello_done( ssl_context *ssl ) -{ - int ret; - - SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); - - if( ssl->client_auth != 0 ) - { - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); - } - } - - if( ssl->in_hslen != 4 || - ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); - } - - ssl->state++; - - SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); - - return( 0 ); -} - -static int ssl_write_client_key_exchange( ssl_context *ssl ) -{ - int ret; - size_t i, n; - - SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); - - if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { -#if !defined(POLARSSL_DHM_C) - SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); -#else - /* - * DHM key exchange -- send G^X mod P - */ - n = ssl->dhm_ctx.len; - - ssl->out_msg[4] = (unsigned char)( n >> 8 ); - ssl->out_msg[5] = (unsigned char)( n ); - i = 6; - - ret = dhm_make_public( &ssl->dhm_ctx, 256, - &ssl->out_msg[i], n, - ssl->f_rng, ssl->p_rng ); - if( ret != 0 ) - { - SSL_DEBUG_RET( 1, "dhm_make_public", ret ); - return( ret ); - } - - SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X ); - SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX ); - - ssl->pmslen = ssl->dhm_ctx.len; - - if( ( ret = dhm_calc_secret( &ssl->dhm_ctx, - ssl->premaster, - &ssl->pmslen ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); - return( ret ); - } - - SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K ); -#endif - } - else - { - /* - * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster)) - */ - ssl->premaster[0] = (unsigned char) ssl->max_major_ver; - ssl->premaster[1] = (unsigned char) ssl->max_minor_ver; - ssl->pmslen = 48; - - ret = ssl->f_rng( ssl->p_rng, ssl->premaster + 2, ssl->pmslen - 2 ); - if( ret != 0 ) - return( ret ); - - i = 4; - n = ssl->peer_cert->rsa.len; - - if( ssl->minor_ver != SSL_MINOR_VERSION_0 ) - { - i += 2; - ssl->out_msg[4] = (unsigned char)( n >> 8 ); - ssl->out_msg[5] = (unsigned char)( n ); - } - - ret = rsa_pkcs1_encrypt( &ssl->peer_cert->rsa, - ssl->f_rng, ssl->p_rng, - RSA_PUBLIC, - ssl->pmslen, ssl->premaster, - ssl->out_msg + i ); - if( ret != 0 ) - { - SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret ); - return( ret ); - } - } - - if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); - return( ret ); - } - - ssl->out_msglen = i + n; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_CLIENT_KEY_EXCHANGE; - - ssl->state++; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); - - return( 0 ); -} - -static int ssl_write_certificate_verify( ssl_context *ssl ) -{ - int ret = 0; - size_t n = 0, offset = 0; - unsigned char hash[48]; - int hash_id = SIG_RSA_RAW; - unsigned int hashlen = 36; - - SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); - - if( ssl->client_auth == 0 || ssl->own_cert == NULL ) - { - SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) - { - // TODO TLS1.2 Should be based on allowed signature algorithm received in - // Certificate Request according to RFC 5246. But OpenSSL only allows - // SHA256 and SHA384. Find out why OpenSSL does this. - // - if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { - hash_id = SIG_RSA_SHA384; - hashlen = 48; - } - else - { - hash_id = SIG_RSA_SHA256; - hashlen = 32; - } - } - - if( ssl->rsa_key == NULL ) - { -#if defined(POLARSSL_PKCS11_C) - if( ssl->pkcs11_key == NULL ) - { -#endif /* defined(POLARSSL_PKCS11_C) */ - SSL_DEBUG_MSG( 1, ( "got no private key" ) ); - return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); -#if defined(POLARSSL_PKCS11_C) - } -#endif /* defined(POLARSSL_PKCS11_C) */ - } - - /* - * Make an RSA signature of the handshake digests - */ - ssl->calc_verify( ssl, hash ); - - if ( ssl->rsa_key ) - n = ssl->rsa_key->len; -#if defined(POLARSSL_PKCS11_C) - else - n = ssl->pkcs11_key->len; -#endif /* defined(POLARSSL_PKCS11_C) */ - - if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) - { - // TODO TLS1.2 Should be based on allowed signature algorithm received in - // Certificate Request according to RFC 5246. But OpenSSL only allows - // SHA256 and SHA384. Find out why OpenSSL does this. - // - if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { - ssl->out_msg[4] = SSL_HASH_SHA384; - ssl->out_msg[5] = SSL_SIG_RSA; - } - else - { - ssl->out_msg[4] = SSL_HASH_SHA256; - ssl->out_msg[5] = SSL_SIG_RSA; - } - - offset = 2; - } - - ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); - ssl->out_msg[5 + offset] = (unsigned char)( n ); - - if( ssl->rsa_key ) - { - ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng, - RSA_PRIVATE, hash_id, - hashlen, hash, ssl->out_msg + 6 + offset ); - } else { -#if defined(POLARSSL_PKCS11_C) - ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE, hash_id, - hashlen, hash, ssl->out_msg + 6 + offset ); -#endif /* defined(POLARSSL_PKCS11_C) */ - } - - if (ret != 0) - { - SSL_DEBUG_RET( 1, "pkcs1_sign", ret ); - return( ret ); - } - - ssl->out_msglen = 6 + n + offset; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_CERTIFICATE_VERIFY; - - ssl->state++; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); - - return( 0 ); -} - -/* - * SSL handshake -- client side - */ -int ssl_handshake_client( ssl_context *ssl ) -{ - int ret = 0; - - SSL_DEBUG_MSG( 2, ( "=> handshake client" ) ); - - while( ssl->state != SSL_HANDSHAKE_OVER ) - { - SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); - - if( ( ret = ssl_flush_output( ssl ) ) != 0 ) - break; - - switch( ssl->state ) - { - case SSL_HELLO_REQUEST: - ssl->state = SSL_CLIENT_HELLO; - break; - - /* - * ==> ClientHello - */ - case SSL_CLIENT_HELLO: - ret = ssl_write_client_hello( ssl ); - break; - - /* - * <== ServerHello - * Certificate - * ( ServerKeyExchange ) - * ( CertificateRequest ) - * ServerHelloDone - */ - case SSL_SERVER_HELLO: - ret = ssl_parse_server_hello( ssl ); - break; - - case SSL_SERVER_CERTIFICATE: - ret = ssl_parse_certificate( ssl ); - break; - - case SSL_SERVER_KEY_EXCHANGE: - ret = ssl_parse_server_key_exchange( ssl ); - break; - - case SSL_CERTIFICATE_REQUEST: - ret = ssl_parse_certificate_request( ssl ); - break; - - case SSL_SERVER_HELLO_DONE: - ret = ssl_parse_server_hello_done( ssl ); - break; - - /* - * ==> ( Certificate/Alert ) - * ClientKeyExchange - * ( CertificateVerify ) - * ChangeCipherSpec - * Finished - */ - case SSL_CLIENT_CERTIFICATE: - ret = ssl_write_certificate( ssl ); - break; - - case SSL_CLIENT_KEY_EXCHANGE: - ret = ssl_write_client_key_exchange( ssl ); - break; - - case SSL_CERTIFICATE_VERIFY: - ret = ssl_write_certificate_verify( ssl ); - break; - - case SSL_CLIENT_CHANGE_CIPHER_SPEC: - ret = ssl_write_change_cipher_spec( ssl ); - break; - - case SSL_CLIENT_FINISHED: - ret = ssl_write_finished( ssl ); - break; - - /* - * <== ChangeCipherSpec - * Finished - */ - case SSL_SERVER_CHANGE_CIPHER_SPEC: - ret = ssl_parse_change_cipher_spec( ssl ); - break; - - case SSL_SERVER_FINISHED: - ret = ssl_parse_finished( ssl ); - break; - - case SSL_FLUSH_BUFFERS: - SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); - ssl->state = SSL_HANDSHAKE_OVER; - break; - - default: - SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - } - - if( ret != 0 ) - break; - } - - SSL_DEBUG_MSG( 2, ( "<= handshake client" ) ); - - return( ret ); -} - -#endif diff --git a/polarssl/src/library/ssl_srv.c b/polarssl/src/library/ssl_srv.c deleted file mode 100644 index ecf1536..0000000 --- a/polarssl/src/library/ssl_srv.c +++ /dev/null @@ -1,1080 +0,0 @@ -/* - * SSLv3/TLSv1 server-side functions - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_SSL_SRV_C) - -#include "polarssl/debug.h" -#include "polarssl/ssl.h" - -#if defined(POLARSSL_PKCS11_C) -#include "polarssl/pkcs11.h" -#endif /* defined(POLARSSL_PKCS11_C) */ - -#include -#include -#include - -static int ssl_parse_client_hello( ssl_context *ssl ) -{ - int ret; - unsigned int i, j; - size_t n; - unsigned int ciph_len, sess_len; - unsigned int chal_len, comp_len; - unsigned char *buf, *p; - - SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); - - if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); - return( ret ); - } - - buf = ssl->in_hdr; - - if( ( buf[0] & 0x80 ) != 0 ) - { - SSL_DEBUG_BUF( 4, "record header", buf, 5 ); - - SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", - buf[2] ) ); - SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", - ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); - SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", - buf[3], buf[4] ) ); - - /* - * SSLv2 Client Hello - * - * Record layer: - * 0 . 1 message length - * - * SSL layer: - * 2 . 2 message type - * 3 . 4 protocol version - */ - if( buf[2] != SSL_HS_CLIENT_HELLO || - buf[3] != SSL_MAJOR_VERSION_3 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; - - if( n < 17 || n > 512 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->max_major_ver = buf[3]; - ssl->max_minor_ver = buf[4]; - - ssl->major_ver = SSL_MAJOR_VERSION_3; - ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_3 ) - ? buf[4] : SSL_MINOR_VERSION_3; - - if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); - return( ret ); - } - - ssl->update_checksum( ssl, buf + 2, n ); - - buf = ssl->in_msg; - n = ssl->in_left - 5; - - /* - * 0 . 1 ciphersuitelist length - * 2 . 3 session id length - * 4 . 5 challenge length - * 6 . .. ciphersuitelist - * .. . .. session id - * .. . .. challenge - */ - SSL_DEBUG_BUF( 4, "record contents", buf, n ); - - ciph_len = ( buf[0] << 8 ) | buf[1]; - sess_len = ( buf[2] << 8 ) | buf[3]; - chal_len = ( buf[4] << 8 ) | buf[5]; - - SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", - ciph_len, sess_len, chal_len ) ); - - /* - * Make sure each parameter length is valid - */ - if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( sess_len > 32 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( chal_len < 8 || chal_len > 32 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( n != 6 + ciph_len + sess_len + chal_len ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", - buf + 6, ciph_len ); - SSL_DEBUG_BUF( 3, "client hello, session id", - buf + 6 + ciph_len, sess_len ); - SSL_DEBUG_BUF( 3, "client hello, challenge", - buf + 6 + ciph_len + sess_len, chal_len ); - - p = buf + 6 + ciph_len; - ssl->session->length = sess_len; - memset( ssl->session->id, 0, sizeof( ssl->session->id ) ); - memcpy( ssl->session->id, p, ssl->session->length ); - - p += sess_len; - memset( ssl->randbytes, 0, 64 ); - memcpy( ssl->randbytes + 32 - chal_len, p, chal_len ); - - for( i = 0; ssl->ciphersuites[i] != 0; i++ ) - { - for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) - { - if( p[0] == 0 && - p[1] == 0 && - p[2] == ssl->ciphersuites[i] ) - goto have_ciphersuite; - } - } - } - else - { - SSL_DEBUG_BUF( 4, "record header", buf, 5 ); - - SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", - buf[0] ) ); - SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", - ( buf[3] << 8 ) | buf[4] ) ); - SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]", - buf[1], buf[2] ) ); - - /* - * SSLv3 Client Hello - * - * Record layer: - * 0 . 0 message type - * 1 . 2 protocol version - * 3 . 4 message length - */ - if( buf[0] != SSL_MSG_HANDSHAKE || - buf[1] != SSL_MAJOR_VERSION_3 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - n = ( buf[3] << 8 ) | buf[4]; - - if( n < 45 || n > 512 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); - return( ret ); - } - - buf = ssl->in_msg; - n = ssl->in_left - 5; - - ssl->update_checksum( ssl, buf, n ); - - /* - * SSL layer: - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 protocol version - * 6 . 9 UNIX time() - * 10 . 37 random bytes - * 38 . 38 session id length - * 39 . 38+x session id - * 39+x . 40+x ciphersuitelist length - * 41+x . .. ciphersuitelist - * .. . .. compression alg. - * .. . .. extensions - */ - SSL_DEBUG_BUF( 4, "record contents", buf, n ); - - SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", - buf[0] ) ); - SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", - ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); - SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]", - buf[4], buf[5] ) ); - - /* - * Check the handshake type and protocol version - */ - if( buf[0] != SSL_HS_CLIENT_HELLO || - buf[4] != SSL_MAJOR_VERSION_3 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->major_ver = SSL_MAJOR_VERSION_3; - ssl->minor_ver = ( buf[5] <= SSL_MINOR_VERSION_3 ) - ? buf[5] : SSL_MINOR_VERSION_3; - - ssl->max_major_ver = buf[4]; - ssl->max_minor_ver = buf[5]; - - memcpy( ssl->randbytes, buf + 6, 32 ); - - /* - * Check the handshake message length - */ - if( buf[1] != 0 || n != (unsigned int) 4 + ( ( buf[2] << 8 ) | buf[3] ) ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* - * Check the session length - */ - sess_len = buf[38]; - - if( sess_len > 32 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->session->length = sess_len; - memset( ssl->session->id, 0, sizeof( ssl->session->id ) ); - memcpy( ssl->session->id, buf + 39 , ssl->session->length ); - - /* - * Check the ciphersuitelist length - */ - ciph_len = ( buf[39 + sess_len] << 8 ) - | ( buf[40 + sess_len] ); - - if( ciph_len < 2 || ciph_len > 256 || ( ciph_len % 2 ) != 0 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* - * Check the compression algorithms length - */ - comp_len = buf[41 + sess_len + ciph_len]; - - if( comp_len < 1 || comp_len > 16 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - SSL_DEBUG_BUF( 3, "client hello, random bytes", - buf + 6, 32 ); - SSL_DEBUG_BUF( 3, "client hello, session id", - buf + 38, sess_len ); - SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", - buf + 41 + sess_len, ciph_len ); - SSL_DEBUG_BUF( 3, "client hello, compression", - buf + 42 + sess_len + ciph_len, comp_len ); - - /* - * Search for a matching ciphersuite - */ - for( i = 0; ssl->ciphersuites[i] != 0; i++ ) - { - for( j = 0, p = buf + 41 + sess_len; j < ciph_len; - j += 2, p += 2 ) - { - if( p[0] == 0 && p[1] == ssl->ciphersuites[i] ) - goto have_ciphersuite; - } - } - } - - SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - - return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); - -have_ciphersuite: - - ssl->session->ciphersuite = ssl->ciphersuites[i]; - ssl_kickstart_checksum( ssl, ssl->session->ciphersuite, buf, n ); - - ssl->in_left = 0; - ssl->state++; - - SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); - - return( 0 ); -} - -static int ssl_write_server_hello( ssl_context *ssl ) -{ - time_t t; - int ret, n; - unsigned char *buf, *p; - - SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 protocol version - * 6 . 9 UNIX time() - * 10 . 37 random bytes - */ - buf = ssl->out_msg; - p = buf + 4; - - *p++ = (unsigned char) ssl->major_ver; - *p++ = (unsigned char) ssl->minor_ver; - - SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", - buf[4], buf[5] ) ); - - t = time( NULL ); - *p++ = (unsigned char)( t >> 24 ); - *p++ = (unsigned char)( t >> 16 ); - *p++ = (unsigned char)( t >> 8 ); - *p++ = (unsigned char)( t ); - - SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); - - if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 ) - return( ret ); - - p += 28; - - memcpy( ssl->randbytes + 32, buf + 6, 32 ); - - SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); - - /* - * 38 . 38 session id length - * 39 . 38+n session id - * 39+n . 40+n chosen ciphersuite - * 41+n . 41+n chosen compression alg. - */ - ssl->session->length = n = 32; - *p++ = (unsigned char) ssl->session->length; - - if( ssl->s_get == NULL || - ssl->s_get( ssl ) != 0 ) - { - /* - * Not found, create a new session id - */ - ssl->resume = 0; - ssl->state++; - - if( ssl->session == NULL ) - { - SSL_DEBUG_MSG( 1, ( "No session struct set" ) ); - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - } - - if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session->id, n ) ) != 0 ) - return( ret ); - } - else - { - /* - * Found a matching session, resume it - */ - ssl->resume = 1; - ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC; - - if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); - return( ret ); - } - } - - memcpy( p, ssl->session->id, ssl->session->length ); - p += ssl->session->length; - - SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); - SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); - SSL_DEBUG_MSG( 3, ( "%s session has been resumed", - ssl->resume ? "a" : "no" ) ); - - *p++ = (unsigned char)( ssl->session->ciphersuite >> 8 ); - *p++ = (unsigned char)( ssl->session->ciphersuite ); - *p++ = SSL_COMPRESS_NULL; - - SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", - ssl->session->ciphersuite ) ); - SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", 0 ) ); - - ssl->out_msglen = p - buf; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_SERVER_HELLO; - - ret = ssl_write_record( ssl ); - - SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); - - return( ret ); -} - -static int ssl_write_certificate_request( ssl_context *ssl ) -{ - int ret; - size_t n; - unsigned char *buf, *p; - const x509_cert *crt; - - SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); - - ssl->state++; - - if( ssl->authmode == SSL_VERIFY_NONE ) - { - SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); - return( 0 ); - } - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 4 cert type count - * 5 .. n-1 cert types - * n .. n+1 length of all DNs - * n+2 .. n+3 length of DN 1 - * n+4 .. ... Distinguished Name #1 - * ... .. ... length of DN 2, etc. - */ - buf = ssl->out_msg; - p = buf + 4; - - /* - * At the moment, only RSA certificates are supported - */ - *p++ = 1; - *p++ = 1; - - p += 2; - crt = ssl->ca_chain; - - while( crt != NULL ) - { - if( p - buf > 4096 ) - break; - - n = crt->subject_raw.len; - *p++ = (unsigned char)( n >> 8 ); - *p++ = (unsigned char)( n ); - memcpy( p, crt->subject_raw.p, n ); - - SSL_DEBUG_BUF( 3, "requested DN", p, n ); - p += n; crt = crt->next; - } - - ssl->out_msglen = n = p - buf; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_CERTIFICATE_REQUEST; - ssl->out_msg[6] = (unsigned char)( ( n - 8 ) >> 8 ); - ssl->out_msg[7] = (unsigned char)( ( n - 8 ) ); - - ret = ssl_write_record( ssl ); - - SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); - - return( ret ); -} - -static int ssl_write_server_key_exchange( ssl_context *ssl ) -{ -#if defined(POLARSSL_DHM_C) - int ret; - size_t n, rsa_key_len = 0; - unsigned char hash[48]; - md5_context md5; - sha1_context sha1; - int hash_id; - unsigned int hashlen; -#endif - - SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); - - if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { - SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); - ssl->state++; - return( 0 ); - } - -#if !defined(POLARSSL_DHM_C) - SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); -#else - - if( ssl->rsa_key == NULL ) - { -#if defined(POLARSSL_PKCS11_C) - if( ssl->pkcs11_key == NULL ) - { -#endif /* defined(POLARSSL_PKCS11_C) */ - SSL_DEBUG_MSG( 1, ( "got no private key" ) ); - return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); -#if defined(POLARSSL_PKCS11_C) - } -#endif /* defined(POLARSSL_PKCS11_C) */ - } - - /* - * Ephemeral DH parameters: - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - if( ( ret = dhm_make_params( &ssl->dhm_ctx, 256, ssl->out_msg + 4, - &n, ssl->f_rng, ssl->p_rng ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "dhm_make_params", ret ); - return( ret ); - } - - SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X ); - SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P ); - SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G ); - SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX ); - - if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) - { - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); - */ - md5_starts( &md5 ); - md5_update( &md5, ssl->randbytes, 64 ); - md5_update( &md5, ssl->out_msg + 4, n ); - md5_finish( &md5, hash ); - - sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->randbytes, 64 ); - sha1_update( &sha1, ssl->out_msg + 4, n ); - sha1_finish( &sha1, hash + 16 ); - - hashlen = 36; - hash_id = SIG_RSA_RAW; - } - else - { - /* - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * }; - */ - /* TODO TLS1.2 Get a supported hash algorithm from the - * signature_algorithms extension, Otherwise SHA1 + RSA! - */ - - sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->randbytes, 64 ); - sha1_update( &sha1, ssl->out_msg + 4, n ); - sha1_finish( &sha1, hash ); - - hashlen = 20; - hash_id = SIG_RSA_SHA1; - } - - SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); - - if ( ssl->rsa_key ) - rsa_key_len = ssl->rsa_key->len; -#if defined(POLARSSL_PKCS11_C) - else - rsa_key_len = ssl->pkcs11_key->len; -#endif /* defined(POLARSSL_PKCS11_C) */ - - if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) - { - // TODO TLS1.2 Base on selection above (SHA1 + RSA is default choice) - ssl->out_msg[4 + n] = SSL_HASH_SHA1; - ssl->out_msg[5 + n] = SSL_SIG_RSA; - - n += 2; - } - - ssl->out_msg[4 + n] = (unsigned char)( rsa_key_len >> 8 ); - ssl->out_msg[5 + n] = (unsigned char)( rsa_key_len ); - - if ( ssl->rsa_key ) - { - ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng, - RSA_PRIVATE, - hash_id, hashlen, hash, ssl->out_msg + 6 + n ); - } -#if defined(POLARSSL_PKCS11_C) - else { - ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE, - hash_id, hashlen, hash, ssl->out_msg + 6 + n ); - } -#endif /* defined(POLARSSL_PKCS11_C) */ - - if( ret != 0 ) - { - SSL_DEBUG_RET( 1, "pkcs1_sign", ret ); - return( ret ); - } - - SSL_DEBUG_BUF( 3, "my RSA sig", ssl->out_msg + 6 + n, rsa_key_len ); - - ssl->out_msglen = 6 + n + rsa_key_len; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_SERVER_KEY_EXCHANGE; - - ssl->state++; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); - - return( 0 ); -#endif -} - -static int ssl_write_server_hello_done( ssl_context *ssl ) -{ - int ret; - - SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); - - ssl->out_msglen = 4; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_SERVER_HELLO_DONE; - - ssl->state++; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); - - return( 0 ); -} - -static int ssl_parse_client_key_exchange( ssl_context *ssl ) -{ - int ret; - size_t i, n = 0; - - SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); - - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE ) - { - SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { -#if !defined(POLARSSL_DHM_C) - SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); -#else - /* - * Receive G^Y mod P, premaster = (G^Y)^X mod P - */ - n = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - - if( n < 1 || n > ssl->dhm_ctx.len || - n + 6 != ssl->in_hslen ) - { - SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = dhm_read_public( &ssl->dhm_ctx, - ssl->in_msg + 6, n ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "dhm_read_public", ret ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP ); - } - - SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY ); - - ssl->pmslen = ssl->dhm_ctx.len; - - if( ( ret = dhm_calc_secret( &ssl->dhm_ctx, - ssl->premaster, &ssl->pmslen ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS ); - } - - SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K ); -#endif - } - else - { - if( ssl->rsa_key == NULL ) - { -#if defined(POLARSSL_PKCS11_C) - if( ssl->pkcs11_key == NULL ) - { -#endif - SSL_DEBUG_MSG( 1, ( "got no private key" ) ); - return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); -#if defined(POLARSSL_PKCS11_C) - } -#endif - } - - /* - * Decrypt the premaster using own private RSA key - */ - i = 4; - if( ssl->rsa_key ) - n = ssl->rsa_key->len; -#if defined(POLARSSL_PKCS11_C) - else - n = ssl->pkcs11_key->len; -#endif - ssl->pmslen = 48; - - if( ssl->minor_ver != SSL_MINOR_VERSION_0 ) - { - i += 2; - if( ssl->in_msg[4] != ( ( n >> 8 ) & 0xFF ) || - ssl->in_msg[5] != ( ( n ) & 0xFF ) ) - { - SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - } - - if( ssl->in_hslen != i + n ) - { - SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ssl->rsa_key ) { - ret = rsa_pkcs1_decrypt( ssl->rsa_key, RSA_PRIVATE, &ssl->pmslen, - ssl->in_msg + i, ssl->premaster, - sizeof(ssl->premaster) ); - } -#if defined(POLARSSL_PKCS11_C) - else { - ret = pkcs11_decrypt( ssl->pkcs11_key, RSA_PRIVATE, &ssl->pmslen, - ssl->in_msg + i, ssl->premaster, - sizeof(ssl->premaster) ); - } -#endif /* defined(POLARSSL_PKCS11_C) */ - - if( ret != 0 || ssl->pmslen != 48 || - ssl->premaster[0] != ssl->max_major_ver || - ssl->premaster[1] != ssl->max_minor_ver ) - { - SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - - /* - * Protection against Bleichenbacher's attack: - * invalid PKCS#1 v1.5 padding must not cause - * the connection to end immediately; instead, - * send a bad_record_mac later in the handshake. - */ - ssl->pmslen = 48; - - ret = ssl->f_rng( ssl->p_rng, ssl->premaster, ssl->pmslen ); - if( ret != 0 ) - return( ret ); - } - } - - if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); - return( ret ); - } - - if( ssl->s_set != NULL ) - ssl->s_set( ssl ); - - ssl->state++; - - SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); - - return( 0 ); -} - -static int ssl_parse_certificate_verify( ssl_context *ssl ) -{ - int ret; - size_t n1, n2; - unsigned char hash[48]; - - SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); - - if( ssl->peer_cert == NULL ) - { - SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - ssl->calc_verify( ssl, hash ); - - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - ssl->state++; - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - n1 = ssl->peer_cert->rsa.len; - n2 = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - - if( n1 + 6 != ssl->in_hslen || n1 != n2 ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC, - SIG_RSA_RAW, 36, hash, ssl->in_msg + 6 ); - if( ret != 0 ) - { - SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); - - return( 0 ); -} - -/* - * SSL handshake -- server side - */ -int ssl_handshake_server( ssl_context *ssl ) -{ - int ret = 0; - - SSL_DEBUG_MSG( 2, ( "=> handshake server" ) ); - - while( ssl->state != SSL_HANDSHAKE_OVER ) - { - SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); - - if( ( ret = ssl_flush_output( ssl ) ) != 0 ) - break; - - switch( ssl->state ) - { - case SSL_HELLO_REQUEST: - ssl->state = SSL_CLIENT_HELLO; - break; - - /* - * <== ClientHello - */ - case SSL_CLIENT_HELLO: - ret = ssl_parse_client_hello( ssl ); - break; - - /* - * ==> ServerHello - * Certificate - * ( ServerKeyExchange ) - * ( CertificateRequest ) - * ServerHelloDone - */ - case SSL_SERVER_HELLO: - ret = ssl_write_server_hello( ssl ); - break; - - case SSL_SERVER_CERTIFICATE: - ret = ssl_write_certificate( ssl ); - break; - - case SSL_SERVER_KEY_EXCHANGE: - ret = ssl_write_server_key_exchange( ssl ); - break; - - case SSL_CERTIFICATE_REQUEST: - ret = ssl_write_certificate_request( ssl ); - break; - - case SSL_SERVER_HELLO_DONE: - ret = ssl_write_server_hello_done( ssl ); - break; - - /* - * <== ( Certificate/Alert ) - * ClientKeyExchange - * ( CertificateVerify ) - * ChangeCipherSpec - * Finished - */ - case SSL_CLIENT_CERTIFICATE: - ret = ssl_parse_certificate( ssl ); - break; - - case SSL_CLIENT_KEY_EXCHANGE: - ret = ssl_parse_client_key_exchange( ssl ); - break; - - case SSL_CERTIFICATE_VERIFY: - ret = ssl_parse_certificate_verify( ssl ); - break; - - case SSL_CLIENT_CHANGE_CIPHER_SPEC: - ret = ssl_parse_change_cipher_spec( ssl ); - break; - - case SSL_CLIENT_FINISHED: - ret = ssl_parse_finished( ssl ); - break; - - /* - * ==> ChangeCipherSpec - * Finished - */ - case SSL_SERVER_CHANGE_CIPHER_SPEC: - ret = ssl_write_change_cipher_spec( ssl ); - break; - - case SSL_SERVER_FINISHED: - ret = ssl_write_finished( ssl ); - break; - - case SSL_FLUSH_BUFFERS: - SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); - ssl->state = SSL_HANDSHAKE_OVER; - break; - - default: - SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - } - - if( ret != 0 ) - break; - } - - SSL_DEBUG_MSG( 2, ( "<= handshake server" ) ); - - return( ret ); -} - -#endif diff --git a/polarssl/src/library/ssl_tls.c b/polarssl/src/library/ssl_tls.c deleted file mode 100644 index 88c6e55..0000000 --- a/polarssl/src/library/ssl_tls.c +++ /dev/null @@ -1,3166 +0,0 @@ -/* - * SSLv3/TLSv1 shared functions - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The SSL 3.0 specification was drafted by Netscape in 1996, - * and became an IETF standard in 1999. - * - * http://wp.netscape.com/eng/ssl3/ - * http://www.ietf.org/rfc/rfc2246.txt - * http://www.ietf.org/rfc/rfc4346.txt - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_SSL_TLS_C) - -#include "polarssl/aes.h" -#include "polarssl/arc4.h" -#include "polarssl/camellia.h" -#include "polarssl/des.h" -#include "polarssl/debug.h" -#include "polarssl/ssl.h" -#include "polarssl/sha2.h" - -#if defined(POLARSSL_GCM_C) -#include "polarssl/gcm.h" -#endif - -#include -#include - -#if defined _MSC_VER && !defined strcasecmp -#define strcasecmp _stricmp -#endif - -/* - * Key material generation - */ -static int tls1_prf( unsigned char *secret, size_t slen, char *label, - unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t nb, hs; - size_t i, j, k; - unsigned char *S1, *S2; - unsigned char tmp[128]; - unsigned char h_i[20]; - - if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - - hs = ( slen + 1 ) / 2; - S1 = secret; - S2 = secret + slen - hs; - - nb = strlen( label ); - memcpy( tmp + 20, label, nb ); - memcpy( tmp + 20 + nb, random, rlen ); - nb += rlen; - - /* - * First compute P_md5(secret,label+random)[0..dlen] - */ - md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp ); - - for( i = 0; i < dlen; i += 16 ) - { - md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i ); - md5_hmac( S1, hs, 4 + tmp, 16, 4 + tmp ); - - k = ( i + 16 > dlen ) ? dlen % 16 : 16; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = h_i[j]; - } - - /* - * XOR out with P_sha1(secret,label+random)[0..dlen] - */ - sha1_hmac( S2, hs, tmp + 20, nb, tmp ); - - for( i = 0; i < dlen; i += 20 ) - { - sha1_hmac( S2, hs, tmp, 20 + nb, h_i ); - sha1_hmac( S2, hs, tmp, 20, tmp ); - - k = ( i + 20 > dlen ) ? dlen % 20 : 20; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); - } - - memset( tmp, 0, sizeof( tmp ) ); - memset( h_i, 0, sizeof( h_i ) ); - - return( 0 ); -} - -static int tls_prf_sha256( unsigned char *secret, size_t slen, char *label, - unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t nb; - size_t i, j, k; - unsigned char tmp[128]; - unsigned char h_i[32]; - - if( sizeof( tmp ) < 32 + strlen( label ) + rlen ) - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - - nb = strlen( label ); - memcpy( tmp + 32, label, nb ); - memcpy( tmp + 32 + nb, random, rlen ); - nb += rlen; - - /* - * Compute P_(secret, label + random)[0..dlen] - */ - sha2_hmac( secret, slen, tmp + 32, nb, tmp, 0 ); - - for( i = 0; i < dlen; i += 32 ) - { - sha2_hmac( secret, slen, tmp, 32 + nb, h_i, 0 ); - sha2_hmac( secret, slen, tmp, 32, tmp, 0 ); - - k = ( i + 32 > dlen ) ? dlen % 32 : 32; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = h_i[j]; - } - - memset( tmp, 0, sizeof( tmp ) ); - memset( h_i, 0, sizeof( h_i ) ); - - return( 0 ); -} - -static int tls_prf_sha384( unsigned char *secret, size_t slen, char *label, - unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t nb; - size_t i, j, k; - unsigned char tmp[128]; - unsigned char h_i[48]; - - if( sizeof( tmp ) < 48 + strlen( label ) + rlen ) - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - - nb = strlen( label ); - memcpy( tmp + 48, label, nb ); - memcpy( tmp + 48 + nb, random, rlen ); - nb += rlen; - - /* - * Compute P_(secret, label + random)[0..dlen] - */ - sha4_hmac( secret, slen, tmp + 48, nb, tmp, 1 ); - - for( i = 0; i < dlen; i += 48 ) - { - sha4_hmac( secret, slen, tmp, 48 + nb, h_i, 1 ); - sha4_hmac( secret, slen, tmp, 48, tmp, 1 ); - - k = ( i + 48 > dlen ) ? dlen % 48 : 48; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = h_i[j]; - } - - memset( tmp, 0, sizeof( tmp ) ); - memset( h_i, 0, sizeof( h_i ) ); - - return( 0 ); -} - -static void ssl_update_checksum_start(ssl_context *, unsigned char *, size_t); -static void ssl_update_checksum_md5sha1(ssl_context *, unsigned char *, size_t); -static void ssl_update_checksum_sha256(ssl_context *, unsigned char *, size_t); -static void ssl_update_checksum_sha384(ssl_context *, unsigned char *, size_t); - -static void ssl_calc_verify_ssl(ssl_context *,unsigned char *); -static void ssl_calc_verify_tls(ssl_context *,unsigned char *); -static void ssl_calc_verify_tls_sha256(ssl_context *,unsigned char *); -static void ssl_calc_verify_tls_sha384(ssl_context *,unsigned char *); - -static void ssl_calc_finished_ssl(ssl_context *,unsigned char *,int); -static void ssl_calc_finished_tls(ssl_context *,unsigned char *,int); -static void ssl_calc_finished_tls_sha256(ssl_context *,unsigned char *,int); -static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int); - -int ssl_derive_keys( ssl_context *ssl ) -{ - int i; - md5_context md5; - sha1_context sha1; - unsigned char tmp[64]; - unsigned char padding[16]; - unsigned char sha1sum[20]; - unsigned char keyblk[256]; - unsigned char *key1; - unsigned char *key2; - unsigned int iv_copy_len; - - SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); - - /* - * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions - */ - if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - ssl->tls_prf = tls1_prf; - ssl->calc_verify = ssl_calc_verify_ssl; - ssl->calc_finished = ssl_calc_finished_ssl; - } - else if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) - { - ssl->tls_prf = tls1_prf; - ssl->calc_verify = ssl_calc_verify_tls; - ssl->calc_finished = ssl_calc_finished_tls; - } - else if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { - ssl->tls_prf = tls_prf_sha384; - ssl->calc_verify = ssl_calc_verify_tls_sha384; - ssl->calc_finished = ssl_calc_finished_tls_sha384; - } - else - { - ssl->tls_prf = tls_prf_sha256; - ssl->calc_verify = ssl_calc_verify_tls_sha256; - ssl->calc_finished = ssl_calc_finished_tls_sha256; - } - - /* - * SSLv3: - * master = - * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) - * - * TLSv1: - * master = PRF( premaster, "master secret", randbytes )[0..47] - */ - if( ssl->resume == 0 ) - { - size_t len = ssl->pmslen; - - SSL_DEBUG_BUF( 3, "premaster secret", ssl->premaster, len ); - - if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - for( i = 0; i < 3; i++ ) - { - memset( padding, 'A' + i, 1 + i ); - - sha1_starts( &sha1 ); - sha1_update( &sha1, padding, 1 + i ); - sha1_update( &sha1, ssl->premaster, len ); - sha1_update( &sha1, ssl->randbytes, 64 ); - sha1_finish( &sha1, sha1sum ); - - md5_starts( &md5 ); - md5_update( &md5, ssl->premaster, len ); - md5_update( &md5, sha1sum, 20 ); - md5_finish( &md5, ssl->session->master + i * 16 ); - } - } - else - ssl->tls_prf( ssl->premaster, len, "master secret", - ssl->randbytes, 64, ssl->session->master, 48 ); - - memset( ssl->premaster, 0, sizeof( ssl->premaster ) ); - } - else - SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); - - /* - * Swap the client and server random values. - */ - memcpy( tmp, ssl->randbytes, 64 ); - memcpy( ssl->randbytes, tmp + 32, 32 ); - memcpy( ssl->randbytes + 32, tmp, 32 ); - memset( tmp, 0, sizeof( tmp ) ); - - /* - * SSLv3: - * key block = - * MD5( master + SHA1( 'A' + master + randbytes ) ) + - * MD5( master + SHA1( 'BB' + master + randbytes ) ) + - * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + - * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + - * ... - * - * TLSv1: - * key block = PRF( master, "key expansion", randbytes ) - */ - if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - for( i = 0; i < 16; i++ ) - { - memset( padding, 'A' + i, 1 + i ); - - sha1_starts( &sha1 ); - sha1_update( &sha1, padding, 1 + i ); - sha1_update( &sha1, ssl->session->master, 48 ); - sha1_update( &sha1, ssl->randbytes, 64 ); - sha1_finish( &sha1, sha1sum ); - - md5_starts( &md5 ); - md5_update( &md5, ssl->session->master, 48 ); - md5_update( &md5, sha1sum, 20 ); - md5_finish( &md5, keyblk + i * 16 ); - } - - memset( &md5, 0, sizeof( md5 ) ); - memset( &sha1, 0, sizeof( sha1 ) ); - - memset( padding, 0, sizeof( padding ) ); - memset( sha1sum, 0, sizeof( sha1sum ) ); - } - else - ssl->tls_prf( ssl->session->master, 48, "key expansion", - ssl->randbytes, 64, keyblk, 256 ); - - SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", ssl_get_ciphersuite( ssl ) ) ); - SSL_DEBUG_BUF( 3, "master secret", ssl->session->master, 48 ); - SSL_DEBUG_BUF( 4, "random bytes", ssl->randbytes, 64 ); - SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); - - memset( ssl->randbytes, 0, sizeof( ssl->randbytes ) ); - - /* - * Determine the appropriate key, IV and MAC length. - */ - switch( ssl->session->ciphersuite ) - { -#if defined(POLARSSL_ARC4_C) - case SSL_RSA_RC4_128_MD5: - ssl->keylen = 16; ssl->minlen = 16; - ssl->ivlen = 0; ssl->maclen = 16; - break; - - case SSL_RSA_RC4_128_SHA: - ssl->keylen = 16; ssl->minlen = 20; - ssl->ivlen = 0; ssl->maclen = 20; - break; -#endif - -#if defined(POLARSSL_DES_C) - case SSL_RSA_DES_168_SHA: - case SSL_EDH_RSA_DES_168_SHA: - ssl->keylen = 24; ssl->minlen = 24; - ssl->ivlen = 8; ssl->maclen = 20; - break; -#endif - -#if defined(POLARSSL_AES_C) - case SSL_RSA_AES_128_SHA: - case SSL_EDH_RSA_AES_128_SHA: - ssl->keylen = 16; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 20; - break; - - case SSL_RSA_AES_256_SHA: - case SSL_EDH_RSA_AES_256_SHA: - ssl->keylen = 32; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 20; - break; - -#if defined(POLARSSL_SHA2_C) - case SSL_RSA_AES_128_SHA256: - case SSL_EDH_RSA_AES_128_SHA256: - ssl->keylen = 16; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 32; - break; - - case SSL_RSA_AES_256_SHA256: - case SSL_EDH_RSA_AES_256_SHA256: - ssl->keylen = 32; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 32; - break; -#endif -#if defined(POLARSSL_GCM_C) - case SSL_RSA_AES_128_GCM_SHA256: - case SSL_EDH_RSA_AES_128_GCM_SHA256: - ssl->keylen = 16; ssl->minlen = 1; - ssl->ivlen = 12; ssl->maclen = 0; - ssl->fixed_ivlen = 4; - break; - - case SSL_RSA_AES_256_GCM_SHA384: - case SSL_EDH_RSA_AES_256_GCM_SHA384: - ssl->keylen = 32; ssl->minlen = 1; - ssl->ivlen = 12; ssl->maclen = 0; - ssl->fixed_ivlen = 4; - break; -#endif -#endif - -#if defined(POLARSSL_CAMELLIA_C) - case SSL_RSA_CAMELLIA_128_SHA: - case SSL_EDH_RSA_CAMELLIA_128_SHA: - ssl->keylen = 16; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 20; - break; - - case SSL_RSA_CAMELLIA_256_SHA: - case SSL_EDH_RSA_CAMELLIA_256_SHA: - ssl->keylen = 32; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 20; - break; - -#if defined(POLARSSL_SHA2_C) - case SSL_RSA_CAMELLIA_128_SHA256: - case SSL_EDH_RSA_CAMELLIA_128_SHA256: - ssl->keylen = 16; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 32; - break; - - case SSL_RSA_CAMELLIA_256_SHA256: - case SSL_EDH_RSA_CAMELLIA_256_SHA256: - ssl->keylen = 32; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 32; - break; -#endif -#endif - -#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - case SSL_RSA_NULL_MD5: - ssl->keylen = 0; ssl->minlen = 0; - ssl->ivlen = 0; ssl->maclen = 16; - break; - - case SSL_RSA_NULL_SHA: - ssl->keylen = 0; ssl->minlen = 0; - ssl->ivlen = 0; ssl->maclen = 20; - break; - - case SSL_RSA_NULL_SHA256: - ssl->keylen = 0; ssl->minlen = 0; - ssl->ivlen = 0; ssl->maclen = 32; - break; -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - -#if defined(POLARSSL_DES_C) - case SSL_RSA_DES_SHA: - case SSL_EDH_RSA_DES_SHA: - ssl->keylen = 8; ssl->minlen = 8; - ssl->ivlen = 8; ssl->maclen = 20; - break; -#endif -#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */ - - default: - SSL_DEBUG_MSG( 1, ( "ciphersuite %s is not available", - ssl_get_ciphersuite( ssl ) ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", - ssl->keylen, ssl->minlen, ssl->ivlen, ssl->maclen ) ); - - /* - * Finally setup the cipher contexts, IVs and MAC secrets. - */ - if( ssl->endpoint == SSL_IS_CLIENT ) - { - key1 = keyblk + ssl->maclen * 2; - key2 = keyblk + ssl->maclen * 2 + ssl->keylen; - - memcpy( ssl->mac_enc, keyblk, ssl->maclen ); - memcpy( ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen ); - - /* - * This is not used in TLS v1.1. - */ - iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen; - memcpy( ssl->iv_enc, key2 + ssl->keylen, iv_copy_len ); - memcpy( ssl->iv_dec, key2 + ssl->keylen + iv_copy_len, - iv_copy_len ); - } - else - { - key1 = keyblk + ssl->maclen * 2 + ssl->keylen; - key2 = keyblk + ssl->maclen * 2; - - memcpy( ssl->mac_dec, keyblk, ssl->maclen ); - memcpy( ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen ); - - /* - * This is not used in TLS v1.1. - */ - iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen; - memcpy( ssl->iv_dec, key1 + ssl->keylen, iv_copy_len ); - memcpy( ssl->iv_enc, key1 + ssl->keylen + iv_copy_len, - iv_copy_len ); - } - - switch( ssl->session->ciphersuite ) - { -#if defined(POLARSSL_ARC4_C) - case SSL_RSA_RC4_128_MD5: - case SSL_RSA_RC4_128_SHA: - arc4_setup( (arc4_context *) ssl->ctx_enc, key1, ssl->keylen ); - arc4_setup( (arc4_context *) ssl->ctx_dec, key2, ssl->keylen ); - break; -#endif - -#if defined(POLARSSL_DES_C) - case SSL_RSA_DES_168_SHA: - case SSL_EDH_RSA_DES_168_SHA: - des3_set3key_enc( (des3_context *) ssl->ctx_enc, key1 ); - des3_set3key_dec( (des3_context *) ssl->ctx_dec, key2 ); - break; -#endif - -#if defined(POLARSSL_AES_C) - case SSL_RSA_AES_128_SHA: - case SSL_EDH_RSA_AES_128_SHA: - case SSL_RSA_AES_128_SHA256: - case SSL_EDH_RSA_AES_128_SHA256: - aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 128 ); - aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 128 ); - break; - - case SSL_RSA_AES_256_SHA: - case SSL_EDH_RSA_AES_256_SHA: - case SSL_RSA_AES_256_SHA256: - case SSL_EDH_RSA_AES_256_SHA256: - aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 256 ); - aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 256 ); - break; - -#if defined(POLARSSL_GCM_C) - case SSL_RSA_AES_128_GCM_SHA256: - case SSL_EDH_RSA_AES_128_GCM_SHA256: - gcm_init( (gcm_context *) ssl->ctx_enc, key1, 128 ); - gcm_init( (gcm_context *) ssl->ctx_dec, key2, 128 ); - break; - - case SSL_RSA_AES_256_GCM_SHA384: - case SSL_EDH_RSA_AES_256_GCM_SHA384: - gcm_init( (gcm_context *) ssl->ctx_enc, key1, 256 ); - gcm_init( (gcm_context *) ssl->ctx_dec, key2, 256 ); - break; -#endif -#endif - -#if defined(POLARSSL_CAMELLIA_C) - case SSL_RSA_CAMELLIA_128_SHA: - case SSL_EDH_RSA_CAMELLIA_128_SHA: - case SSL_RSA_CAMELLIA_128_SHA256: - case SSL_EDH_RSA_CAMELLIA_128_SHA256: - camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 128 ); - camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 128 ); - break; - - case SSL_RSA_CAMELLIA_256_SHA: - case SSL_EDH_RSA_CAMELLIA_256_SHA: - case SSL_RSA_CAMELLIA_256_SHA256: - case SSL_EDH_RSA_CAMELLIA_256_SHA256: - camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 256 ); - camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 256 ); - break; -#endif - -#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - case SSL_RSA_NULL_MD5: - case SSL_RSA_NULL_SHA: - case SSL_RSA_NULL_SHA256: - break; -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - -#if defined(POLARSSL_DES_C) - case SSL_RSA_DES_SHA: - case SSL_EDH_RSA_DES_SHA: - des_setkey_enc( (des_context *) ssl->ctx_enc, key1 ); - des_setkey_dec( (des_context *) ssl->ctx_dec, key2 ); - break; -#endif -#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */ - - default: - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - memset( keyblk, 0, sizeof( keyblk ) ); - - SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); - - return( 0 ); -} - -void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] ) -{ - md5_context md5; - sha1_context sha1; - unsigned char pad_1[48]; - unsigned char pad_2[48]; - - SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); - - memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) ); - memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - sizeof( sha1_context ) ); - - memset( pad_1, 0x36, 48 ); - memset( pad_2, 0x5C, 48 ); - - md5_update( &md5, ssl->session->master, 48 ); - md5_update( &md5, pad_1, 48 ); - md5_finish( &md5, hash ); - - md5_starts( &md5 ); - md5_update( &md5, ssl->session->master, 48 ); - md5_update( &md5, pad_2, 48 ); - md5_update( &md5, hash, 16 ); - md5_finish( &md5, hash ); - - sha1_update( &sha1, ssl->session->master, 48 ); - sha1_update( &sha1, pad_1, 40 ); - sha1_finish( &sha1, hash + 16 ); - - sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->session->master, 48 ); - sha1_update( &sha1, pad_2, 40 ); - sha1_update( &sha1, hash + 16, 20 ); - sha1_finish( &sha1, hash + 16 ); - - SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); - SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - return; -} - -void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] ) -{ - md5_context md5; - sha1_context sha1; - - SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); - - memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) ); - memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - sizeof( sha1_context ) ); - - md5_finish( &md5, hash ); - sha1_finish( &sha1, hash + 16 ); - - SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); - SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - return; -} - -void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] ) -{ - sha2_context sha2; - - SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); - - memcpy( &sha2 , (sha2_context *) ssl->ctx_checksum, sizeof(sha2_context) ); - sha2_finish( &sha2, hash ); - - SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); - SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - return; -} - -void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] ) -{ - sha4_context sha4; - - SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); - - memcpy( &sha4 , (sha4_context *) ssl->ctx_checksum, sizeof(sha4_context) ); - sha4_finish( &sha4, hash ); - - SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); - SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - return; -} - -/* - * SSLv3.0 MAC functions - */ -static void ssl_mac_md5( unsigned char *secret, - unsigned char *buf, size_t len, - unsigned char *ctr, int type ) -{ - unsigned char header[11]; - unsigned char padding[48]; - md5_context md5; - - memcpy( header, ctr, 8 ); - header[ 8] = (unsigned char) type; - header[ 9] = (unsigned char)( len >> 8 ); - header[10] = (unsigned char)( len ); - - memset( padding, 0x36, 48 ); - md5_starts( &md5 ); - md5_update( &md5, secret, 16 ); - md5_update( &md5, padding, 48 ); - md5_update( &md5, header, 11 ); - md5_update( &md5, buf, len ); - md5_finish( &md5, buf + len ); - - memset( padding, 0x5C, 48 ); - md5_starts( &md5 ); - md5_update( &md5, secret, 16 ); - md5_update( &md5, padding, 48 ); - md5_update( &md5, buf + len, 16 ); - md5_finish( &md5, buf + len ); -} - -static void ssl_mac_sha1( unsigned char *secret, - unsigned char *buf, size_t len, - unsigned char *ctr, int type ) -{ - unsigned char header[11]; - unsigned char padding[40]; - sha1_context sha1; - - memcpy( header, ctr, 8 ); - header[ 8] = (unsigned char) type; - header[ 9] = (unsigned char)( len >> 8 ); - header[10] = (unsigned char)( len ); - - memset( padding, 0x36, 40 ); - sha1_starts( &sha1 ); - sha1_update( &sha1, secret, 20 ); - sha1_update( &sha1, padding, 40 ); - sha1_update( &sha1, header, 11 ); - sha1_update( &sha1, buf, len ); - sha1_finish( &sha1, buf + len ); - - memset( padding, 0x5C, 40 ); - sha1_starts( &sha1 ); - sha1_update( &sha1, secret, 20 ); - sha1_update( &sha1, padding, 40 ); - sha1_update( &sha1, buf + len, 20 ); - sha1_finish( &sha1, buf + len ); -} - -/* - * Encryption/decryption functions - */ -static int ssl_encrypt_buf( ssl_context *ssl ) -{ - size_t i, padlen; - - SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); - - /* - * Add MAC then encrypt - */ - if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - if( ssl->maclen == 16 ) - ssl_mac_md5( ssl->mac_enc, - ssl->out_msg, ssl->out_msglen, - ssl->out_ctr, ssl->out_msgtype ); - - if( ssl->maclen == 20 ) - ssl_mac_sha1( ssl->mac_enc, - ssl->out_msg, ssl->out_msglen, - ssl->out_ctr, ssl->out_msgtype ); - } - else - { - if( ssl->maclen == 16 ) - md5_hmac( ssl->mac_enc, 16, - ssl->out_ctr, ssl->out_msglen + 13, - ssl->out_msg + ssl->out_msglen ); - - if( ssl->maclen == 20 ) - sha1_hmac( ssl->mac_enc, 20, - ssl->out_ctr, ssl->out_msglen + 13, - ssl->out_msg + ssl->out_msglen ); - - if( ssl->maclen == 32 ) - sha2_hmac( ssl->mac_enc, 32, - ssl->out_ctr, ssl->out_msglen + 13, - ssl->out_msg + ssl->out_msglen, 0); - } - - SSL_DEBUG_BUF( 4, "computed mac", - ssl->out_msg + ssl->out_msglen, ssl->maclen ); - - ssl->out_msglen += ssl->maclen; - - if( ssl->ivlen == 0 ) - { - padlen = 0; - - SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); - - SSL_DEBUG_BUF( 4, "before encrypt: output payload", - ssl->out_msg, ssl->out_msglen ); - -#if defined(POLARSSL_ARC4_C) - if( ssl->session->ciphersuite == SSL_RSA_RC4_128_MD5 || - ssl->session->ciphersuite == SSL_RSA_RC4_128_SHA ) - { - arc4_crypt( (arc4_context *) ssl->ctx_enc, - ssl->out_msglen, ssl->out_msg, - ssl->out_msg ); - } else -#endif -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( ssl->session->ciphersuite == SSL_RSA_NULL_MD5 || - ssl->session->ciphersuite == SSL_RSA_NULL_SHA || - ssl->session->ciphersuite == SSL_RSA_NULL_SHA256 ) - { - } else -#endif - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); - } - else if( ssl->ivlen == 12 ) - { - size_t enc_msglen; - unsigned char *enc_msg; - unsigned char add_data[13]; - int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; - - padlen = 0; - enc_msglen = ssl->out_msglen; - - memcpy( add_data, ssl->out_ctr, 8 ); - add_data[8] = ssl->out_msgtype; - add_data[9] = ssl->major_ver; - add_data[10] = ssl->minor_ver; - add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; - add_data[12] = ssl->out_msglen & 0xFF; - - SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); - -#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C) - - if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { - /* - * Generate IV - */ - ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc + ssl->fixed_ivlen, - ssl->ivlen - ssl->fixed_ivlen ); - if( ret != 0 ) - return( ret ); - - /* - * Shift message for ivlen bytes and prepend IV - */ - memmove( ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen, - ssl->out_msg, ssl->out_msglen ); - memcpy( ssl->out_msg, ssl->iv_enc + ssl->fixed_ivlen, - ssl->ivlen - ssl->fixed_ivlen ); - - /* - * Fix pointer positions and message length with added IV - */ - enc_msg = ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen; - enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->ivlen - ssl->fixed_ivlen; - - SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); - - SSL_DEBUG_BUF( 4, "before encrypt: output payload", - ssl->out_msg, ssl->out_msglen ); - - /* - * Adjust for tag - */ - ssl->out_msglen += 16; - - gcm_crypt_and_tag( (gcm_context *) ssl->ctx_enc, - GCM_ENCRYPT, enc_msglen, - ssl->iv_enc, ssl->ivlen, - add_data, 13, - enc_msg, enc_msg, - 16, enc_msg + enc_msglen ); - - SSL_DEBUG_BUF( 4, "after encrypt: tag", - enc_msg + enc_msglen, 16 ); - - } else -#endif - return( ret ); - } - else - { - unsigned char *enc_msg; - size_t enc_msglen; - - padlen = ssl->ivlen - ( ssl->out_msglen + 1 ) % ssl->ivlen; - if( padlen == ssl->ivlen ) - padlen = 0; - - for( i = 0; i <= padlen; i++ ) - ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; - - ssl->out_msglen += padlen + 1; - - enc_msglen = ssl->out_msglen; - enc_msg = ssl->out_msg; - - /* - * Prepend per-record IV for block cipher in TLS v1.1 and up as per - * Method 1 (6.2.3.2. in RFC4346 and RFC5246) - */ - if( ssl->minor_ver >= SSL_MINOR_VERSION_2 ) - { - /* - * Generate IV - */ - int ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc, ssl->ivlen ); - if( ret != 0 ) - return( ret ); - - /* - * Shift message for ivlen bytes and prepend IV - */ - memmove( ssl->out_msg + ssl->ivlen, ssl->out_msg, ssl->out_msglen ); - memcpy( ssl->out_msg, ssl->iv_enc, ssl->ivlen ); - - /* - * Fix pointer positions and message length with added IV - */ - enc_msg = ssl->out_msg + ssl->ivlen; - enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->ivlen; - } - - SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of IV and %d bytes of padding", - ssl->out_msglen, ssl->ivlen, padlen + 1 ) ); - - SSL_DEBUG_BUF( 4, "before encrypt: output payload", - ssl->out_msg, ssl->out_msglen ); - - switch( ssl->ivlen ) - { -#if defined(POLARSSL_DES_C) - case 8: -#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) - if( ssl->session->ciphersuite == SSL_RSA_DES_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA ) - { - des_crypt_cbc( (des_context *) ssl->ctx_enc, - DES_ENCRYPT, enc_msglen, - ssl->iv_enc, enc_msg, enc_msg ); - } - else -#endif - des3_crypt_cbc( (des3_context *) ssl->ctx_enc, - DES_ENCRYPT, enc_msglen, - ssl->iv_enc, enc_msg, enc_msg ); - break; -#endif - - case 16: -#if defined(POLARSSL_AES_C) - if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_RSA_AES_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ) - { - aes_crypt_cbc( (aes_context *) ssl->ctx_enc, - AES_ENCRYPT, enc_msglen, - ssl->iv_enc, enc_msg, enc_msg); - break; - } -#endif - -#if defined(POLARSSL_CAMELLIA_C) - if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ) - { - camellia_crypt_cbc( (camellia_context *) ssl->ctx_enc, - CAMELLIA_ENCRYPT, enc_msglen, - ssl->iv_enc, enc_msg, enc_msg ); - break; - } -#endif - - default: - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); - } - } - - for( i = 8; i > 0; i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - - SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); - - return( 0 ); -} - -/* - * TODO: Use digest version when integrated! - */ -#define POLARSSL_SSL_MAX_MAC_SIZE 32 - -static int ssl_decrypt_buf( ssl_context *ssl ) -{ - size_t i, padlen; - unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE]; - - SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); - - if( ssl->in_msglen < ssl->minlen ) - { - SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", - ssl->in_msglen, ssl->minlen ) ); - return( POLARSSL_ERR_SSL_INVALID_MAC ); - } - - if( ssl->ivlen == 0 ) - { -#if defined(POLARSSL_ARC4_C) - padlen = 0; - if( ssl->session->ciphersuite == SSL_RSA_RC4_128_MD5 || - ssl->session->ciphersuite == SSL_RSA_RC4_128_SHA ) - { - arc4_crypt( (arc4_context *) ssl->ctx_dec, - ssl->in_msglen, ssl->in_msg, - ssl->in_msg ); - } else -#endif -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( ssl->session->ciphersuite == SSL_RSA_NULL_MD5 || - ssl->session->ciphersuite == SSL_RSA_NULL_SHA || - ssl->session->ciphersuite == SSL_RSA_NULL_SHA256 ) - { - } else -#endif - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); - } - else if( ssl->ivlen == 12 ) - { - unsigned char *dec_msg; - unsigned char *dec_msg_result; - size_t dec_msglen; - unsigned char add_data[13]; - int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; - - padlen = 0; - -#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C) - if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { - dec_msglen = ssl->in_msglen - ( ssl->ivlen - ssl->fixed_ivlen ); - dec_msglen -= 16; - dec_msg = ssl->in_msg + ( ssl->ivlen - ssl->fixed_ivlen ); - dec_msg_result = ssl->in_msg; - ssl->in_msglen = dec_msglen; - - memcpy( add_data, ssl->in_ctr, 8 ); - add_data[8] = ssl->in_msgtype; - add_data[9] = ssl->major_ver; - add_data[10] = ssl->minor_ver; - add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; - add_data[12] = ssl->in_msglen & 0xFF; - - SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); - - memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg, - ssl->ivlen - ssl->fixed_ivlen ); - - SSL_DEBUG_BUF( 4, "IV used", ssl->iv_dec, ssl->ivlen ); - SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 ); - - memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg, - ssl->ivlen - ssl->fixed_ivlen ); - - ret = gcm_auth_decrypt( (gcm_context *) ssl->ctx_dec, - dec_msglen, - ssl->iv_dec, ssl->ivlen, - add_data, 13, - dec_msg + dec_msglen, 16, - dec_msg, dec_msg_result ); - - if( ret != 0 ) - { - SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)", - -ret ) ); - - return( POLARSSL_ERR_SSL_INVALID_MAC ); - } - } else -#endif - return( ret ); - } - else - { - unsigned char *dec_msg; - unsigned char *dec_msg_result; - size_t dec_msglen; - - /* - * Decrypt and check the padding - */ - if( ssl->in_msglen % ssl->ivlen != 0 ) - { - SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", - ssl->in_msglen, ssl->ivlen ) ); - return( POLARSSL_ERR_SSL_INVALID_MAC ); - } - - dec_msglen = ssl->in_msglen; - dec_msg = ssl->in_msg; - dec_msg_result = ssl->in_msg; - - /* - * Initialize for prepended IV for block cipher in TLS v1.1 and up - */ - if( ssl->minor_ver >= SSL_MINOR_VERSION_2 ) - { - dec_msg += ssl->ivlen; - dec_msglen -= ssl->ivlen; - ssl->in_msglen -= ssl->ivlen; - - for( i = 0; i < ssl->ivlen; i++ ) - ssl->iv_dec[i] = ssl->in_msg[i]; - } - - switch( ssl->ivlen ) - { -#if defined(POLARSSL_DES_C) - case 8: -#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) - if( ssl->session->ciphersuite == SSL_RSA_DES_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA ) - { - des_crypt_cbc( (des_context *) ssl->ctx_dec, - DES_DECRYPT, dec_msglen, - ssl->iv_dec, dec_msg, dec_msg_result ); - } - else -#endif - des3_crypt_cbc( (des3_context *) ssl->ctx_dec, - DES_DECRYPT, dec_msglen, - ssl->iv_dec, dec_msg, dec_msg_result ); - break; -#endif - - case 16: -#if defined(POLARSSL_AES_C) - if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_RSA_AES_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ) - { - aes_crypt_cbc( (aes_context *) ssl->ctx_dec, - AES_DECRYPT, dec_msglen, - ssl->iv_dec, dec_msg, dec_msg_result ); - break; - } -#endif - -#if defined(POLARSSL_CAMELLIA_C) - if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ) - { - camellia_crypt_cbc( (camellia_context *) ssl->ctx_dec, - CAMELLIA_DECRYPT, dec_msglen, - ssl->iv_dec, dec_msg, dec_msg_result ); - break; - } -#endif - - default: - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; - - if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - if( padlen > ssl->ivlen ) - { - SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " - "should be no more than %d", - padlen, ssl->ivlen ) ); - padlen = 0; - } - } - else - { - /* - * TLSv1: always check the padding - */ - for( i = 1; i <= padlen; i++ ) - { - if( ssl->in_msg[ssl->in_msglen - i] != padlen - 1 ) - { - SSL_DEBUG_MSG( 1, ( "bad padding byte: should be " - "%02x, but is %02x", padlen - 1, - ssl->in_msg[ssl->in_msglen - i] ) ); - padlen = 0; - } - } - } - } - - SSL_DEBUG_BUF( 4, "raw buffer after decryption", - ssl->in_msg, ssl->in_msglen ); - - /* - * Always compute the MAC (RFC4346, CBCTIME). - */ - if( ssl->in_msglen < ssl->maclen + padlen ) - { - SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", - ssl->in_msglen, ssl->maclen, padlen ) ); - return( POLARSSL_ERR_SSL_INVALID_MAC ); - } - - ssl->in_msglen -= ( ssl->maclen + padlen ); - - ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 ); - ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen ); - - memcpy( tmp, ssl->in_msg + ssl->in_msglen, POLARSSL_SSL_MAX_MAC_SIZE ); - - if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - if( ssl->maclen == 16 ) - ssl_mac_md5( ssl->mac_dec, - ssl->in_msg, ssl->in_msglen, - ssl->in_ctr, ssl->in_msgtype ); - else if( ssl->maclen == 20 ) - ssl_mac_sha1( ssl->mac_dec, - ssl->in_msg, ssl->in_msglen, - ssl->in_ctr, ssl->in_msgtype ); - } - else - { - if( ssl->maclen == 16 ) - md5_hmac( ssl->mac_dec, 16, - ssl->in_ctr, ssl->in_msglen + 13, - ssl->in_msg + ssl->in_msglen ); - else if( ssl->maclen == 20 ) - sha1_hmac( ssl->mac_dec, 20, - ssl->in_ctr, ssl->in_msglen + 13, - ssl->in_msg + ssl->in_msglen ); - else if( ssl->maclen == 32 ) - sha2_hmac( ssl->mac_dec, 32, - ssl->in_ctr, ssl->in_msglen + 13, - ssl->in_msg + ssl->in_msglen, 0 ); - } - - SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->maclen ); - SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, - ssl->maclen ); - - if( memcmp( tmp, ssl->in_msg + ssl->in_msglen, - ssl->maclen ) != 0 ) - { - SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); - return( POLARSSL_ERR_SSL_INVALID_MAC ); - } - - /* - * Finally check the padding length; bad padding - * will produce the same error as an invalid MAC. - */ - if( ssl->ivlen != 0 && ssl->ivlen != 12 && padlen == 0 ) - return( POLARSSL_ERR_SSL_INVALID_MAC ); - - if( ssl->in_msglen == 0 ) - { - ssl->nb_zero++; - - /* - * Three or more empty messages may be a DoS attack - * (excessive CPU consumption). - */ - if( ssl->nb_zero > 3 ) - { - SSL_DEBUG_MSG( 1, ( "received four consecutive empty " - "messages, possible DoS attack" ) ); - return( POLARSSL_ERR_SSL_INVALID_MAC ); - } - } - else - ssl->nb_zero = 0; - - for( i = 8; i > 0; i-- ) - if( ++ssl->in_ctr[i - 1] != 0 ) - break; - - SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); - - return( 0 ); -} - -/* - * Fill the input message buffer - */ -int ssl_fetch_input( ssl_context *ssl, size_t nb_want ) -{ - int ret; - size_t len; - - SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); - - while( ssl->in_left < nb_want ) - { - len = nb_want - ssl->in_left; - ret = ssl->f_recv( ssl->p_recv, ssl->in_hdr + ssl->in_left, len ); - - SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - SSL_DEBUG_RET( 2, "ssl->f_recv", ret ); - - if( ret == 0 ) - return( POLARSSL_ERR_SSL_CONN_EOF ); - - if( ret < 0 ) - return( ret ); - - ssl->in_left += ret; - } - - SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); - - return( 0 ); -} - -/* - * Flush any data not yet written - */ -int ssl_flush_output( ssl_context *ssl ) -{ - int ret; - unsigned char *buf; - - SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); - - while( ssl->out_left > 0 ) - { - SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", - 5 + ssl->out_msglen, ssl->out_left ) ); - - buf = ssl->out_hdr + 5 + ssl->out_msglen - ssl->out_left; - ret = ssl->f_send( ssl->p_send, buf, ssl->out_left ); - SSL_DEBUG_RET( 2, "ssl->f_send", ret ); - - if( ret <= 0 ) - return( ret ); - - ssl->out_left -= ret; - } - - SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); - - return( 0 ); -} - -/* - * Record layer functions - */ -int ssl_write_record( ssl_context *ssl ) -{ - int ret; - size_t len = ssl->out_msglen; - - SSL_DEBUG_MSG( 2, ( "=> write record" ) ); - - ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; - ssl->out_hdr[1] = (unsigned char) ssl->major_ver; - ssl->out_hdr[2] = (unsigned char) ssl->minor_ver; - ssl->out_hdr[3] = (unsigned char)( len >> 8 ); - ssl->out_hdr[4] = (unsigned char)( len ); - - if( ssl->out_msgtype == SSL_MSG_HANDSHAKE ) - { - ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); - ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); - ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); - - ssl->update_checksum( ssl, ssl->out_msg, len ); - } - - if( ssl->do_crypt != 0 ) - { - if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); - return( ret ); - } - - len = ssl->out_msglen; - ssl->out_hdr[3] = (unsigned char)( len >> 8 ); - ssl->out_hdr[4] = (unsigned char)( len ); - } - - ssl->out_left = 5 + ssl->out_msglen; - - SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], - ( ssl->out_hdr[3] << 8 ) | ssl->out_hdr[4] ) ); - - SSL_DEBUG_BUF( 4, "output record sent to network", - ssl->out_hdr, 5 + ssl->out_msglen ); - - if( ( ret = ssl_flush_output( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_flush_output", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write record" ) ); - - return( 0 ); -} - -int ssl_read_record( ssl_context *ssl ) -{ - int ret; - - SSL_DEBUG_MSG( 2, ( "=> read record" ) ); - - if( ssl->in_hslen != 0 && - ssl->in_hslen < ssl->in_msglen ) - { - /* - * Get next Handshake message in the current record - */ - ssl->in_msglen -= ssl->in_hslen; - - memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, - ssl->in_msglen ); - - ssl->in_hslen = 4; - ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3]; - - SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" - " %d, type = %d, hslen = %d", - ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); - - if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 ) - { - SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - if( ssl->in_msglen < ssl->in_hslen ) - { - SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - ssl->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); - - return( 0 ); - } - - ssl->in_hslen = 0; - - /* - * Read the record header and validate it - */ - if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); - return( ret ); - } - - ssl->in_msgtype = ssl->in_hdr[0]; - ssl->in_msglen = ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4]; - - SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->in_hdr[0], ssl->in_hdr[1], ssl->in_hdr[2], - ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4] ) ); - - if( ssl->in_hdr[1] != ssl->major_ver ) - { - SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - if( ssl->in_hdr[2] > ssl->max_minor_ver ) - { - SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - /* - * Make sure the message length is acceptable - */ - if( ssl->do_crypt == 0 ) - { - if( ssl->in_msglen < 1 || - ssl->in_msglen > SSL_MAX_CONTENT_LEN ) - { - SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - } - else - { - if( ssl->in_msglen < ssl->minlen ) - { - SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - if( ssl->minor_ver == SSL_MINOR_VERSION_0 && - ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN ) - { - SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - /* - * TLS encrypted messages can have up to 256 bytes of padding - */ - if( ssl->minor_ver >= SSL_MINOR_VERSION_1 && - ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN + 256 ) - { - SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - } - - /* - * Read and optionally decrypt the message contents - */ - if( ( ret = ssl_fetch_input( ssl, 5 + ssl->in_msglen ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); - return( ret ); - } - - SSL_DEBUG_BUF( 4, "input record from network", - ssl->in_hdr, 5 + ssl->in_msglen ); - - if( ssl->do_crypt != 0 ) - { - if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); - return( ret ); - } - - SSL_DEBUG_BUF( 4, "input payload after decrypt", - ssl->in_msg, ssl->in_msglen ); - - if( ssl->in_msglen > SSL_MAX_CONTENT_LEN ) - { - SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - } - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE && - ssl->in_msgtype != SSL_MSG_ALERT && - ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC && - ssl->in_msgtype != SSL_MSG_APPLICATION_DATA ) - { - SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); - - if( ( ret = ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, - SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) - { - return( ret ); - } - - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - if( ssl->in_msgtype == SSL_MSG_HANDSHAKE ) - { - ssl->in_hslen = 4; - ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3]; - - SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" - " %d, type = %d, hslen = %d", - ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); - - /* - * Additional checks to validate the handshake header - */ - if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 ) - { - SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - if( ssl->in_msglen < ssl->in_hslen ) - { - SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); - return( POLARSSL_ERR_SSL_INVALID_RECORD ); - } - - ssl->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); - } - - if( ssl->in_msgtype == SSL_MSG_ALERT ) - { - SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", - ssl->in_msg[0], ssl->in_msg[1] ) ); - - /* - * Ignore non-fatal alerts, except close_notify - */ - if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL ) - { - SSL_DEBUG_MSG( 1, ( "is a fatal alert message" ) ); - /** - * Subtract from error code as ssl->in_msg[1] is 7-bit positive - * error identifier. - */ - return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE - ssl->in_msg[1] ); - } - - if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY ) - { - SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); - return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY ); - } - } - - ssl->in_left = 0; - - SSL_DEBUG_MSG( 2, ( "<= read record" ) ); - - return( 0 ); -} - -int ssl_send_alert_message( ssl_context *ssl, - unsigned char level, - unsigned char message ) -{ - int ret; - - SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); - - ssl->out_msgtype = SSL_MSG_ALERT; - ssl->out_msglen = 2; - ssl->out_msg[0] = level; - ssl->out_msg[1] = message; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); - - return( 0 ); -} - -/* - * Handshake functions - */ -int ssl_write_certificate( ssl_context *ssl ) -{ - int ret; - size_t i, n; - const x509_cert *crt; - - SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); - - if( ssl->endpoint == SSL_IS_CLIENT ) - { - if( ssl->client_auth == 0 ) - { - SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - - /* - * If using SSLv3 and got no cert, send an Alert message - * (otherwise an empty Certificate message will be sent). - */ - if( ssl->own_cert == NULL && - ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - ssl->out_msglen = 2; - ssl->out_msgtype = SSL_MSG_ALERT; - ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING; - ssl->out_msg[1] = SSL_ALERT_MSG_NO_CERT; - - SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); - goto write_msg; - } - } - else /* SSL_IS_SERVER */ - { - if( ssl->own_cert == NULL ) - { - SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); - return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED ); - } - } - - SSL_DEBUG_CRT( 3, "own certificate", ssl->own_cert ); - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 6 length of all certs - * 7 . 9 length of cert. 1 - * 10 . n-1 peer certificate - * n . n+2 length of cert. 2 - * n+3 . ... upper level cert, etc. - */ - i = 7; - crt = ssl->own_cert; - - while( crt != NULL ) - { - n = crt->raw.len; - if( i + 3 + n > SSL_MAX_CONTENT_LEN ) - { - SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", - i + 3 + n, SSL_MAX_CONTENT_LEN ) ); - return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE ); - } - - ssl->out_msg[i ] = (unsigned char)( n >> 16 ); - ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); - ssl->out_msg[i + 2] = (unsigned char)( n ); - - i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); - i += n; crt = crt->next; - } - - ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); - ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); - ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); - - ssl->out_msglen = i; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_CERTIFICATE; - -write_msg: - - ssl->state++; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); - - return( 0 ); -} - -int ssl_parse_certificate( ssl_context *ssl ) -{ - int ret; - size_t i, n; - - SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - - if( ssl->endpoint == SSL_IS_SERVER && - ssl->authmode == SSL_VERIFY_NONE ) - { - ssl->verify_result = BADCERT_SKIP_VERIFY; - SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - ssl->state++; - - /* - * Check if the client sent an empty certificate - */ - if( ssl->endpoint == SSL_IS_SERVER && - ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - if( ssl->in_msglen == 2 && - ssl->in_msgtype == SSL_MSG_ALERT && - ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == SSL_ALERT_MSG_NO_CERT ) - { - SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); - - ssl->verify_result = BADCERT_MISSING; - if( ssl->authmode == SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE ); - } - } - - if( ssl->endpoint == SSL_IS_SERVER && - ssl->minor_ver != SSL_MINOR_VERSION_0 ) - { - if( ssl->in_hslen == 7 && - ssl->in_msgtype == SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == SSL_HS_CERTIFICATE && - memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 ) - { - SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); - - ssl->verify_result = BADCERT_MISSING; - if( ssl->authmode == SSL_VERIFY_REQUIRED ) - return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE ); - else - return( 0 ); - } - } - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - /* - * Same message structure as in ssl_write_certificate() - */ - n = ( ssl->in_msg[5] << 8 ) | ssl->in_msg[6]; - - if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - if( ( ssl->peer_cert = (x509_cert *) malloc( - sizeof( x509_cert ) ) ) == NULL ) - { - SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", - sizeof( x509_cert ) ) ); - return( POLARSSL_ERR_SSL_MALLOC_FAILED ); - } - - memset( ssl->peer_cert, 0, sizeof( x509_cert ) ); - - i = 7; - - while( i < ssl->in_hslen ) - { - if( ssl->in_msg[i] != 0 ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) - | (unsigned int) ssl->in_msg[i + 2]; - i += 3; - - if( n < 128 || i + n > ssl->in_hslen ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - ret = x509parse_crt( ssl->peer_cert, ssl->in_msg + i, n ); - if( ret != 0 ) - { - SSL_DEBUG_RET( 1, " x509parse_crt", ret ); - return( ret ); - } - - i += n; - } - - SSL_DEBUG_CRT( 3, "peer certificate", ssl->peer_cert ); - - if( ssl->authmode != SSL_VERIFY_NONE ) - { - if( ssl->ca_chain == NULL ) - { - SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); - return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED ); - } - - ret = x509parse_verify( ssl->peer_cert, ssl->ca_chain, ssl->ca_crl, - ssl->peer_cn, &ssl->verify_result, - ssl->f_vrfy, ssl->p_vrfy ); - - if( ret != 0 ) - SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); - - if( ssl->authmode != SSL_VERIFY_REQUIRED ) - ret = 0; - } - - SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); - - return( ret ); -} - -int ssl_write_change_cipher_spec( ssl_context *ssl ) -{ - int ret; - - SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); - - ssl->out_msgtype = SSL_MSG_CHANGE_CIPHER_SPEC; - ssl->out_msglen = 1; - ssl->out_msg[0] = 1; - - ssl->do_crypt = 0; - ssl->state++; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); - - return( 0 ); -} - -int ssl_parse_change_cipher_spec( ssl_context *ssl ) -{ - int ret; - - SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); - - ssl->do_crypt = 0; - - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC ) - { - SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) - { - SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); - } - - ssl->state++; - - SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); - - return( 0 ); -} - -void ssl_kickstart_checksum( ssl_context *ssl, int ciphersuite, - unsigned char *input_buf, size_t len ) -{ - if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) - { - md5_starts( (md5_context *) ssl->ctx_checksum ); - sha1_starts( (sha1_context *) ( ssl->ctx_checksum + - sizeof(md5_context) ) ); - - ssl->update_checksum = ssl_update_checksum_md5sha1; - } - else if ( ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) - { - sha4_starts( (sha4_context *) ssl->ctx_checksum, 1 ); - ssl->update_checksum = ssl_update_checksum_sha384; - } - else - { - sha2_starts( (sha2_context *) ssl->ctx_checksum, 0 ); - ssl->update_checksum = ssl_update_checksum_sha256; - } - - if( ssl->endpoint == SSL_IS_CLIENT ) - ssl->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); - ssl->update_checksum( ssl, input_buf, len ); -} - -static void ssl_update_checksum_start( ssl_context *ssl, unsigned char *buf, - size_t len ) -{ - ((void) ssl); - ((void) buf); - ((void) len); -} - -static void ssl_update_checksum_md5sha1( ssl_context *ssl, unsigned char *buf, - size_t len ) -{ - md5_update( (md5_context *) ssl->ctx_checksum, buf, len ); - sha1_update( (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - buf, len ); -} - -static void ssl_update_checksum_sha256( ssl_context *ssl, unsigned char *buf, - size_t len ) -{ - sha2_update( (sha2_context *) ssl->ctx_checksum, buf, len ); -} - -static void ssl_update_checksum_sha384( ssl_context *ssl, unsigned char *buf, - size_t len ) -{ - sha4_update( (sha4_context *) ssl->ctx_checksum, buf, len ); -} - -static void ssl_calc_finished_ssl( - ssl_context *ssl, unsigned char *buf, int from ) -{ - char *sender; - md5_context md5; - sha1_context sha1; - - unsigned char padbuf[48]; - unsigned char md5sum[16]; - unsigned char sha1sum[20]; - - SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); - - memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) ); - memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - sizeof( sha1_context ) ); - - /* - * SSLv3: - * hash = - * MD5( master + pad2 + - * MD5( handshake + sender + master + pad1 ) ) - * + SHA1( master + pad2 + - * SHA1( handshake + sender + master + pad1 ) ) - */ - - SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) - md5.state, sizeof( md5.state ) ); - - SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof( sha1.state ) ); - - sender = ( from == SSL_IS_CLIENT ) ? (char *) "CLNT" - : (char *) "SRVR"; - - memset( padbuf, 0x36, 48 ); - - md5_update( &md5, (unsigned char *) sender, 4 ); - md5_update( &md5, ssl->session->master, 48 ); - md5_update( &md5, padbuf, 48 ); - md5_finish( &md5, md5sum ); - - sha1_update( &sha1, (unsigned char *) sender, 4 ); - sha1_update( &sha1, ssl->session->master, 48 ); - sha1_update( &sha1, padbuf, 40 ); - sha1_finish( &sha1, sha1sum ); - - memset( padbuf, 0x5C, 48 ); - - md5_starts( &md5 ); - md5_update( &md5, ssl->session->master, 48 ); - md5_update( &md5, padbuf, 48 ); - md5_update( &md5, md5sum, 16 ); - md5_finish( &md5, buf ); - - sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->session->master, 48 ); - sha1_update( &sha1, padbuf , 40 ); - sha1_update( &sha1, sha1sum, 20 ); - sha1_finish( &sha1, buf + 16 ); - - SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); - - memset( &md5, 0, sizeof( md5_context ) ); - memset( &sha1, 0, sizeof( sha1_context ) ); - - memset( padbuf, 0, sizeof( padbuf ) ); - memset( md5sum, 0, sizeof( md5sum ) ); - memset( sha1sum, 0, sizeof( sha1sum ) ); - - SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} - -static void ssl_calc_finished_tls( - ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - char *sender; - md5_context md5; - sha1_context sha1; - unsigned char padbuf[36]; - - SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); - - memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) ); - memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - sizeof( sha1_context ) ); - - /* - * TLSv1: - * hash = PRF( master, finished_label, - * MD5( handshake ) + SHA1( handshake ) )[0..11] - */ - - SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) - md5.state, sizeof( md5.state ) ); - - SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof( sha1.state ) ); - - sender = ( from == SSL_IS_CLIENT ) - ? (char *) "client finished" - : (char *) "server finished"; - - md5_finish( &md5, padbuf ); - sha1_finish( &sha1, padbuf + 16 ); - - ssl->tls_prf( ssl->session->master, 48, sender, - padbuf, 36, buf, len ); - - SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - memset( &md5, 0, sizeof( md5_context ) ); - memset( &sha1, 0, sizeof( sha1_context ) ); - - memset( padbuf, 0, sizeof( padbuf ) ); - - SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} - -static void ssl_calc_finished_tls_sha256( - ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - char *sender; - sha2_context sha2; - unsigned char padbuf[32]; - - SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); - - memcpy( &sha2 , (sha2_context *) ssl->ctx_checksum, sizeof(sha2_context) ); - - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ - - SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) - sha2.state, sizeof( sha2.state ) ); - - sender = ( from == SSL_IS_CLIENT ) - ? (char *) "client finished" - : (char *) "server finished"; - - sha2_finish( &sha2, padbuf ); - - ssl->tls_prf( ssl->session->master, 48, sender, - padbuf, 32, buf, len ); - - SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - memset( &sha2, 0, sizeof( sha2_context ) ); - - memset( padbuf, 0, sizeof( padbuf ) ); - - SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} - -static void ssl_calc_finished_tls_sha384( - ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - char *sender; - sha4_context sha4; - unsigned char padbuf[48]; - - SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); - - memcpy( &sha4 , (sha4_context *) ssl->ctx_checksum, sizeof(sha4_context) ); - - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ - - SSL_DEBUG_BUF( 4, "finished sha4 state", (unsigned char *) - sha4.state, sizeof( sha4.state ) ); - - sender = ( from == SSL_IS_CLIENT ) - ? (char *) "client finished" - : (char *) "server finished"; - - sha4_finish( &sha4, padbuf ); - - ssl->tls_prf( ssl->session->master, 48, sender, - padbuf, 48, buf, len ); - - SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - memset( &sha4, 0, sizeof( sha4_context ) ); - - memset( padbuf, 0, sizeof( padbuf ) ); - - SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} - -int ssl_write_finished( ssl_context *ssl ) -{ - int ret, hash_len; - - SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); - - ssl->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint ); - - // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) - hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12; - - ssl->out_msglen = 4 + hash_len; - ssl->out_msgtype = SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = SSL_HS_FINISHED; - - /* - * In case of session resuming, invert the client and server - * ChangeCipherSpec messages order. - */ - if( ssl->resume != 0 ) - { - if( ssl->endpoint == SSL_IS_CLIENT ) - ssl->state = SSL_HANDSHAKE_OVER; - else - ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; - } - else - ssl->state++; - - ssl->do_crypt = 1; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - - SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); - - return( 0 ); -} - -int ssl_parse_finished( ssl_context *ssl ) -{ - int ret; - unsigned int hash_len; - unsigned char buf[36]; - - SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); - - ssl->calc_finished( ssl, buf, ssl->endpoint ^ 1 ); - - ssl->do_crypt = 1; - - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) - hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12; - - if( ssl->in_msg[0] != SSL_HS_FINISHED || - ssl->in_hslen != 4 + hash_len ) - { - SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_FINISHED ); - } - - if( memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 ) - { - SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_FINISHED ); - } - - if( ssl->resume != 0 ) - { - if( ssl->endpoint == SSL_IS_CLIENT ) - ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; - - if( ssl->endpoint == SSL_IS_SERVER ) - ssl->state = SSL_HANDSHAKE_OVER; - } - else - ssl->state++; - - SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); - - return( 0 ); -} - -/* - * Initialize an SSL context - */ -int ssl_init( ssl_context *ssl ) -{ - int len = SSL_BUFFER_LEN; - - memset( ssl, 0, sizeof( ssl_context ) ); - - ssl->in_ctr = (unsigned char *) malloc( len ); - ssl->in_hdr = ssl->in_ctr + 8; - ssl->in_msg = ssl->in_ctr + 13; - - if( ssl->in_ctr == NULL ) - { - SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) ); - return( POLARSSL_ERR_SSL_MALLOC_FAILED ); - } - - ssl->out_ctr = (unsigned char *) malloc( len ); - ssl->out_hdr = ssl->out_ctr + 8; - ssl->out_msg = ssl->out_ctr + 13; - - if( ssl->out_ctr == NULL ) - { - SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) ); - free( ssl-> in_ctr ); - return( POLARSSL_ERR_SSL_MALLOC_FAILED ); - } - - memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN ); - memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); - - ssl->hostname = NULL; - ssl->hostname_len = 0; - - ssl->update_checksum = ssl_update_checksum_start; - - return( 0 ); -} - -/* - * Reset an initialized and used SSL context for re-use while retaining - * all application-set variables, function pointers and data. - */ -void ssl_session_reset( ssl_context *ssl ) -{ - ssl->state = SSL_HELLO_REQUEST; - - ssl->in_offt = NULL; - - ssl->in_msgtype = 0; - ssl->in_msglen = 0; - ssl->in_left = 0; - - ssl->in_hslen = 0; - ssl->nb_zero = 0; - - ssl->out_msgtype = 0; - ssl->out_msglen = 0; - ssl->out_left = 0; - - ssl->do_crypt = 0; - ssl->pmslen = 0; - ssl->keylen = 0; - ssl->minlen = 0; - ssl->ivlen = 0; - ssl->maclen = 0; - - memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); - memset( ssl->in_ctr, 0, SSL_BUFFER_LEN ); - memset( ssl->randbytes, 0, 64 ); - memset( ssl->premaster, 0, 256 ); - memset( ssl->iv_enc, 0, 16 ); - memset( ssl->iv_dec, 0, 16 ); - memset( ssl->mac_enc, 0, 32 ); - memset( ssl->mac_dec, 0, 32 ); - memset( ssl->ctx_enc, 0, 128 ); - memset( ssl->ctx_dec, 0, 128 ); - - ssl->update_checksum = ssl_update_checksum_start; -} - -/* - * SSL set accessors - */ -void ssl_set_endpoint( ssl_context *ssl, int endpoint ) -{ - ssl->endpoint = endpoint; -} - -void ssl_set_authmode( ssl_context *ssl, int authmode ) -{ - ssl->authmode = authmode; -} - -void ssl_set_verify( ssl_context *ssl, - int (*f_vrfy)(void *, x509_cert *, int, int), - void *p_vrfy ) -{ - ssl->f_vrfy = f_vrfy; - ssl->p_vrfy = p_vrfy; -} - -void ssl_set_rng( ssl_context *ssl, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - ssl->f_rng = f_rng; - ssl->p_rng = p_rng; -} - -void ssl_set_dbg( ssl_context *ssl, - void (*f_dbg)(void *, int, const char *), - void *p_dbg ) -{ - ssl->f_dbg = f_dbg; - ssl->p_dbg = p_dbg; -} - -void ssl_set_bio( ssl_context *ssl, - int (*f_recv)(void *, unsigned char *, size_t), void *p_recv, - int (*f_send)(void *, const unsigned char *, size_t), void *p_send ) -{ - ssl->f_recv = f_recv; - ssl->f_send = f_send; - ssl->p_recv = p_recv; - ssl->p_send = p_send; -} - -void ssl_set_scb( ssl_context *ssl, - int (*s_get)(ssl_context *), - int (*s_set)(ssl_context *) ) -{ - ssl->s_get = s_get; - ssl->s_set = s_set; -} - -void ssl_set_session( ssl_context *ssl, int resume, int timeout, - ssl_session *session ) -{ - ssl->resume = resume; - ssl->timeout = timeout; - ssl->session = session; -} - -void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites ) -{ - ssl->ciphersuites = ciphersuites; -} - -void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain, - x509_crl *ca_crl, const char *peer_cn ) -{ - ssl->ca_chain = ca_chain; - ssl->ca_crl = ca_crl; - ssl->peer_cn = peer_cn; -} - -void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert, - rsa_context *rsa_key ) -{ - ssl->own_cert = own_cert; - ssl->rsa_key = rsa_key; -} - -#if defined(POLARSSL_PKCS11_C) -void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert, - pkcs11_context *pkcs11_key ) -{ - ssl->own_cert = own_cert; - ssl->pkcs11_key = pkcs11_key; -} -#endif - -int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ) -{ - int ret; - - if( ( ret = mpi_read_string( &ssl->dhm_ctx.P, 16, dhm_P ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "mpi_read_string", ret ); - return( ret ); - } - - if( ( ret = mpi_read_string( &ssl->dhm_ctx.G, 16, dhm_G ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "mpi_read_string", ret ); - return( ret ); - } - - return( 0 ); -} - -int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ) -{ - int ret; - - if( ( ret = mpi_copy(&ssl->dhm_ctx.P, &dhm_ctx->P) ) != 0 ) - { - SSL_DEBUG_RET( 1, "mpi_copy", ret ); - return( ret ); - } - - if( ( ret = mpi_copy(&ssl->dhm_ctx.G, &dhm_ctx->G) ) != 0 ) - { - SSL_DEBUG_RET( 1, "mpi_copy", ret ); - return( ret ); - } - - return( 0 ); -} - -int ssl_set_hostname( ssl_context *ssl, const char *hostname ) -{ - if( hostname == NULL ) - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - - ssl->hostname_len = strlen( hostname ); - ssl->hostname = (unsigned char *) malloc( ssl->hostname_len + 1 ); - - if( ssl->hostname == NULL ) - return( POLARSSL_ERR_SSL_MALLOC_FAILED ); - - memcpy( ssl->hostname, (unsigned char *) hostname, - ssl->hostname_len ); - - ssl->hostname[ssl->hostname_len] = '\0'; - - return( 0 ); -} - -void ssl_set_max_version( ssl_context *ssl, int major, int minor ) -{ - ssl->max_major_ver = major; - ssl->max_minor_ver = minor; -} - -/* - * SSL get accessors - */ -size_t ssl_get_bytes_avail( const ssl_context *ssl ) -{ - return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); -} - -int ssl_get_verify_result( const ssl_context *ssl ) -{ - return( ssl->verify_result ); -} - -const char *ssl_get_ciphersuite_name( const int ciphersuite_id ) -{ - switch( ciphersuite_id ) - { -#if defined(POLARSSL_ARC4_C) - case SSL_RSA_RC4_128_MD5: - return( "SSL-RSA-RC4-128-MD5" ); - - case SSL_RSA_RC4_128_SHA: - return( "SSL-RSA-RC4-128-SHA" ); -#endif - -#if defined(POLARSSL_DES_C) - case SSL_RSA_DES_168_SHA: - return( "SSL-RSA-DES-168-SHA" ); - - case SSL_EDH_RSA_DES_168_SHA: - return( "SSL-EDH-RSA-DES-168-SHA" ); -#endif - -#if defined(POLARSSL_AES_C) - case SSL_RSA_AES_128_SHA: - return( "SSL-RSA-AES-128-SHA" ); - - case SSL_EDH_RSA_AES_128_SHA: - return( "SSL-EDH-RSA-AES-128-SHA" ); - - case SSL_RSA_AES_256_SHA: - return( "SSL-RSA-AES-256-SHA" ); - - case SSL_EDH_RSA_AES_256_SHA: - return( "SSL-EDH-RSA-AES-256-SHA" ); - -#if defined(POLARSSL_SHA2_C) - case SSL_RSA_AES_128_SHA256: - return( "SSL-RSA-AES-128-SHA256" ); - - case SSL_EDH_RSA_AES_128_SHA256: - return( "SSL-EDH-RSA-AES-128-SHA256" ); - - case SSL_RSA_AES_256_SHA256: - return( "SSL-RSA-AES-256-SHA256" ); - - case SSL_EDH_RSA_AES_256_SHA256: - return( "SSL-EDH-RSA-AES-256-SHA256" ); -#endif - -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - case SSL_RSA_AES_128_GCM_SHA256: - return( "SSL-RSA-AES-128-GCM-SHA256" ); - - case SSL_EDH_RSA_AES_128_GCM_SHA256: - return( "SSL-EDH-RSA-AES-128-GCM-SHA256" ); -#endif - -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) - case SSL_RSA_AES_256_GCM_SHA384: - return( "SSL-RSA-AES-256-GCM-SHA384" ); - - case SSL_EDH_RSA_AES_256_GCM_SHA384: - return( "SSL-EDH-RSA-AES-256-GCM-SHA384" ); -#endif -#endif /* POLARSSL_AES_C */ - -#if defined(POLARSSL_CAMELLIA_C) - case SSL_RSA_CAMELLIA_128_SHA: - return( "SSL-RSA-CAMELLIA-128-SHA" ); - - case SSL_EDH_RSA_CAMELLIA_128_SHA: - return( "SSL-EDH-RSA-CAMELLIA-128-SHA" ); - - case SSL_RSA_CAMELLIA_256_SHA: - return( "SSL-RSA-CAMELLIA-256-SHA" ); - - case SSL_EDH_RSA_CAMELLIA_256_SHA: - return( "SSL-EDH-RSA-CAMELLIA-256-SHA" ); - -#if defined(POLARSSL_SHA2_C) - case SSL_RSA_CAMELLIA_128_SHA256: - return( "SSL-RSA-CAMELLIA-128-SHA256" ); - - case SSL_EDH_RSA_CAMELLIA_128_SHA256: - return( "SSL-EDH-RSA-CAMELLIA-128-SHA256" ); - - case SSL_RSA_CAMELLIA_256_SHA256: - return( "SSL-RSA-CAMELLIA-256-SHA256" ); - - case SSL_EDH_RSA_CAMELLIA_256_SHA256: - return( "SSL-EDH-RSA-CAMELLIA-256-SHA256" ); -#endif -#endif - -#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - case SSL_RSA_NULL_MD5: - return( "SSL-RSA-NULL-MD5" ); - case SSL_RSA_NULL_SHA: - return( "SSL-RSA-NULL-SHA" ); - case SSL_RSA_NULL_SHA256: - return( "SSL-RSA-NULL-SHA256" ); -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - -#if defined(POLARSSL_DES_C) - case SSL_RSA_DES_SHA: - return( "SSL-RSA-DES-SHA" ); - case SSL_EDH_RSA_DES_SHA: - return( "SSL-EDH-RSA-DES-SHA" ); -#endif -#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */ - - default: - break; - } - - return( "unknown" ); -} - -int ssl_get_ciphersuite_id( const char *ciphersuite_name ) -{ -#if defined(POLARSSL_ARC4_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-RC4-128-MD5")) - return( SSL_RSA_RC4_128_MD5 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-RC4-128-SHA")) - return( SSL_RSA_RC4_128_SHA ); -#endif - -#if defined(POLARSSL_DES_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-DES-168-SHA")) - return( SSL_RSA_DES_168_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-DES-168-SHA")) - return( SSL_EDH_RSA_DES_168_SHA ); -#endif - -#if defined(POLARSSL_AES_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-SHA")) - return( SSL_RSA_AES_128_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-SHA")) - return( SSL_EDH_RSA_AES_128_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-SHA")) - return( SSL_RSA_AES_256_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-SHA")) - return( SSL_EDH_RSA_AES_256_SHA ); - -#if defined(POLARSSL_SHA2_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-SHA256")) - return( SSL_RSA_AES_128_SHA256 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-SHA256")) - return( SSL_EDH_RSA_AES_128_SHA256 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-SHA256")) - return( SSL_RSA_AES_256_SHA256 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-SHA256")) - return( SSL_EDH_RSA_AES_256_SHA256 ); -#endif - -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-GCM-SHA256")) - return( SSL_RSA_AES_128_GCM_SHA256 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-GCM-SHA256")) - return( SSL_EDH_RSA_AES_128_GCM_SHA256 ); -#endif - -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-GCM-SHA384")) - return( SSL_RSA_AES_256_GCM_SHA384 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-GCM-SHA384")) - return( SSL_EDH_RSA_AES_256_GCM_SHA384 ); -#endif -#endif - -#if defined(POLARSSL_CAMELLIA_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-128-SHA")) - return( SSL_RSA_CAMELLIA_128_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-128-SHA")) - return( SSL_EDH_RSA_CAMELLIA_128_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-256-SHA")) - return( SSL_RSA_CAMELLIA_256_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-256-SHA")) - return( SSL_EDH_RSA_CAMELLIA_256_SHA ); - -#if defined(POLARSSL_SHA2_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-128-SHA256")) - return( SSL_RSA_CAMELLIA_128_SHA256 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-128-SHA256")) - return( SSL_EDH_RSA_CAMELLIA_128_SHA256 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-256-SHA256")) - return( SSL_RSA_CAMELLIA_256_SHA256 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-256-SHA256")) - return( SSL_EDH_RSA_CAMELLIA_256_SHA256 ); -#endif -#endif - -#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-MD5")) - return( SSL_RSA_NULL_MD5 ); - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-SHA")) - return( SSL_RSA_NULL_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-SHA256")) - return( SSL_RSA_NULL_SHA256 ); -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - -#if defined(POLARSSL_DES_C) - if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-DES-SHA")) - return( SSL_RSA_DES_SHA ); - if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-DES-SHA")) - return( SSL_EDH_RSA_DES_SHA ); -#endif -#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */ - - return( 0 ); -} - -const char *ssl_get_ciphersuite( const ssl_context *ssl ) -{ - return ssl_get_ciphersuite_name( ssl->session->ciphersuite ); -} - -const char *ssl_get_version( const ssl_context *ssl ) -{ - switch( ssl->minor_ver ) - { - case SSL_MINOR_VERSION_0: - return( "SSLv3.0" ); - - case SSL_MINOR_VERSION_1: - return( "TLSv1.0" ); - - case SSL_MINOR_VERSION_2: - return( "TLSv1.1" ); - - case SSL_MINOR_VERSION_3: - return( "TLSv1.2" ); - - default: - break; - } - return( "unknown" ); -} - -int ssl_default_ciphersuites[] = -{ -#if defined(POLARSSL_DHM_C) -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) - SSL_EDH_RSA_AES_256_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) - SSL_EDH_RSA_AES_256_GCM_SHA384, -#endif - SSL_EDH_RSA_AES_256_SHA, -#if defined(POLARSSL_SHA2_C) - SSL_EDH_RSA_AES_128_SHA256, -#endif -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - SSL_EDH_RSA_AES_128_GCM_SHA256, -#endif - SSL_EDH_RSA_AES_128_SHA, -#endif -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) - SSL_EDH_RSA_CAMELLIA_256_SHA256, -#endif /* POLARSSL_SHA2_C */ - SSL_EDH_RSA_CAMELLIA_256_SHA, -#if defined(POLARSSL_SHA2_C) - SSL_EDH_RSA_CAMELLIA_128_SHA256, -#endif /* POLARSSL_SHA2_C */ - SSL_EDH_RSA_CAMELLIA_128_SHA, -#endif -#if defined(POLARSSL_DES_C) - SSL_EDH_RSA_DES_168_SHA, -#endif -#endif - -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) - SSL_RSA_AES_256_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) - SSL_RSA_AES_256_GCM_SHA384, -#endif /* POLARSSL_SHA2_C */ - SSL_RSA_AES_256_SHA, -#endif -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) - SSL_RSA_CAMELLIA_256_SHA256, -#endif /* POLARSSL_SHA2_C */ - SSL_RSA_CAMELLIA_256_SHA, -#endif -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) - SSL_RSA_AES_128_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - SSL_RSA_AES_128_GCM_SHA256, -#endif /* POLARSSL_SHA2_C */ - SSL_RSA_AES_128_SHA, -#endif -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) - SSL_RSA_CAMELLIA_128_SHA256, -#endif /* POLARSSL_SHA2_C */ - SSL_RSA_CAMELLIA_128_SHA, -#endif -#if defined(POLARSSL_DES_C) - SSL_RSA_DES_168_SHA, -#endif -#if defined(POLARSSL_ARC4_C) - SSL_RSA_RC4_128_SHA, - SSL_RSA_RC4_128_MD5, -#endif - 0 -}; - -/* - * Perform the SSL handshake - */ -int ssl_handshake( ssl_context *ssl ) -{ - int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; - - SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); - -#if defined(POLARSSL_SSL_CLI_C) - if( ssl->endpoint == SSL_IS_CLIENT ) - ret = ssl_handshake_client( ssl ); -#endif - -#if defined(POLARSSL_SSL_SRV_C) - if( ssl->endpoint == SSL_IS_SERVER ) - ret = ssl_handshake_server( ssl ); -#endif - - SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); - - return( ret ); -} - -/* - * Receive application data decrypted from the SSL layer - */ -int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) -{ - int ret; - size_t n; - - SSL_DEBUG_MSG( 2, ( "=> read" ) ); - - if( ssl->state != SSL_HANDSHAKE_OVER ) - { - if( ( ret = ssl_handshake( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_handshake", ret ); - return( ret ); - } - } - - if( ssl->in_offt == NULL ) - { - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - if( ret == POLARSSL_ERR_SSL_CONN_EOF ) - return( 0 ); - - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msglen == 0 && - ssl->in_msgtype == SSL_MSG_APPLICATION_DATA ) - { - /* - * OpenSSL sends empty messages to randomize the IV - */ - if( ( ret = ssl_read_record( ssl ) ) != 0 ) - { - if( ret == POLARSSL_ERR_SSL_CONN_EOF ) - return( 0 ); - - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } - } - - if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA ) - { - SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - ssl->in_offt = ssl->in_msg; - } - - n = ( len < ssl->in_msglen ) - ? len : ssl->in_msglen; - - memcpy( buf, ssl->in_offt, n ); - ssl->in_msglen -= n; - - if( ssl->in_msglen == 0 ) - /* all bytes consumed */ - ssl->in_offt = NULL; - else - /* more data available */ - ssl->in_offt += n; - - SSL_DEBUG_MSG( 2, ( "<= read" ) ); - - return( (int) n ); -} - -/* - * Send application data to be encrypted by the SSL layer - */ -int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) -{ - int ret; - size_t n; - - SSL_DEBUG_MSG( 2, ( "=> write" ) ); - - if( ssl->state != SSL_HANDSHAKE_OVER ) - { - if( ( ret = ssl_handshake( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_handshake", ret ); - return( ret ); - } - } - - n = ( len < SSL_MAX_CONTENT_LEN ) - ? len : SSL_MAX_CONTENT_LEN; - - if( ssl->out_left != 0 ) - { - if( ( ret = ssl_flush_output( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_flush_output", ret ); - return( ret ); - } - } - else - { - ssl->out_msglen = n; - ssl->out_msgtype = SSL_MSG_APPLICATION_DATA; - memcpy( ssl->out_msg, buf, n ); - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - } - - SSL_DEBUG_MSG( 2, ( "<= write" ) ); - - return( (int) n ); -} - -/* - * Notify the peer that the connection is being closed - */ -int ssl_close_notify( ssl_context *ssl ) -{ - int ret; - - SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); - - if( ( ret = ssl_flush_output( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_flush_output", ret ); - return( ret ); - } - - if( ssl->state == SSL_HANDSHAKE_OVER ) - { - ssl->out_msgtype = SSL_MSG_ALERT; - ssl->out_msglen = 2; - ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING; - ssl->out_msg[1] = SSL_ALERT_MSG_CLOSE_NOTIFY; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - } - - SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); - - return( ret ); -} - -/* - * Free an SSL context - */ -void ssl_free( ssl_context *ssl ) -{ - SSL_DEBUG_MSG( 2, ( "=> free" ) ); - - if( ssl->peer_cert != NULL ) - { - x509_free( ssl->peer_cert ); - memset( ssl->peer_cert, 0, sizeof( x509_cert ) ); - free( ssl->peer_cert ); - } - - if( ssl->out_ctr != NULL ) - { - memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); - free( ssl->out_ctr ); - } - - if( ssl->in_ctr != NULL ) - { - memset( ssl->in_ctr, 0, SSL_BUFFER_LEN ); - free( ssl->in_ctr ); - } - -#if defined(POLARSSL_DHM_C) - dhm_free( &ssl->dhm_ctx ); -#endif - - if ( ssl->hostname != NULL) - { - memset( ssl->hostname, 0, ssl->hostname_len ); - free( ssl->hostname ); - ssl->hostname_len = 0; - } - - SSL_DEBUG_MSG( 2, ( "<= free" ) ); - - /* Actually free after last debug message */ - memset( ssl, 0, sizeof( ssl_context ) ); -} - -#endif diff --git a/polarssl/src/library/timing.c b/polarssl/src/library/timing.c deleted file mode 100644 index 523dbe1..0000000 --- a/polarssl/src/library/timing.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Portable interface to the CPU cycle counter - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_TIMING_C) - -#include "polarssl/timing.h" - -#if defined(_WIN32) - -#include -#include - -struct _hr_time -{ - LARGE_INTEGER start; -}; - -#else - -#include -#include -#include -#include -#include - -struct _hr_time -{ - struct timeval start; -}; - -#endif - -#if defined(POLARSSL_HAVE_ASM) && \ - (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) - -unsigned long hardclock( void ) -{ - unsigned long tsc; - __asm rdtsc - __asm mov [tsc], eax - return( tsc ); -} - -#else -#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) - -unsigned long hardclock( void ) -{ - unsigned long lo, hi; - asm( "rdtsc" : "=a" (lo), "=d" (hi) ); - return( lo ); -} - -#else -#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \ - (defined(__amd64__) || defined(__x86_64__)) - -unsigned long hardclock( void ) -{ - unsigned long lo, hi; - asm( "rdtsc" : "=a" (lo), "=d" (hi) ); - return( lo | (hi << 32) ); -} - -#else -#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \ - (defined(__powerpc__) || defined(__ppc__)) - -unsigned long hardclock( void ) -{ - unsigned long tbl, tbu0, tbu1; - - do - { - asm( "mftbu %0" : "=r" (tbu0) ); - asm( "mftb %0" : "=r" (tbl ) ); - asm( "mftbu %0" : "=r" (tbu1) ); - } - while( tbu0 != tbu1 ); - - return( tbl ); -} - -#else -#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__sparc__) - -unsigned long hardclock( void ) -{ - unsigned long tick; - asm( ".byte 0x83, 0x41, 0x00, 0x00" ); - asm( "mov %%g1, %0" : "=r" (tick) ); - return( tick ); -} - -#else -#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__alpha__) - -unsigned long hardclock( void ) -{ - unsigned long cc; - asm( "rpcc %0" : "=r" (cc) ); - return( cc & 0xFFFFFFFF ); -} - -#else -#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__ia64__) - -unsigned long hardclock( void ) -{ - unsigned long itc; - asm( "mov %0 = ar.itc" : "=r" (itc) ); - return( itc ); -} - -#else -#if defined(_MSC_VER) - -unsigned long hardclock( void ) -{ - LARGE_INTEGER offset; - - QueryPerformanceCounter( &offset ); - - return (unsigned long)( offset.QuadPart ); -} - -#else - -static int hardclock_init = 0; -static struct timeval tv_init; - -unsigned long hardclock( void ) -{ - struct timeval tv_cur; - - if( hardclock_init == 0 ) - { - gettimeofday( &tv_init, NULL ); - hardclock_init = 1; - } - - gettimeofday( &tv_cur, NULL ); - return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 - + ( tv_cur.tv_usec - tv_init.tv_usec ) ); -} - -#endif /* generic */ -#endif /* WIN32 */ -#endif /* IA-64 */ -#endif /* Alpha */ -#endif /* SPARC8 */ -#endif /* PowerPC */ -#endif /* AMD64 */ -#endif /* i586+ */ - -volatile int alarmed = 0; - -#if defined(_WIN32) - -unsigned long get_timer( struct hr_time *val, int reset ) -{ - unsigned long delta; - LARGE_INTEGER offset, hfreq; - struct _hr_time *t = (struct _hr_time *) val; - - QueryPerformanceCounter( &offset ); - QueryPerformanceFrequency( &hfreq ); - - delta = (unsigned long)( ( 1000 * - ( offset.QuadPart - t->start.QuadPart ) ) / - hfreq.QuadPart ); - - if( reset ) - QueryPerformanceCounter( &t->start ); - - return( delta ); -} - -DWORD WINAPI TimerProc( LPVOID uElapse ) -{ - Sleep( (DWORD) uElapse ); - alarmed = 1; - return( TRUE ); -} - -void set_alarm( int seconds ) -{ - DWORD ThreadId; - - alarmed = 0; - CloseHandle( CreateThread( NULL, 0, TimerProc, - (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) ); -} - -void m_sleep( int milliseconds ) -{ - Sleep( milliseconds ); -} - -#else - -unsigned long get_timer( struct hr_time *val, int reset ) -{ - unsigned long delta; - struct timeval offset; - struct _hr_time *t = (struct _hr_time *) val; - - gettimeofday( &offset, NULL ); - - delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 - + ( offset.tv_usec - t->start.tv_usec ) / 1000; - - if( reset ) - { - t->start.tv_sec = offset.tv_sec; - t->start.tv_usec = offset.tv_usec; - } - - return( delta ); -} - -static void sighandler( int signum ) -{ - alarmed = 1; - signal( signum, sighandler ); -} - -void set_alarm( int seconds ) -{ - alarmed = 0; - signal( SIGALRM, sighandler ); - alarm( seconds ); -} - -void m_sleep( int milliseconds ) -{ - struct timeval tv; - - tv.tv_sec = milliseconds / 1000; - tv.tv_usec = milliseconds * 1000; - - select( 0, NULL, NULL, NULL, &tv ); -} - -#endif - -#endif diff --git a/polarssl/src/library/version.c b/polarssl/src/library/version.c deleted file mode 100644 index c1080b7..0000000 --- a/polarssl/src/library/version.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Version information - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_VERSION_C) - -#include "polarssl/version.h" -#include - -const char version[] = POLARSSL_VERSION_STRING; - -unsigned int version_get_number() -{ - return POLARSSL_VERSION_NUMBER; -} - -void version_get_string( char *string ) -{ - memcpy( string, POLARSSL_VERSION_STRING, sizeof( POLARSSL_VERSION_STRING ) ); -} - -void version_get_string_full( char *string ) -{ - memcpy( string, POLARSSL_VERSION_STRING_FULL, sizeof( POLARSSL_VERSION_STRING_FULL ) ); -} - -#endif /* POLARSSL_VERSION_C */ diff --git a/polarssl/src/library/x509parse.c b/polarssl/src/library/x509parse.c deleted file mode 100644 index 9d01a65..0000000 --- a/polarssl/src/library/x509parse.c +++ /dev/null @@ -1,3425 +0,0 @@ -/* - * X.509 certificate and private key decoding - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc3279.txt - * http://www.ietf.org/rfc/rfc3280.txt - * - * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_X509_PARSE_C) - -#include "polarssl/x509.h" -#include "polarssl/asn1.h" -#include "polarssl/pem.h" -#include "polarssl/des.h" -#include "polarssl/md2.h" -#include "polarssl/md4.h" -#include "polarssl/md5.h" -#include "polarssl/sha1.h" -#include "polarssl/sha2.h" -#include "polarssl/sha4.h" -#include "polarssl/dhm.h" - -#include -#include -#if defined(_WIN32) -#include -#else -#include -#endif - -#if defined(POLARSSL_FS_IO) -#include -#endif - -/* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ -static int x509_get_version( unsigned char **p, - const unsigned char *end, - int *ver ) -{ - int ret; - size_t len; - - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 ) - { - if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - { - *ver = 0; - return( 0 ); - } - - return( ret ); - } - - end = *p + len; - - if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret ); - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * Version ::= INTEGER { v1(0), v2(1) } - */ -static int x509_crl_get_version( unsigned char **p, - const unsigned char *end, - int *ver ) -{ - int ret; - - if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) - { - if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - { - *ver = 0; - return( 0 ); - } - - return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret ); - } - - return( 0 ); -} - -/* - * CertificateSerialNumber ::= INTEGER - */ -static int x509_get_serial( unsigned char **p, - const unsigned char *end, - x509_buf *serial ) -{ - int ret; - - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) && - **p != ASN1_INTEGER ) - return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL + - POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); - - serial->tag = *(*p)++; - - if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL + ret ); - - serial->p = *p; - *p += serial->len; - - return( 0 ); -} - -/* - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - */ -static int x509_get_alg( unsigned char **p, - const unsigned char *end, - x509_buf *alg ) -{ - int ret; - size_t len; - - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - - end = *p + len; - alg->tag = **p; - - if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - - alg->p = *p; - *p += alg->len; - - if( *p == end ) - return( 0 ); - - /* - * assume the algorithm parameters must be NULL - */ - if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - */ -static int x509_get_attr_type_value( unsigned char **p, - const unsigned char *end, - x509_name *cur ) -{ - int ret; - size_t len; - x509_buf *oid; - x509_buf *val; - - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret ); - - oid = &cur->oid; - oid->tag = **p; - - if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret ); - - oid->p = *p; - *p += oid->len; - - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_NAME + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING && - **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING && - **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING ) - return( POLARSSL_ERR_X509_CERT_INVALID_NAME + - POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); - - val = &cur->val; - val->tag = *(*p)++; - - if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret ); - - val->p = *p; - *p += val->len; - - cur->next = NULL; - - return( 0 ); -} - -/* - * RelativeDistinguishedName ::= - * SET OF AttributeTypeAndValue - * - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - */ -static int x509_get_name( unsigned char **p, - const unsigned char *end, - x509_name *cur ) -{ - int ret; - size_t len; - const unsigned char *end2; - x509_name *use; - - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret ); - - end2 = end; - end = *p + len; - use = cur; - - do - { - if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 ) - return( ret ); - - if( *p != end ) - { - use->next = (x509_name *) malloc( - sizeof( x509_name ) ); - - if( use->next == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - memset( use->next, 0, sizeof( x509_name ) ); - - use = use->next; - } - } - while( *p != end ); - - /* - * recurse until end of SEQUENCE is reached - */ - if( *p == end2 ) - return( 0 ); - - cur->next = (x509_name *) malloc( - sizeof( x509_name ) ); - - if( cur->next == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - return( x509_get_name( p, end2, cur->next ) ); -} - -/* - * Time ::= CHOICE { - * utcTime UTCTime, - * generalTime GeneralizedTime } - */ -static int x509_get_time( unsigned char **p, - const unsigned char *end, - x509_time *time ) -{ - int ret; - size_t len; - char date[64]; - unsigned char tag; - - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_DATE + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - tag = **p; - - if ( tag == ASN1_UTC_TIME ) - { - (*p)++; - ret = asn1_get_len( p, end, &len ); - - if( ret != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret ); - - memset( date, 0, sizeof( date ) ); - memcpy( date, *p, ( len < sizeof( date ) - 1 ) ? - len : sizeof( date ) - 1 ); - - if( sscanf( date, "%2d%2d%2d%2d%2d%2d", - &time->year, &time->mon, &time->day, - &time->hour, &time->min, &time->sec ) < 5 ) - return( POLARSSL_ERR_X509_CERT_INVALID_DATE ); - - time->year += 100 * ( time->year < 50 ); - time->year += 1900; - - *p += len; - - return( 0 ); - } - else if ( tag == ASN1_GENERALIZED_TIME ) - { - (*p)++; - ret = asn1_get_len( p, end, &len ); - - if( ret != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret ); - - memset( date, 0, sizeof( date ) ); - memcpy( date, *p, ( len < sizeof( date ) - 1 ) ? - len : sizeof( date ) - 1 ); - - if( sscanf( date, "%4d%2d%2d%2d%2d%2d", - &time->year, &time->mon, &time->day, - &time->hour, &time->min, &time->sec ) < 5 ) - return( POLARSSL_ERR_X509_CERT_INVALID_DATE ); - - *p += len; - - return( 0 ); - } - else - return( POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); -} - - -/* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - */ -static int x509_get_dates( unsigned char **p, - const unsigned char *end, - x509_time *from, - x509_time *to ) -{ - int ret; - size_t len; - - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret ); - - end = *p + len; - - if( ( ret = x509_get_time( p, end, from ) ) != 0 ) - return( ret ); - - if( ( ret = x509_get_time( p, end, to ) ) != 0 ) - return( ret ); - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_DATE + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ -static int x509_get_pubkey( unsigned char **p, - const unsigned char *end, - x509_buf *pk_alg_oid, - mpi *N, mpi *E ) -{ - int ret, can_handle; - size_t len; - unsigned char *end2; - - if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 ) - return( ret ); - - /* - * only RSA public keys handled at this time - */ - can_handle = 0; - - if( pk_alg_oid->len == 9 && - memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) == 0 ) - can_handle = 1; - - if( pk_alg_oid->len == 9 && - memcmp( pk_alg_oid->p, OID_PKCS1, 8 ) == 0 ) - { - if( pk_alg_oid->p[8] >= 2 && pk_alg_oid->p[8] <= 5 ) - can_handle = 1; - - if ( pk_alg_oid->p[8] >= 11 && pk_alg_oid->p[8] <= 14 ) - can_handle = 1; - } - - if( pk_alg_oid->len == 5 && - memcmp( pk_alg_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 ) - can_handle = 1; - - if( can_handle == 0 ) - return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); - - if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); - - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - end2 = *p + len; - - if( *(*p)++ != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); - - /* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ - if( ( ret = asn1_get_tag( p, end2, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); - - if( *p + len != end2 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 || - ( ret = asn1_get_mpi( p, end2, E ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -static int x509_get_sig( unsigned char **p, - const unsigned char *end, - x509_buf *sig ) -{ - int ret; - size_t len; - - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - sig->tag = **p; - - if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + ret ); - - - if( --len < 1 || *(*p)++ != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE ); - - sig->len = len; - sig->p = *p; - - *p += len; - - return( 0 ); -} - -/* - * X.509 v2/v3 unique identifier (not parsed) - */ -static int x509_get_uid( unsigned char **p, - const unsigned char *end, - x509_buf *uid, int n ) -{ - int ret; - - if( *p == end ) - return( 0 ); - - uid->tag = **p; - - if( ( ret = asn1_get_tag( p, end, &uid->len, - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 ) - { - if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - uid->p = *p; - *p += uid->len; - - return( 0 ); -} - -/* - * X.509 Extensions (No parsing of extensions, pointer should - * be either manually updated or extensions should be parsed! - */ -static int x509_get_ext( unsigned char **p, - const unsigned char *end, - x509_buf *ext, int tag ) -{ - int ret; - size_t len; - - if( *p == end ) - return( 0 ); - - ext->tag = **p; - - if( ( ret = asn1_get_tag( p, end, &ext->len, - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 ) - return( ret ); - - ext->p = *p; - end = *p + ext->len; - - /* - * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension - * - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - if( end != *p + len ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 CRL v2 extensions (no extensions parsed yet.) - */ -static int x509_get_crl_ext( unsigned char **p, - const unsigned char *end, - x509_buf *ext ) -{ - int ret; - size_t len = 0; - - /* Get explicit tag */ - if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 ) - { - if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - while( *p < end ) - { - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - *p += len; - } - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 CRL v2 entry extensions (no extensions parsed yet.) - */ -static int x509_get_crl_entry_ext( unsigned char **p, - const unsigned char *end, - x509_buf *ext ) -{ - int ret; - size_t len = 0; - - /* OPTIONAL */ - if (end <= *p) - return( 0 ); - - ext->tag = **p; - ext->p = *p; - - /* - * Get CRL-entry extension sequence header - * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 - */ - if( ( ret = asn1_get_tag( p, end, &ext->len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - { - ext->p = NULL; - return( 0 ); - } - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - } - - end = *p + ext->len; - - if( end != *p + ext->len ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - *p += len; - } - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -static int x509_get_basic_constraints( unsigned char **p, - const unsigned char *end, - int *ca_istrue, - int *max_pathlen ) -{ - int ret; - size_t len; - - /* - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - */ - *ca_istrue = 0; /* DEFAULT FALSE */ - *max_pathlen = 0; /* endless */ - - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - if( *p == end ) - return 0; - - if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 ) - { - if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - ret = asn1_get_int( p, end, ca_istrue ); - - if( ret != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - if( *ca_istrue != 0 ) - *ca_istrue = 1; - } - - if( *p == end ) - return 0; - - if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - (*max_pathlen)++; - - return 0; -} - -static int x509_get_ns_cert_type( unsigned char **p, - const unsigned char *end, - unsigned char *ns_cert_type) -{ - int ret; - x509_bitstring bs = { 0, 0, NULL }; - - if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - if( bs.len != 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_INVALID_LENGTH ); - - /* Get actual bitstring */ - *ns_cert_type = *bs.p; - return 0; -} - -static int x509_get_key_usage( unsigned char **p, - const unsigned char *end, - unsigned char *key_usage) -{ - int ret; - x509_bitstring bs = { 0, 0, NULL }; - - if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - if( bs.len > 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_INVALID_LENGTH ); - - /* Get actual bitstring */ - *key_usage = *bs.p; - return 0; -} - -/* - * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId - * - * KeyPurposeId ::= OBJECT IDENTIFIER - */ -static int x509_get_ext_key_usage( unsigned char **p, - const unsigned char *end, - x509_sequence *ext_key_usage) -{ - int ret; - - if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - /* Sequence length must be >= 1 */ - if( ext_key_usage->buf.p == NULL ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_INVALID_LENGTH ); - - return 0; -} - -/* - * SubjectAltName ::= GeneralNames - * - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName, - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER } - * - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString OPTIONAL, - * partyName [1] DirectoryString } - * - * NOTE: PolarSSL only parses and uses dNSName at this point. - */ -static int x509_get_subject_alt_name( unsigned char **p, - const unsigned char *end, - x509_sequence *subject_alt_name ) -{ - int ret; - size_t len, tag_len; - asn1_buf *buf; - unsigned char tag; - asn1_sequence *cur = subject_alt_name; - - /* Get main sequence tag */ - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - if( *p + len != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - tag = **p; - (*p)++; - if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); - - if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) ) - { - *p += tag_len; - continue; - } - - buf = &(cur->buf); - buf->tag = tag; - buf->p = *p; - buf->len = tag_len; - *p += buf->len; - - /* Allocate and assign next pointer */ - if (*p < end) - { - cur->next = (asn1_sequence *) malloc( - sizeof( asn1_sequence ) ); - - if( cur->next == NULL ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_MALLOC_FAILED ); - - cur = cur->next; - } - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 v3 extensions - * - * TODO: Perform all of the basic constraints tests required by the RFC - * TODO: Set values for undetected extensions to a sane default? - * - */ -static int x509_get_crt_ext( unsigned char **p, - const unsigned char *end, - x509_cert *crt ) -{ - int ret; - size_t len; - unsigned char *end_ext_data, *end_ext_octet; - - if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) - { - if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - while( *p < end ) - { - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - x509_buf extn_oid = {0, 0, NULL}; - int is_critical = 0; /* DEFAULT FALSE */ - - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - end_ext_data = *p + len; - - /* Get extension ID */ - extn_oid.tag = **p; - - if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - extn_oid.p = *p; - *p += extn_oid.len; - - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - - /* Get optional critical */ - if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && - ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - /* Data should be octet string type */ - if( ( ret = asn1_get_tag( p, end_ext_data, &len, - ASN1_OCTET_STRING ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret ); - - end_ext_octet = *p + len; - - if( end_ext_octet != end_ext_data ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - /* - * Detect supported extensions - */ - if( ( OID_SIZE( OID_BASIC_CONSTRAINTS ) == extn_oid.len ) && - memcmp( extn_oid.p, OID_BASIC_CONSTRAINTS, extn_oid.len ) == 0 ) - { - /* Parse basic constraints */ - if( ( ret = x509_get_basic_constraints( p, end_ext_octet, - &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) - return ( ret ); - crt->ext_types |= EXT_BASIC_CONSTRAINTS; - } - else if( ( OID_SIZE( OID_NS_CERT_TYPE ) == extn_oid.len ) && - memcmp( extn_oid.p, OID_NS_CERT_TYPE, extn_oid.len ) == 0 ) - { - /* Parse netscape certificate type */ - if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, - &crt->ns_cert_type ) ) != 0 ) - return ( ret ); - crt->ext_types |= EXT_NS_CERT_TYPE; - } - else if( ( OID_SIZE( OID_KEY_USAGE ) == extn_oid.len ) && - memcmp( extn_oid.p, OID_KEY_USAGE, extn_oid.len ) == 0 ) - { - /* Parse key usage */ - if( ( ret = x509_get_key_usage( p, end_ext_octet, - &crt->key_usage ) ) != 0 ) - return ( ret ); - crt->ext_types |= EXT_KEY_USAGE; - } - else if( ( OID_SIZE( OID_EXTENDED_KEY_USAGE ) == extn_oid.len ) && - memcmp( extn_oid.p, OID_EXTENDED_KEY_USAGE, extn_oid.len ) == 0 ) - { - /* Parse extended key usage */ - if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, - &crt->ext_key_usage ) ) != 0 ) - return ( ret ); - crt->ext_types |= EXT_EXTENDED_KEY_USAGE; - } - else if( ( OID_SIZE( OID_SUBJECT_ALT_NAME ) == extn_oid.len ) && - memcmp( extn_oid.p, OID_SUBJECT_ALT_NAME, extn_oid.len ) == 0 ) - { - /* Parse extended key usage */ - if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, - &crt->subject_alt_names ) ) != 0 ) - return ( ret ); - crt->ext_types |= EXT_SUBJECT_ALT_NAME; - } - else - { - /* No parser found, skip extension */ - *p = end_ext_octet; - -#if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - if( is_critical ) - { - /* Data is marked as critical: fail */ - return ( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); - } -#endif - } - } - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 CRL Entries - */ -static int x509_get_entries( unsigned char **p, - const unsigned char *end, - x509_crl_entry *entry ) -{ - int ret; - size_t entry_len; - x509_crl_entry *cur_entry = entry; - - if( *p == end ) - return( 0 ); - - if( ( ret = asn1_get_tag( p, end, &entry_len, - ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 ) - { - if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - end = *p + entry_len; - - while( *p < end ) - { - size_t len2; - const unsigned char *end2; - - if( ( ret = asn1_get_tag( p, end, &len2, - ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 ) - { - return( ret ); - } - - cur_entry->raw.tag = **p; - cur_entry->raw.p = *p; - cur_entry->raw.len = len2; - end2 = *p + len2; - - if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) - return( ret ); - - if( ( ret = x509_get_time( p, end2, &cur_entry->revocation_date ) ) != 0 ) - return( ret ); - - if( ( ret = x509_get_crl_entry_ext( p, end2, &cur_entry->entry_ext ) ) != 0 ) - return( ret ); - - if ( *p < end ) - { - cur_entry->next = malloc( sizeof( x509_crl_entry ) ); - - if( cur_entry->next == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - cur_entry = cur_entry->next; - memset( cur_entry, 0, sizeof( x509_crl_entry ) ); - } - } - - return( 0 ); -} - -static int x509_get_sig_alg( const x509_buf *sig_oid, int *sig_alg ) -{ - if( sig_oid->len == 9 && - memcmp( sig_oid->p, OID_PKCS1, 8 ) == 0 ) - { - if( sig_oid->p[8] >= 2 && sig_oid->p[8] <= 5 ) - { - *sig_alg = sig_oid->p[8]; - return( 0 ); - } - - if ( sig_oid->p[8] >= 11 && sig_oid->p[8] <= 14 ) - { - *sig_alg = sig_oid->p[8]; - return( 0 ); - } - - return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG ); - } - if( sig_oid->len == 5 && - memcmp( sig_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 ) - { - *sig_alg = SIG_RSA_SHA1; - return( 0 ); - } - - return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG ); -} - -/* - * Parse and fill a single X.509 certificate in DER format - */ -int x509parse_crt_der( x509_cert *crt, const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - - /* - * Check for valid input - */ - if( crt == NULL || buf == NULL ) - return( POLARSSL_ERR_X509_INVALID_INPUT ); - - p = (unsigned char *) malloc( len = buflen ); - - if( p == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - buflen = 0; - - crt->raw.p = p; - crt->raw.len = len; - end = p + len; - - /* - * Certificate ::= SEQUENCE { - * tbsCertificate TBSCertificate, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING } - */ - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT ); - } - - if( len != (size_t) ( end - p ) ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - } - - /* - * TBSCertificate ::= SEQUENCE { - */ - crt->tbs.p = p; - - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); - } - - end = p + len; - crt->tbs.len = end - crt->tbs.p; - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - * - * CertificateSerialNumber ::= INTEGER - * - * signature AlgorithmIdentifier - */ - if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || - ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 || - ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - crt->version++; - - if( crt->version > 3 ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION ); - } - - if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_alg ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - /* - * issuer Name - */ - crt->issuer_raw.p = p; - - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); - } - - if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - crt->issuer_raw.len = p - crt->issuer_raw.p; - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - * - */ - if( ( ret = x509_get_dates( &p, end, &crt->valid_from, - &crt->valid_to ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - /* - * subject Name - */ - crt->subject_raw.p = p; - - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); - } - - if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - crt->subject_raw.len = p - crt->subject_raw.p; - - /* - * SubjectPublicKeyInfo ::= SEQUENCE - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); - } - - if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid, - &crt->rsa.N, &crt->rsa.E ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - crt->rsa.len = mpi_size( &crt->rsa.N ); - - /* - * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * extensions [3] EXPLICIT Extensions OPTIONAL - * -- If present, version shall be v3 - */ - if( crt->version == 2 || crt->version == 3 ) - { - ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); - if( ret != 0 ) - { - x509_free( crt ); - return( ret ); - } - } - - if( crt->version == 2 || crt->version == 3 ) - { - ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); - if( ret != 0 ) - { - x509_free( crt ); - return( ret ); - } - } - - if( crt->version == 3 ) - { - ret = x509_get_crt_ext( &p, end, crt); - if( ret != 0 ) - { - x509_free( crt ); - return( ret ); - } - } - - if( p != end ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - } - - end = crt->raw.p + crt->raw.len; - - /* - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - */ - if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH ); - } - - if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 ) - { - x509_free( crt ); - return( ret ); - } - - if( p != end ) - { - x509_free( crt ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - } - - return( 0 ); -} - -/* - * Parse one or more PEM certificates from a buffer and add them to the chained list - */ -int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ) -{ - int ret, success = 0, first_error = 0, total_failed = 0; - x509_cert *crt, *prev = NULL; - int buf_format = X509_FORMAT_DER; - - crt = chain; - - /* - * Check for valid input - */ - if( crt == NULL || buf == NULL ) - return( POLARSSL_ERR_X509_INVALID_INPUT ); - - while( crt->version != 0 && crt->next != NULL ) - { - prev = crt; - crt = crt->next; - } - - /* - * Add new certificate on the end of the chain if needed. - */ - if ( crt->version != 0 && crt->next == NULL) - { - crt->next = (x509_cert *) malloc( sizeof( x509_cert ) ); - - if( crt->next == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - prev = crt; - crt = crt->next; - memset( crt, 0, sizeof( x509_cert ) ); - } - - /* - * Determine buffer content. Buffer contains either one DER certificate or - * one or more PEM certificates. - */ -#if defined(POLARSSL_PEM_C) - if( strstr( (char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) - buf_format = X509_FORMAT_PEM; -#endif - - if( buf_format == X509_FORMAT_DER ) - return x509parse_crt_der( crt, buf, buflen ); - -#if defined(POLARSSL_PEM_C) - if( buf_format == X509_FORMAT_PEM ) - { - pem_context pem; - - while( buflen > 0 ) - { - size_t use_len; - pem_init( &pem ); - - ret = pem_read_buffer( &pem, - "-----BEGIN CERTIFICATE-----", - "-----END CERTIFICATE-----", - buf, NULL, 0, &use_len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - buflen -= use_len; - buf += use_len; - } - else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT ) - { - pem_free( &pem ); - - if( first_error == 0 ) - first_error = ret; - - continue; - } - else - break; - - ret = x509parse_crt_der( crt, pem.buf, pem.buflen ); - - pem_free( &pem ); - - if( ret != 0 ) - { - /* - * quit parsing on a memory error - */ - if( ret == POLARSSL_ERR_X509_MALLOC_FAILED ) - { - if( prev ) - prev->next = NULL; - - if( crt != chain ) - free( crt ); - - return( ret ); - } - - if( first_error == 0 ) - first_error = ret; - - total_failed++; - - memset( crt, 0, sizeof( x509_cert ) ); - continue; - } - - success = 1; - - /* - * Add new certificate to the list - */ - crt->next = (x509_cert *) malloc( sizeof( x509_cert ) ); - - if( crt->next == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - prev = crt; - crt = crt->next; - memset( crt, 0, sizeof( x509_cert ) ); - } - } -#endif - - if( crt->version == 0 ) - { - if( prev ) - prev->next = NULL; - - if( crt != chain ) - free( crt ); - } - - if( success ) - return( total_failed ); - else if( first_error ) - return( first_error ); - else - return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); -} - -/* - * Parse one or more CRLs and add them to the chained list - */ -int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - x509_crl *crl; -#if defined(POLARSSL_PEM_C) - size_t use_len; - pem_context pem; -#endif - - crl = chain; - - /* - * Check for valid input - */ - if( crl == NULL || buf == NULL ) - return( POLARSSL_ERR_X509_INVALID_INPUT ); - - while( crl->version != 0 && crl->next != NULL ) - crl = crl->next; - - /* - * Add new CRL on the end of the chain if needed. - */ - if ( crl->version != 0 && crl->next == NULL) - { - crl->next = (x509_crl *) malloc( sizeof( x509_crl ) ); - - if( crl->next == NULL ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - } - - crl = crl->next; - memset( crl, 0, sizeof( x509_crl ) ); - } - -#if defined(POLARSSL_PEM_C) - pem_init( &pem ); - ret = pem_read_buffer( &pem, - "-----BEGIN X509 CRL-----", - "-----END X509 CRL-----", - buf, NULL, 0, &use_len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - buflen -= use_len; - buf += use_len; - - /* - * Steal PEM buffer - */ - p = pem.buf; - pem.buf = NULL; - len = pem.buflen; - pem_free( &pem ); - } - else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT ) - { - pem_free( &pem ); - return( ret ); - } - else - { - /* - * nope, copy the raw DER data - */ - p = (unsigned char *) malloc( len = buflen ); - - if( p == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - buflen = 0; - } -#else - p = (unsigned char *) malloc( len = buflen ); - - if( p == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - buflen = 0; -#endif - - crl->raw.p = p; - crl->raw.len = len; - end = p + len; - - /* - * CertificateList ::= SEQUENCE { - * tbsCertList TBSCertList, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING } - */ - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT ); - } - - if( len != (size_t) ( end - p ) ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - } - - /* - * TBSCertList ::= SEQUENCE { - */ - crl->tbs.p = p; - - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); - } - - end = p + len; - crl->tbs.len = end - crl->tbs.p; - - /* - * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } - * -- if present, MUST be v2 - * - * signature AlgorithmIdentifier - */ - if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || - ( ret = x509_get_alg( &p, end, &crl->sig_oid1 ) ) != 0 ) - { - x509_crl_free( crl ); - return( ret ); - } - - crl->version++; - - if( crl->version > 2 ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION ); - } - - if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_alg ) ) != 0 ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG ); - } - - /* - * issuer Name - */ - crl->issuer_raw.p = p; - - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); - } - - if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) - { - x509_crl_free( crl ); - return( ret ); - } - - crl->issuer_raw.len = p - crl->issuer_raw.p; - - /* - * thisUpdate Time - * nextUpdate Time OPTIONAL - */ - if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 ) - { - x509_crl_free( crl ); - return( ret ); - } - - if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 ) - { - if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE + - POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) && - ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE + - POLARSSL_ERR_ASN1_OUT_OF_DATA ) ) - { - x509_crl_free( crl ); - return( ret ); - } - } - - /* - * revokedCertificates SEQUENCE OF SEQUENCE { - * userCertificate CertificateSerialNumber, - * revocationDate Time, - * crlEntryExtensions Extensions OPTIONAL - * -- if present, MUST be v2 - * } OPTIONAL - */ - if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) - { - x509_crl_free( crl ); - return( ret ); - } - - /* - * crlExtensions EXPLICIT Extensions OPTIONAL - * -- if present, MUST be v2 - */ - if( crl->version == 2 ) - { - ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); - - if( ret != 0 ) - { - x509_crl_free( crl ); - return( ret ); - } - } - - if( p != end ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - } - - end = crl->raw.p + crl->raw.len; - - /* - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - */ - if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2 ) ) != 0 ) - { - x509_crl_free( crl ); - return( ret ); - } - - if( memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH ); - } - - if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 ) - { - x509_crl_free( crl ); - return( ret ); - } - - if( p != end ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - } - - if( buflen > 0 ) - { - crl->next = (x509_crl *) malloc( sizeof( x509_crl ) ); - - if( crl->next == NULL ) - { - x509_crl_free( crl ); - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - } - - crl = crl->next; - memset( crl, 0, sizeof( x509_crl ) ); - - return( x509parse_crl( crl, buf, buflen ) ); - } - - return( 0 ); -} - -#if defined(POLARSSL_FS_IO) -/* - * Load all data from a file into a given buffer. - */ -int load_file( const char *path, unsigned char **buf, size_t *n ) -{ - FILE *f; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_X509_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - *n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - if( fread( *buf, 1, *n, f ) != *n ) - { - fclose( f ); - free( *buf ); - return( POLARSSL_ERR_X509_FILE_IO_ERROR ); - } - - fclose( f ); - - (*buf)[*n] = '\0'; - - return( 0 ); -} - -/* - * Load one or more certificates and add them to the chained list - */ -int x509parse_crtfile( x509_cert *chain, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = x509parse_crt( chain, buf, n ); - - memset( buf, 0, n + 1 ); - free( buf ); - - return( ret ); -} - -/* - * Load one or more CRLs and add them to the chained list - */ -int x509parse_crlfile( x509_crl *chain, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = x509parse_crl( chain, buf, n ); - - memset( buf, 0, n + 1 ); - free( buf ); - - return( ret ); -} - -/* - * Load and parse a private RSA key - */ -int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd ) -{ - int ret; - size_t n; - unsigned char *buf; - - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - if( pwd == NULL ) - ret = x509parse_key( rsa, buf, n, NULL, 0 ); - else - ret = x509parse_key( rsa, buf, n, - (unsigned char *) pwd, strlen( pwd ) ); - - memset( buf, 0, n + 1 ); - free( buf ); - - return( ret ); -} - -/* - * Load and parse a public RSA key - */ -int x509parse_public_keyfile( rsa_context *rsa, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = x509parse_public_key( rsa, buf, n ); - - memset( buf, 0, n + 1 ); - free( buf ); - - return( ret ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * Parse a private RSA key - */ -int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - unsigned char *p_alt; - x509_buf pk_alg_oid; - -#if defined(POLARSSL_PEM_C) - pem_context pem; - - pem_init( &pem ); - ret = pem_read_buffer( &pem, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", - key, pwd, pwdlen, &len ); - - if( ret == POLARSSL_ERR_PEM_NO_HEADER_PRESENT ) - { - ret = pem_read_buffer( &pem, - "-----BEGIN PRIVATE KEY-----", - "-----END PRIVATE KEY-----", - key, pwd, pwdlen, &len ); - } - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - keylen = pem.buflen; - } - else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT ) - { - pem_free( &pem ); - return( ret ); - } - - p = ( ret == 0 ) ? pem.buf : (unsigned char *) key; -#else - ((void) pwd); - ((void) pwdlen); - p = (unsigned char *) key; -#endif - end = p + keylen; - - /* - * Note: Depending on the type of private key file one can expect either a - * PrivatKeyInfo object (PKCS#8) or a RSAPrivateKey (PKCS#1) directly. - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * algorithm AlgorithmIdentifier, - * PrivateKey BIT STRING - * } - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * otherPrimeInfos OtherPrimeInfos OPTIONAL - * } - */ - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - if( rsa->ver != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); - } - - p_alt = p; - - if( ( ret = x509_get_alg( &p_alt, end, &pk_alg_oid ) ) != 0 ) - { - // Assume that we have the PKCS#1 format if wrong - // tag was encountered - // - if( ret != POLARSSL_ERR_X509_CERT_INVALID_ALG + - POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT ); - } - } - else - { - int can_handle; - - /* - * only RSA keys handled at this time - */ - can_handle = 0; - - if( pk_alg_oid.len == 9 && - memcmp( pk_alg_oid.p, OID_PKCS1_RSA, 9 ) == 0 ) - can_handle = 1; - - if( pk_alg_oid.len == 9 && - memcmp( pk_alg_oid.p, OID_PKCS1, 8 ) == 0 ) - { - if( pk_alg_oid.p[8] >= 2 && pk_alg_oid.p[8] <= 5 ) - can_handle = 1; - - if ( pk_alg_oid.p[8] >= 11 && pk_alg_oid.p[8] <= 14 ) - can_handle = 1; - } - - if( pk_alg_oid.len == 5 && - memcmp( pk_alg_oid.p, OID_RSA_SHA_OBS, 5 ) == 0 ) - can_handle = 1; - - if( can_handle == 0 ) - return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); - - /* - * Parse the PKCS#8 format - */ - - p = p_alt; - if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - if( ( end - p ) < 1 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - } - - end = p + len; - - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - if( rsa->ver != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); - } - } - - if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || - ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || - ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || - ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || - ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || - ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || - ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || - ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - rsa->len = mpi_size( &rsa->N ); - - if( p != end ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - } - - if( ( ret = rsa_check_privkey( rsa ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( ret ); - } - -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - - return( 0 ); -} - -/* - * Parse a public RSA key - */ -int x509parse_public_key( rsa_context *rsa, const unsigned char *key, size_t keylen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - x509_buf alg_oid; -#if defined(POLARSSL_PEM_C) - pem_context pem; - - pem_init( &pem ); - ret = pem_read_buffer( &pem, - "-----BEGIN PUBLIC KEY-----", - "-----END PUBLIC KEY-----", - key, NULL, 0, &len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - keylen = pem.buflen; - } - else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT ) - { - pem_free( &pem ); - return( ret ); - } - - p = ( ret == 0 ) ? pem.buf : (unsigned char *) key; -#else - p = (unsigned char *) key; -#endif - end = p + keylen; - - /* - * PublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * PublicKey BIT STRING - * } - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - * - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ - - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); - } - - if( ( ret = x509_get_pubkey( &p, end, &alg_oid, &rsa->N, &rsa->E ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - if( ( ret = rsa_check_pubkey( rsa ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( ret ); - } - - rsa->len = mpi_size( &rsa->N ); - -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - - return( 0 ); -} - -#if defined(POLARSSL_DHM_C) -/* - * Parse DHM parameters - */ -int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen ) -{ - int ret; - size_t len; - unsigned char *p, *end; -#if defined(POLARSSL_PEM_C) - pem_context pem; - - pem_init( &pem ); - - ret = pem_read_buffer( &pem, - "-----BEGIN DH PARAMETERS-----", - "-----END DH PARAMETERS-----", - dhmin, NULL, 0, &dhminlen ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - dhminlen = pem.buflen; - } - else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT ) - { - pem_free( &pem ); - return( ret ); - } - - p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; -#else - p = (unsigned char *) dhmin; -#endif - end = p + dhminlen; - - memset( dhm, 0, sizeof( dhm_context ) ); - - /* - * DHParams ::= SEQUENCE { - * prime INTEGER, -- P - * generator INTEGER, -- g - * } - */ - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || - ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - dhm_free( dhm ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - if( p != end ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - dhm_free( dhm ); - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - } - -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - - return( 0 ); -} - -#if defined(POLARSSL_FS_IO) -/* - * Load and parse a private RSA key - */ -int x509parse_dhmfile( dhm_context *dhm, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = x509parse_dhm( dhm, buf, n ); - - memset( buf, 0, n + 1 ); - free( buf ); - - return( ret ); -} -#endif /* POLARSSL_FS_IO */ -#endif /* POLARSSL_DHM_C */ - -#if defined _MSC_VER && !defined snprintf -#include - -#if !defined vsnprintf -#define vsnprintf _vsnprintf -#endif // vsnprintf - -/* - * Windows _snprintf and _vsnprintf are not compatible to linux versions. - * Result value is not size of buffer needed, but -1 if no fit is possible. - * - * This fuction tries to 'fix' this by at least suggesting enlarging the - * size by 20. - */ -int compat_snprintf(char *str, size_t size, const char *format, ...) -{ - va_list ap; - int res = -1; - - va_start( ap, format ); - - res = vsnprintf( str, size, format, ap ); - - va_end( ap ); - - // No quick fix possible - if ( res < 0 ) - return( (int) size + 20 ); - - return res; -} - -#define snprintf compat_snprintf -#endif - -#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 - -#define SAFE_SNPRINTF() \ -{ \ - if( ret == -1 ) \ - return( -1 ); \ - \ - if ( (unsigned int) ret > n ) { \ - p[n - 1] = '\0'; \ - return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\ - } \ - \ - n -= (unsigned int) ret; \ - p += (unsigned int) ret; \ -} - -/* - * Store the name in printable form into buf; no more - * than size characters will be written - */ -int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn ) -{ - int ret; - size_t i, n; - unsigned char c; - const x509_name *name; - char s[128], *p; - - memset( s, 0, sizeof( s ) ); - - name = dn; - p = buf; - n = size; - - while( name != NULL ) - { - if( name != dn ) - { - ret = snprintf( p, n, ", " ); - SAFE_SNPRINTF(); - } - - if( memcmp( name->oid.p, OID_X520, 2 ) == 0 ) - { - switch( name->oid.p[2] ) - { - case X520_COMMON_NAME: - ret = snprintf( p, n, "CN=" ); break; - - case X520_COUNTRY: - ret = snprintf( p, n, "C=" ); break; - - case X520_LOCALITY: - ret = snprintf( p, n, "L=" ); break; - - case X520_STATE: - ret = snprintf( p, n, "ST=" ); break; - - case X520_ORGANIZATION: - ret = snprintf( p, n, "O=" ); break; - - case X520_ORG_UNIT: - ret = snprintf( p, n, "OU=" ); break; - - default: - ret = snprintf( p, n, "0x%02X=", - name->oid.p[2] ); - break; - } - SAFE_SNPRINTF(); - } - else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 ) - { - switch( name->oid.p[8] ) - { - case PKCS9_EMAIL: - ret = snprintf( p, n, "emailAddress=" ); break; - - default: - ret = snprintf( p, n, "0x%02X=", - name->oid.p[8] ); - break; - } - SAFE_SNPRINTF(); - } - else - { - ret = snprintf( p, n, "\?\?=" ); - SAFE_SNPRINTF(); - } - - for( i = 0; i < name->val.len; i++ ) - { - if( i >= sizeof( s ) - 1 ) - break; - - c = name->val.p[i]; - if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) - s[i] = '?'; - else s[i] = c; - } - s[i] = '\0'; - ret = snprintf( p, n, "%s", s ); - SAFE_SNPRINTF(); - name = name->next; - } - - return( (int) ( size - n ) ); -} - -/* - * Store the serial in printable form into buf; no more - * than size characters will be written - */ -int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial ) -{ - int ret; - size_t i, n, nr; - char *p; - - p = buf; - n = size; - - nr = ( serial->len <= 32 ) - ? serial->len : 28; - - for( i = 0; i < nr; i++ ) - { - if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) - continue; - - ret = snprintf( p, n, "%02X%s", - serial->p[i], ( i < nr - 1 ) ? ":" : "" ); - SAFE_SNPRINTF(); - } - - if( nr != serial->len ) - { - ret = snprintf( p, n, "...." ); - SAFE_SNPRINTF(); - } - - return( (int) ( size - n ) ); -} - -/* - * Return an informational string about the certificate. - */ -int x509parse_cert_info( char *buf, size_t size, const char *prefix, - const x509_cert *crt ) -{ - int ret; - size_t n; - char *p; - - p = buf; - n = size; - - ret = snprintf( p, n, "%scert. version : %d\n", - prefix, crt->version ); - SAFE_SNPRINTF(); - ret = snprintf( p, n, "%sserial number : ", - prefix ); - SAFE_SNPRINTF(); - - ret = x509parse_serial_gets( p, n, &crt->serial); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%sissuer name : ", prefix ); - SAFE_SNPRINTF(); - ret = x509parse_dn_gets( p, n, &crt->issuer ); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%ssubject name : ", prefix ); - SAFE_SNPRINTF(); - ret = x509parse_dn_gets( p, n, &crt->subject ); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%sissued on : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crt->valid_from.year, crt->valid_from.mon, - crt->valid_from.day, crt->valid_from.hour, - crt->valid_from.min, crt->valid_from.sec ); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%sexpires on : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crt->valid_to.year, crt->valid_to.mon, - crt->valid_to.day, crt->valid_to.hour, - crt->valid_to.min, crt->valid_to.sec ); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix ); - SAFE_SNPRINTF(); - - switch( crt->sig_alg ) - { - case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break; - case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break; - case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break; - case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break; - case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break; - case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break; - case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break; - case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break; - default: ret = snprintf( p, n, "???" ); break; - } - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%sRSA key size : %d bits\n", prefix, - (int) crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 ); - SAFE_SNPRINTF(); - - return( (int) ( size - n ) ); -} - -/* Compare a given OID string with an OID x509_buf * */ -#define OID_CMP(oid_str, oid_buf) \ - ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \ - memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0) - -/* - * Return an informational string describing the given OID - */ -const char *x509_oid_get_description( x509_buf *oid ) -{ - if ( oid == NULL ) - return ( NULL ); - - else if( OID_CMP( OID_SERVER_AUTH, oid ) ) - return( STRING_SERVER_AUTH ); - - else if( OID_CMP( OID_CLIENT_AUTH, oid ) ) - return( STRING_CLIENT_AUTH ); - - else if( OID_CMP( OID_CODE_SIGNING, oid ) ) - return( STRING_CODE_SIGNING ); - - else if( OID_CMP( OID_EMAIL_PROTECTION, oid ) ) - return( STRING_EMAIL_PROTECTION ); - - else if( OID_CMP( OID_TIME_STAMPING, oid ) ) - return( STRING_TIME_STAMPING ); - - else if( OID_CMP( OID_OCSP_SIGNING, oid ) ) - return( STRING_OCSP_SIGNING ); - - return( NULL ); -} - -/* Return the x.y.z.... style numeric string for the given OID */ -int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid ) -{ - int ret; - size_t i, n; - unsigned int value; - char *p; - - p = buf; - n = size; - - /* First byte contains first two dots */ - if( oid->len > 0 ) - { - ret = snprintf( p, n, "%d.%d", oid->p[0]/40, oid->p[0]%40 ); - SAFE_SNPRINTF(); - } - - /* TODO: value can overflow in value. */ - value = 0; - for( i = 1; i < oid->len; i++ ) - { - value <<= 7; - value += oid->p[i] & 0x7F; - - if( !( oid->p[i] & 0x80 ) ) - { - /* Last byte */ - ret = snprintf( p, n, ".%d", value ); - SAFE_SNPRINTF(); - value = 0; - } - } - - return( (int) ( size - n ) ); -} - -/* - * Return an informational string about the CRL. - */ -int x509parse_crl_info( char *buf, size_t size, const char *prefix, - const x509_crl *crl ) -{ - int ret; - size_t n; - char *p; - const x509_crl_entry *entry; - - p = buf; - n = size; - - ret = snprintf( p, n, "%sCRL version : %d", - prefix, crl->version ); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%sissuer name : ", prefix ); - SAFE_SNPRINTF(); - ret = x509parse_dn_gets( p, n, &crl->issuer ); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%sthis update : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crl->this_update.year, crl->this_update.mon, - crl->this_update.day, crl->this_update.hour, - crl->this_update.min, crl->this_update.sec ); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n%snext update : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crl->next_update.year, crl->next_update.mon, - crl->next_update.day, crl->next_update.hour, - crl->next_update.min, crl->next_update.sec ); - SAFE_SNPRINTF(); - - entry = &crl->entry; - - ret = snprintf( p, n, "\n%sRevoked certificates:", - prefix ); - SAFE_SNPRINTF(); - - while( entry != NULL && entry->raw.len != 0 ) - { - ret = snprintf( p, n, "\n%sserial number: ", - prefix ); - SAFE_SNPRINTF(); - - ret = x509parse_serial_gets( p, n, &entry->serial); - SAFE_SNPRINTF(); - - ret = snprintf( p, n, " revocation date: " \ - "%04d-%02d-%02d %02d:%02d:%02d", - entry->revocation_date.year, entry->revocation_date.mon, - entry->revocation_date.day, entry->revocation_date.hour, - entry->revocation_date.min, entry->revocation_date.sec ); - SAFE_SNPRINTF(); - - entry = entry->next; - } - - ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix ); - SAFE_SNPRINTF(); - - switch( crl->sig_alg ) - { - case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break; - case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break; - case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break; - case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break; - case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break; - case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break; - case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break; - case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break; - default: ret = snprintf( p, n, "???" ); break; - } - SAFE_SNPRINTF(); - - ret = snprintf( p, n, "\n" ); - SAFE_SNPRINTF(); - - return( (int) ( size - n ) ); -} - -/* - * Return 0 if the x509_time is still valid, or 1 otherwise. - */ -int x509parse_time_expired( const x509_time *to ) -{ - int year, mon, day; - int hour, min, sec; - -#if defined(_WIN32) - SYSTEMTIME st; - - GetLocalTime(&st); - - year = st.wYear; - mon = st.wMonth; - day = st.wDay; - hour = st.wHour; - min = st.wMinute; - sec = st.wSecond; -#else - struct tm *lt; - time_t tt; - - tt = time( NULL ); - lt = localtime( &tt ); - - year = lt->tm_year + 1900; - mon = lt->tm_mon + 1; - day = lt->tm_mday; - hour = lt->tm_hour; - min = lt->tm_min; - sec = lt->tm_sec; -#endif - - if( year > to->year ) - return( 1 ); - - if( year == to->year && - mon > to->mon ) - return( 1 ); - - if( year == to->year && - mon == to->mon && - day > to->day ) - return( 1 ); - - if( year == to->year && - mon == to->mon && - day == to->day && - hour > to->hour ) - return( 1 ); - - if( year == to->year && - mon == to->mon && - day == to->day && - hour == to->hour && - min > to->min ) - return( 1 ); - - if( year == to->year && - mon == to->mon && - day == to->day && - hour == to->hour && - min == to->min && - sec > to->sec ) - return( 1 ); - - return( 0 ); -} - -/* - * Return 1 if the certificate is revoked, or 0 otherwise. - */ -int x509parse_revoked( const x509_cert *crt, const x509_crl *crl ) -{ - const x509_crl_entry *cur = &crl->entry; - - while( cur != NULL && cur->serial.len != 0 ) - { - if( crt->serial.len == cur->serial.len && - memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) - { - if( x509parse_time_expired( &cur->revocation_date ) ) - return( 1 ); - } - - cur = cur->next; - } - - return( 0 ); -} - -/* - * Wrapper for x509 hashes. - * - * \param out Buffer to receive the hash (Should be at least 64 bytes) - */ -static void x509_hash( const unsigned char *in, size_t len, int alg, - unsigned char *out ) -{ - switch( alg ) - { -#if defined(POLARSSL_MD2_C) - case SIG_RSA_MD2 : md2( in, len, out ); break; -#endif -#if defined(POLARSSL_MD4_C) - case SIG_RSA_MD4 : md4( in, len, out ); break; -#endif -#if defined(POLARSSL_MD5_C) - case SIG_RSA_MD5 : md5( in, len, out ); break; -#endif -#if defined(POLARSSL_SHA1_C) - case SIG_RSA_SHA1 : sha1( in, len, out ); break; -#endif -#if defined(POLARSSL_SHA2_C) - case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break; - case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break; -#endif -#if defined(POLARSSL_SHA4_C) - case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break; - case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break; -#endif - default: - memset( out, '\xFF', 64 ); - break; - } -} - -/* - * Check that the given certificate is valid accoring to the CRL. - */ -static int x509parse_verifycrl(x509_cert *crt, x509_cert *ca, - x509_crl *crl_list) -{ - int flags = 0; - int hash_id; - unsigned char hash[64]; - - /* - * TODO: What happens if no CRL is present? - * Suggestion: Revocation state should be unknown if no CRL is present. - * For backwards compatibility this is not yet implemented. - */ - - while( ca != NULL && crl_list != NULL && crl_list->version != 0 ) - { - if( crl_list->issuer_raw.len != ca->subject_raw.len || - memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, - crl_list->issuer_raw.len ) != 0 ) - { - crl_list = crl_list->next; - continue; - } - - /* - * Check if CRL is correctly signed by the trusted CA - */ - hash_id = crl_list->sig_alg; - - x509_hash( crl_list->tbs.p, crl_list->tbs.len, hash_id, hash ); - - if( !rsa_pkcs1_verify( &ca->rsa, RSA_PUBLIC, hash_id, - 0, hash, crl_list->sig.p ) == 0 ) - { - /* - * CRL is not trusted - */ - flags |= BADCRL_NOT_TRUSTED; - break; - } - - /* - * Check for validity of CRL (Do not drop out) - */ - if( x509parse_time_expired( &crl_list->next_update ) ) - flags |= BADCRL_EXPIRED; - - /* - * Check if certificate is revoked - */ - if( x509parse_revoked(crt, crl_list) ) - { - flags |= BADCERT_REVOKED; - break; - } - - crl_list = crl_list->next; - } - return flags; -} - -int x509_wildcard_verify( const char *cn, x509_buf *name ) -{ - size_t i; - size_t cn_idx = 0; - - if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) - return( 0 ); - - for( i = 0; i < strlen( cn ); ++i ) - { - if( cn[i] == '.' ) - { - cn_idx = i; - break; - } - } - - if( cn_idx == 0 ) - return( 0 ); - - if( memcmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 && - strlen( cn ) - cn_idx == name->len - 1 ) - { - return( 1 ); - } - - return( 0 ); -} - -/* - * Verify the certificate validity - */ -int x509parse_verify( x509_cert *crt, - x509_cert *trust_ca, - x509_crl *ca_crl, - const char *cn, int *flags, - int (*f_vrfy)(void *, x509_cert *, int, int), - void *p_vrfy ) -{ - size_t cn_len; - int hash_id; - int pathlen; - x509_cert *parent; - x509_name *name; - unsigned char hash[64]; - x509_sequence *cur = NULL; - - *flags = 0; - - if( x509parse_time_expired( &crt->valid_to ) ) - *flags = BADCERT_EXPIRED; - - if( cn != NULL ) - { - name = &crt->subject; - cn_len = strlen( cn ); - - while( name != NULL ) - { - if( memcmp( name->oid.p, OID_CN, 3 ) == 0 ) - { - if( memcmp( name->val.p, cn, cn_len ) == 0 && - name->val.len == cn_len ) - break; - - if( memcmp( name->val.p, "*.", 2 ) == 0 && - x509_wildcard_verify( cn, &name->val ) ) - break; - } - - name = name->next; - } - - if( name == NULL ) - { - if( crt->ext_types & EXT_SUBJECT_ALT_NAME ) - { - cur = &crt->subject_alt_names; - - while( cur != NULL ) - { - if( memcmp( cn, cur->buf.p, cn_len ) == 0 && - cur->buf.len == cn_len ) - break; - - if( memcmp( cur->buf.p, "*.", 2 ) == 0 && - x509_wildcard_verify( cn, &cur->buf ) ) - break; - - cur = cur->next; - } - } - - if( cur == NULL ) - *flags |= BADCERT_CN_MISMATCH; - } - } - - /* - * Iterate upwards in the given cert chain, - * ignoring any upper cert with CA != TRUE. - */ - parent = crt->next; - - pathlen = 1; - - while( parent != NULL && parent->version != 0 ) - { - if( parent->ca_istrue == 0 || - crt->issuer_raw.len != parent->subject_raw.len || - memcmp( crt->issuer_raw.p, parent->subject_raw.p, - crt->issuer_raw.len ) != 0 ) - { - parent = parent->next; - continue; - } - - hash_id = crt->sig_alg; - - x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash ); - - if( rsa_pkcs1_verify( &parent->rsa, RSA_PUBLIC, hash_id, 0, hash, - crt->sig.p ) != 0 ) - *flags |= BADCERT_NOT_TRUSTED; - - /* Check trusted CA's CRL for the given crt */ - *flags |= x509parse_verifycrl(crt, parent, ca_crl); - - /* crt is verified to be a child of the parent cur, call verify callback */ - if( NULL != f_vrfy ) - { - if( f_vrfy( p_vrfy, crt, pathlen - 1, ( *flags == 0 ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED ); - else - *flags = 0; - } - else if( *flags != 0 ) - return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED ); - - pathlen++; - - crt = parent; - parent = crt->next; - } - - /* - * Attempt to validate topmost cert with our CA chain. - */ - *flags |= BADCERT_NOT_TRUSTED; - - while( trust_ca != NULL && trust_ca->version != 0 ) - { - if( crt->issuer_raw.len != trust_ca->subject_raw.len || - memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p, - crt->issuer_raw.len ) != 0 ) - { - trust_ca = trust_ca->next; - continue; - } - - if( trust_ca->max_pathlen > 0 && - trust_ca->max_pathlen < pathlen ) - break; - - hash_id = crt->sig_alg; - - x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash ); - - if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id, - 0, hash, crt->sig.p ) == 0 ) - { - /* - * cert. is signed by a trusted CA - */ - *flags &= ~BADCERT_NOT_TRUSTED; - break; - } - - trust_ca = trust_ca->next; - } - - /* Check trusted CA's CRL for the given crt */ - *flags |= x509parse_verifycrl( crt, trust_ca, ca_crl ); - - /* Verification succeeded, call callback on top cert */ - if( NULL != f_vrfy ) - { - if( f_vrfy(p_vrfy, crt, pathlen-1, ( *flags == 0 ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED ); - else - *flags = 0; - } - else if( *flags != 0 ) - return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED ); - - return( 0 ); -} - -/* - * Unallocate all certificate data - */ -void x509_free( x509_cert *crt ) -{ - x509_cert *cert_cur = crt; - x509_cert *cert_prv; - x509_name *name_cur; - x509_name *name_prv; - x509_sequence *seq_cur; - x509_sequence *seq_prv; - - if( crt == NULL ) - return; - - do - { - rsa_free( &cert_cur->rsa ); - - name_cur = cert_cur->issuer.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - memset( name_prv, 0, sizeof( x509_name ) ); - free( name_prv ); - } - - name_cur = cert_cur->subject.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - memset( name_prv, 0, sizeof( x509_name ) ); - free( name_prv ); - } - - seq_cur = cert_cur->ext_key_usage.next; - while( seq_cur != NULL ) - { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - memset( seq_prv, 0, sizeof( x509_sequence ) ); - free( seq_prv ); - } - - seq_cur = cert_cur->subject_alt_names.next; - while( seq_cur != NULL ) - { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - memset( seq_prv, 0, sizeof( x509_sequence ) ); - free( seq_prv ); - } - - if( cert_cur->raw.p != NULL ) - { - memset( cert_cur->raw.p, 0, cert_cur->raw.len ); - free( cert_cur->raw.p ); - } - - cert_cur = cert_cur->next; - } - while( cert_cur != NULL ); - - cert_cur = crt; - do - { - cert_prv = cert_cur; - cert_cur = cert_cur->next; - - memset( cert_prv, 0, sizeof( x509_cert ) ); - if( cert_prv != crt ) - free( cert_prv ); - } - while( cert_cur != NULL ); -} - -/* - * Unallocate all CRL data - */ -void x509_crl_free( x509_crl *crl ) -{ - x509_crl *crl_cur = crl; - x509_crl *crl_prv; - x509_name *name_cur; - x509_name *name_prv; - x509_crl_entry *entry_cur; - x509_crl_entry *entry_prv; - - if( crl == NULL ) - return; - - do - { - name_cur = crl_cur->issuer.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - memset( name_prv, 0, sizeof( x509_name ) ); - free( name_prv ); - } - - entry_cur = crl_cur->entry.next; - while( entry_cur != NULL ) - { - entry_prv = entry_cur; - entry_cur = entry_cur->next; - memset( entry_prv, 0, sizeof( x509_crl_entry ) ); - free( entry_prv ); - } - - if( crl_cur->raw.p != NULL ) - { - memset( crl_cur->raw.p, 0, crl_cur->raw.len ); - free( crl_cur->raw.p ); - } - - crl_cur = crl_cur->next; - } - while( crl_cur != NULL ); - - crl_cur = crl; - do - { - crl_prv = crl_cur; - crl_cur = crl_cur->next; - - memset( crl_prv, 0, sizeof( x509_crl ) ); - if( crl_prv != crl ) - free( crl_prv ); - } - while( crl_cur != NULL ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include "polarssl/certs.h" - -/* - * Checkup routine - */ -int x509_self_test( int verbose ) -{ -#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C) - int ret; - int flags; - size_t i, j; - x509_cert cacert; - x509_cert clicert; - rsa_context rsa; -#if defined(POLARSSL_DHM_C) - dhm_context dhm; -#endif - - if( verbose != 0 ) - printf( " X.509 certificate load: " ); - - memset( &clicert, 0, sizeof( x509_cert ) ); - - ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt, - strlen( test_cli_crt ) ); - if( ret != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( ret ); - } - - memset( &cacert, 0, sizeof( x509_cert ) ); - - ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt, - strlen( test_ca_crt ) ); - if( ret != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - printf( "passed\n X.509 private key load: " ); - - i = strlen( test_ca_key ); - j = strlen( test_ca_pwd ); - - rsa_init( &rsa, RSA_PKCS_V15, 0 ); - - if( ( ret = x509parse_key( &rsa, - (unsigned char *) test_ca_key, i, - (unsigned char *) test_ca_pwd, j ) ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - printf( "passed\n X.509 signature verify: "); - - ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &flags, NULL, NULL ); - if( ret != 0 ) - { - printf("%02x", flags); - if( verbose != 0 ) - printf( "failed\n" ); - - return( ret ); - } - -#if defined(POLARSSL_DHM_C) - if( verbose != 0 ) - printf( "passed\n X.509 DHM parameter load: " ); - - i = strlen( test_dhm_params ); - j = strlen( test_ca_pwd ); - - if( ( ret = x509parse_dhm( &dhm, (unsigned char *) test_dhm_params, i ) ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - printf( "passed\n\n" ); -#endif - - x509_free( &cacert ); - x509_free( &clicert ); - rsa_free( &rsa ); -#if defined(POLARSSL_DHM_C) - dhm_free( &dhm ); -#endif - - return( 0 ); -#else - ((void) verbose); - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); -#endif -} - -#endif - -#endif diff --git a/polarssl/src/library/x509write.c b/polarssl/src/library/x509write.c deleted file mode 100644 index 400ffa0..0000000 --- a/polarssl/src/library/x509write.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * X509 buffer writing functionality - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_X509_WRITE_C) - -#include "polarssl/asn1write.h" -#include "polarssl/x509write.h" -#include "polarssl/x509.h" -#include "polarssl/sha1.h" -#include "polarssl/sha2.h" -#include "polarssl/sha4.h" -#include "polarssl/md4.h" -#include "polarssl/md5.h" - -int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) -{ - int ret; - unsigned char *c; - size_t len = 0; - - c = buf + size - 1; - - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); - - ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - if( c - buf < 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - *--c = 0; - len += 1; - - ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); - - ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, OID_PKCS1_RSA ) ); - - ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - return( len ); -} - -int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa ) -{ - int ret; - unsigned char *c; - size_t len = 0; - - c = buf + size - 1; - - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); - ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) ); - - ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - // TODO: Make NON RSA Specific variant later on -/* *--c = 0; - len += 1; - - len += asn1_write_len( &c, len); - len += asn1_write_tag( &c, ASN1_BIT_STRING ); - - len += asn1_write_oid( &c, OID_PKCS1_RSA ); - - len += asn1_write_int( &c, 0 ); - - len += asn1_write_len( &c, len); - len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/ - -/* for(i = 0; i < len; ++i) - { - if (i % 16 == 0 ) printf("\n"); - printf("%02x ", c[i]); - } - printf("\n");*/ - - return( len ); -} - -int x509_write_name( unsigned char **p, unsigned char *start, char *oid, - char *name ) -{ - int ret; - size_t string_len = 0; - size_t oid_len = 0; - size_t len = 0; - - // Write PrintableString for all except OID_PKCS9_EMAIL - // - if( OID_SIZE( OID_PKCS9_EMAIL ) == strlen( oid ) && - memcmp( oid, OID_PKCS9_EMAIL, strlen( oid ) ) == 0 ) - { - ASN1_CHK_ADD( string_len, asn1_write_ia5_string( p, start, name ) ); - } - else - ASN1_CHK_ADD( string_len, asn1_write_printable_string( p, start, name ) ); - - // Write OID - // - ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) ); - - len = oid_len + string_len; - ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + string_len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) ); - - return( len ); -} - -/* - * Wrapper for x509 hashes. - * - * \param out Buffer to receive the hash (Should be at least 64 bytes) - */ -static void x509_hash( const unsigned char *in, size_t len, int alg, - unsigned char *out ) -{ - switch( alg ) - { -#if defined(POLARSSL_MD2_C) - case SIG_RSA_MD2 : md2( in, len, out ); break; -#endif -#if defined(POLARSSL_MD4_C) - case SIG_RSA_MD4 : md4( in, len, out ); break; -#endif -#if defined(POLARSSL_MD5_C) - case SIG_RSA_MD5 : md5( in, len, out ); break; -#endif -#if defined(POLARSSL_SHA1_C) - case SIG_RSA_SHA1 : sha1( in, len, out ); break; -#endif -#if defined(POLARSSL_SHA2_C) - case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break; - case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break; -#endif -#if defined(POLARSSL_SHA4_C) - case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break; - case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break; -#endif - default: - memset( out, '\xFF', 64 ); - break; - } -} - -int x509_write_sig( unsigned char **p, unsigned char *start, char *oid, - unsigned char *sig, size_t size ) -{ - int ret; - size_t len = 0; - - if( *p - start < (int) size + 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - len = size; - (*p) -= len; - memcpy( *p, sig, len ); - - *--(*p) = 0; - len += 1; - - ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) ); - - // Write OID - // - ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid ) ); - - return( len ); -} - -int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, - x509_req_name *req_name, int hash_id ) -{ - int ret; - char sig_oid[10]; - unsigned char *c, *c2; - unsigned char hash[64]; - unsigned char sig[POLARSSL_MPI_MAX_SIZE]; - unsigned char tmp_buf[2048]; - size_t sub_len = 0, pub_len = 0, sig_len = 0; - size_t len = 0; - x509_req_name *cur = req_name; - - c = tmp_buf + 2048 - 1; - - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, 0 ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ); - - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->E ) ); - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->N ) ); - - ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) ); - ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - if( c - tmp_buf < 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - *--c = 0; - pub_len += 1; - - ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) ); - ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) ); - - ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) ); - - len += pub_len; - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - while( cur != NULL ) - { - ASN1_CHK_ADD( sub_len, x509_write_name( &c, tmp_buf, cur->oid, cur->name ) ); - - cur = cur->next; - } - - len += sub_len; - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); - - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - x509_hash( c, len, hash_id, hash ); - - rsa_pkcs1_sign( rsa, NULL, NULL, RSA_PRIVATE, hash_id, 0, hash, sig ); - - // Generate correct OID - // - memcpy( sig_oid, OID_PKCS1, 8 ); - sig_oid[8] = hash_id; - sig_oid[9] = '\0'; - - c2 = buf + size - 1; - ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, rsa->len ) ); - - c2 -= len; - memcpy( c2, c, len ); - - len += sig_len; - ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - return( len ); -} - -#endif diff --git a/polarssl/src/library/xtea.c b/polarssl/src/library/xtea.c deleted file mode 100644 index bc473e5..0000000 --- a/polarssl/src/library/xtea.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * An 32-bit implementation of the XTEA algorithm - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_XTEA_C) - -#include "polarssl/xtea.h" - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * XTEA key schedule - */ -void xtea_setup( xtea_context *ctx, unsigned char key[16] ) -{ - int i; - - memset(ctx, 0, sizeof(xtea_context)); - - for( i = 0; i < 4; i++ ) - { - GET_ULONG_BE( ctx->k[i], key, i << 2 ); - } -} - -/* - * XTEA encrypt function - */ -int xtea_crypt_ecb( xtea_context *ctx, int mode, unsigned char input[8], - unsigned char output[8]) -{ - uint32_t *k, v0, v1, i; - - k = ctx->k; - - GET_ULONG_BE( v0, input, 0 ); - GET_ULONG_BE( v1, input, 4 ); - - if( mode == XTEA_ENCRYPT ) - { - uint32_t sum = 0, delta = 0x9E3779B9; - - for( i = 0; i < 32; i++ ) - { - v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - sum += delta; - v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); - } - } - else /* XTEA_DECRYPT */ - { - uint32_t delta = 0x9E3779B9, sum = delta * 32; - - for( i = 0; i < 32; i++ ) - { - v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); - sum -= delta; - v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - } - } - - PUT_ULONG_BE( v0, output, 0 ); - PUT_ULONG_BE( v1, output, 4 ); - - return( 0 ); -} - -/* - * XTEA-CBC buffer encryption/decryption - */ -int xtea_crypt_cbc( xtea_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - unsigned char *input, - unsigned char *output) -{ - int i; - unsigned char temp[8]; - - if(length % 8) - return( POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH ); - - if( mode == XTEA_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - xtea_crypt_ecb( ctx, mode, input, output ); - - for(i = 0; i < 8; i++) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - xtea_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include -#include - -/* - * XTEA tests vectors (non-official) - */ - -static const unsigned char xtea_test_key[6][16] = -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char xtea_test_pt[6][8] = -{ - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } -}; - -static const unsigned char xtea_test_ct[6][8] = -{ - { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, - { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, - { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } -}; - -/* - * Checkup routine - */ -int xtea_self_test( int verbose ) -{ - int i; - unsigned char buf[8]; - xtea_context ctx; - - for( i = 0; i < 6; i++ ) - { - if( verbose != 0 ) - printf( " XTEA test #%d: ", i + 1 ); - - memcpy( buf, xtea_test_pt[i], 8 ); - - xtea_setup( &ctx, (unsigned char *) xtea_test_key[i] ); - xtea_crypt_ecb( &ctx, XTEA_ENCRYPT, buf, buf ); - - if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/pthreads/pthread-win32.vcxproj b/pthreads/pthread-win32.vcxproj deleted file mode 100644 index 7b33891..0000000 --- a/pthreads/pthread-win32.vcxproj +++ /dev/null @@ -1,122 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {CE4CD8F8-E5AB-46F6-ACF3-167687C47C9F} - pthreadwin32 - Win32Proj - - - - StaticLibrary - NotSet - true - v110_xp - - - StaticLibrary - NotSet - v110_xp - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)build\temp\lib\ - $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ - $(SolutionDir)build\temp\lib\ - $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ - AllRules.ruleset - - - AllRules.ruleset - - - $(ProjectName)-mt-debug - $(ProjectName)-mt - - - - Disabled - false - $(ProjectDir)src;%(AdditionalIncludeDirectories) - _WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;_DEBUG;_LIB;HAVE_PTW32_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;%(PreprocessorDefinitions) - false - - - Default - MultiThreadedDebug - - - Level3 - OldStyle - - - - - xcopy "$(ProjectDir)src\pthread.h" "$(SolutionDir)build\temp\include" /I /Y /D -xcopy "$(ProjectDir)src\semaphore.h" "$(SolutionDir)build\temp\include" /I /Y /D -xcopy "$(ProjectDir)src\sched.h" "$(SolutionDir)build\temp\include" /I /Y /D - - - - - - MaxSpeed - AnySuitable - false - false - $(ProjectDir)src;%(AdditionalIncludeDirectories) - _WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;NDEBUG;_LIB;HAVE_PTW32_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - - - Level3 - - - - - - - xcopy "$(ProjectDir)src\pthread.h" "$(SolutionDir)build\temp\include" /I /Y /D -xcopy "$(ProjectDir)src\semaphore.h" "$(SolutionDir)build\temp\include" /I /Y /D -xcopy "$(ProjectDir)src\sched.h" "$(SolutionDir)build\temp\include" /I /Y /D - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pthreads/pthread-win32.vcxproj.filters b/pthreads/pthread-win32.vcxproj.filters deleted file mode 100644 index 018736f..0000000 --- a/pthreads/pthread-win32.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {3a19fdc3-6df5-4400-b261-99ce258b4112} - - - {e7061adc-6595-41d4-b2a0-1dfdb96907bc} - - - - - include - - - include - - - include - - - include - - - include - - - - - src - - - \ No newline at end of file diff --git a/pthreads/src/COPYING.LIB b/pthreads/src/COPYING.LIB deleted file mode 100644 index b1e3f5a..0000000 --- a/pthreads/src/COPYING.LIB +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/pthreads/src/README b/pthreads/src/README deleted file mode 100644 index 545360b..0000000 --- a/pthreads/src/README +++ /dev/null @@ -1,601 +0,0 @@ -PTHREADS-WIN32 -============== - -Pthreads-win32 is free software, distributed under the GNU Lesser -General Public License (LGPL). See the file 'COPYING.LIB' for terms -and conditions. Also see the file 'COPYING' for information -specific to pthreads-win32, copyrights and the LGPL. - - -What is it? ------------ - -Pthreads-win32 is an Open Source Software implementation of the -Threads component of the POSIX 1003.1c 1995 Standard (or later) -for Microsoft's Win32 environment. Some functions from POSIX -1003.1b are also supported including semaphores. Other related -functions include the set of read-write lock functions. The -library also supports some of the functionality of the Open -Group's Single Unix specification, version 2, namely mutex types, -plus some common and pthreads-win32 specific non-portable -routines (see README.NONPORTABLE). - -See the file "ANNOUNCE" for more information including standards -conformance details and the list of supported and unsupported -routines. - - -Prerequisites -------------- -MSVC or GNU C (MinGW32 MSys development kit) - To build from source. - -QueueUserAPCEx by Panagiotis E. Hadjidoukas - To support any thread cancelation in C++ library builds or - to support cancelation of blocked threads in any build. - This library is not required otherwise. - - For true async cancelation of threads (including blocked threads). - This is a DLL and Windows driver that provides pre-emptive APC - by forcing threads into an alertable state when the APC is queued. - Both the DLL and driver are provided with the pthreads-win32.exe - self-unpacking ZIP, and on the pthreads-win32 FTP site (in source - and pre-built forms). Currently this is a separate LGPL package to - pthreads-win32. See the README in the QueueUserAPCEx folder for - installation instructions. - - Pthreads-win32 will automatically detect if the QueueUserAPCEx DLL - QuserEx.DLL is available and whether the driver AlertDrv.sys is - loaded. If it is not available, pthreads-win32 will simulate async - cancelation, which means that it can async cancel only threads that - are runnable. The simulated async cancellation cannot cancel blocked - threads. - - [FOR SECURITY] To be found Quserex.dll MUST be installed in the - Windows System Folder. This is not an unreasonable constraint given a - driver must also be installed and loaded at system startup. - - -Library naming --------------- - -Because the library is being built using various exception -handling schemes and compilers - and because the library -may not work reliably if these are mixed in an application, -each different version of the library has it's own name. - -Note 1: the incompatibility is really between EH implementations -of the different compilers. It should be possible to use the -standard C version from either compiler with C++ applications -built with a different compiler. If you use an EH version of -the library, then you must use the same compiler for the -application. This is another complication and dependency that -can be avoided by using only the standard C library version. - -Note 2: if you use a standard C pthread*.dll with a C++ -application, then any functions that you define that are -intended to be called via pthread_cleanup_push() must be -__cdecl. - -Note 3: the intention was to also name either the VC or GC -version (it should be arbitrary) as pthread.dll, including -pthread.lib and libpthread.a as appropriate. This is no longer -likely to happen. - -Note 4: the compatibility number was added so that applications -can differentiate between binary incompatible versions of the -libs and dlls. - -In general: - pthread[VG]{SE,CE,C}[c].dll - pthread[VG]{SE,CE,C}[c].lib - -where: - [VG] indicates the compiler - V - MS VC, or - G - GNU C - - {SE,CE,C} indicates the exception handling scheme - SE - Structured EH, or - CE - C++ EH, or - C - no exceptions - uses setjmp/longjmp - - c - DLL compatibility number indicating ABI and API - compatibility with applications built against - a snapshot with the same compatibility number. - See 'Version numbering' below. - -The name may also be suffixed by a 'd' to indicate a debugging version -of the library. E.g. pthreadVC2d.lib. Debugging versions contain -additional information for debugging (symbols etc) and are often not -optimised in any way (compiled with optimisation turned off). - -Examples: - pthreadVSE.dll (MSVC/SEH) - pthreadGCE.dll (GNUC/C++ EH) - pthreadGC.dll (GNUC/not dependent on exceptions) - pthreadVC1.dll (MSVC/not dependent on exceptions - not binary - compatible with pthreadVC.dll) - pthreadVC2.dll (MSVC/not dependent on exceptions - not binary - compatible with pthreadVC1.dll or pthreadVC.dll) - -The GNU library archive file names have correspondingly changed to: - - libpthreadGCEc.a - libpthreadGCc.a - - -Versioning numbering --------------------- - -Version numbering is separate from the snapshot dating system, and -is the canonical version identification system embedded within the -DLL using the Microsoft version resource system. The versioning -system chosen follows the GNU Libtool system. See -http://www.gnu.org/software/libtool/manual.html section 6.2. - -See the resource file 'version.rc'. - -Microsoft version numbers use 4 integers: - - 0.0.0.0 - -Pthreads-win32 uses the first 3 following the Libtool convention. -The fourth is commonly used for the build number, but will be reserved -for future use. - - current.revision.age.0 - -The numbers are changed as follows: - -1. If the library source code has changed at all since the last update, - then increment revision (`c:r:a' becomes `c:r+1:a'). -2. If any interfaces have been added, removed, or changed since the last - update, increment current, and set revision to 0. -3. If any interfaces have been added since the last public release, then - increment age. -4. If any interfaces have been removed or changed since the last public - release, then set age to 0. - - -DLL compatibility numbering is an attempt to ensure that applications -always load a compatible pthreads-win32 DLL by using a DLL naming system -that is consistent with the version numbering system. It also allows -older and newer DLLs to coexist in the same filesystem so that older -applications can continue to be used. For pre .NET Windows systems, -this inevitably requires incompatible versions of the same DLLs to have -different names. - -Pthreads-win32 has adopted the Cygwin convention of appending a single -integer number to the DLL name. The number used is based on the library -version number and is computed as 'current' - 'age'. - -(See http://home.att.net/~perlspinr/libversioning.html for a nicely -detailed explanation.) - -Using this method, DLL name/s will only change when the DLL's -backwards compatibility changes. Note that the addition of new -'interfaces' will not of itself change the DLL's compatibility for older -applications. - - -Which of the several dll versions to use? ------------------------------------------ -or, ---- -What are all these pthread*.dll and pthread*.lib files? -------------------------------------------------------- - -Simple, use either pthreadGCv.* if you use GCC, or pthreadVCv.* if you -use MSVC - where 'v' is the DLL versioning (compatibility) number. - -Otherwise, you need to choose carefully and know WHY. - -The most important choice you need to make is whether to use a -version that uses exceptions internally, or not. There are versions -of the library that use exceptions as part of the thread -cancelation and exit implementation. The default version uses -setjmp/longjmp. - -There is some contension amongst POSIX threads experts as -to how POSIX threads cancelation and exit should work -with languages that use exceptions, e.g. C++ and even C -(Microsoft's Structured Exceptions). - -The issue is: should cancelation of a thread in, say, -a C++ application cause object destructors and C++ exception -handlers to be invoked as the stack unwinds during thread -exit, or not? - -There seems to be more opinion in favour of using the -standard C version of the library (no EH) with C++ applications -for the reason that this appears to be the assumption commercial -pthreads implementations make. Therefore, if you use an EH version -of pthreads-win32 then you may be under the illusion that -your application will be portable, when in fact it is likely to -behave differently when linked with other pthreads libraries. - -Now you may be asking: then why have you kept the EH versions of -the library? - -There are a couple of reasons: -- there is division amongst the experts and so the code may - be needed in the future. Yes, it's in the repository and we - can get it out anytime in the future, but it would be difficult - to find. -- pthreads-win32 is one of the few implementations, and possibly - the only freely available one, that has EH versions. It may be - useful to people who want to play with or study application - behaviour under these conditions. - -Notes: - -[If you use either pthreadVCE or pthreadGCE] - -1. [See also the discussion in the FAQ file - Q2, Q4, and Q5] - -If your application contains catch(...) blocks in your POSIX -threads then you will need to replace the "catch(...)" with the macro -"PtW32Catch", eg. - - #ifdef PtW32Catch - PtW32Catch { - ... - } - #else - catch(...) { - ... - } - #endif - -Otherwise neither pthreads cancelation nor pthread_exit() will work -reliably when using versions of the library that use C++ exceptions -for cancelation and thread exit. - -This is due to what is believed to be a C++ compliance error in VC++ -whereby you may not have multiple handlers for the same exception in -the same try/catch block. GNU G++ doesn't have this restriction. - - -Other name changes ------------------- - -All snapshots prior to and including snapshot 2000-08-13 -used "_pthread_" as the prefix to library internal -functions, and "_PTHREAD_" to many library internal -macros. These have now been changed to "ptw32_" and "PTW32_" -respectively so as to not conflict with the ANSI standard's -reservation of identifiers beginning with "_" and "__" for -use by compiler implementations only. - -If you have written any applications and you are linking -statically with the pthreads-win32 library then you may have -included a call to _pthread_processInitialize. You will -now have to change that to ptw32_processInitialize. - - -Cleanup code default style --------------------------- - -Previously, if not defined, the cleanup style was determined automatically -from the compiler used, and one of the following was defined accordingly: - - __CLEANUP_SEH MSVC only - __CLEANUP_CXX C++, including MSVC++, GNU G++ - __CLEANUP_C C, including GNU GCC, not MSVC - -These defines determine the style of cleanup (see pthread.h) and, -most importantly, the way that cancelation and thread exit (via -pthread_exit) is performed (see the routine ptw32_throw()). - -In short, the exceptions versions of the library throw an exception -when a thread is canceled, or exits via pthread_exit(). This exception is -caught by a handler in the thread startup routine, so that the -the correct stack unwinding occurs regardless of where the thread -is when it's canceled or exits via pthread_exit(). - -In this snapshot, unless the build explicitly defines (e.g. via a -compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then -the build NOW always defaults to __CLEANUP_C style cleanup. This style -uses setjmp/longjmp in the cancelation and pthread_exit implementations, -and therefore won't do stack unwinding even when linked to applications -that have it (e.g. C++ apps). This is for consistency with most/all -commercial Unix POSIX threads implementations. - -Although it was not clearly documented before, it is still necessary to -build your application using the same __CLEANUP_* define as was -used for the version of the library that you link with, so that the -correct parts of pthread.h are included. That is, the possible -defines require the following library versions: - - __CLEANUP_SEH pthreadVSE.dll - __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll - __CLEANUP_C pthreadVC.dll or pthreadGC.dll - -It is recommended that you let pthread.h use it's default __CLEANUP_C -for both library and application builds. That is, don't define any of -the above, and then link with pthreadVC.lib (MSVC or MSVC++) and -libpthreadGC.a (MinGW GCC or G++). The reason is explained below, but -another reason is that the prebuilt pthreadVCE.dll is currently broken. -Versions built with MSVC++ later than version 6 may not be broken, but I -can't verify this yet. - -WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY? -Because no commercial Unix POSIX threads implementation allows you to -choose to have stack unwinding. Therefore, providing it in pthread-win32 -as a default is dangerous. We still provide the choice but unless -you consciously choose to do otherwise, your pthreads applications will -now run or crash in similar ways irrespective of the pthreads platform -you use. Or at least this is the hope. - - -Building under VC++ using C++ EH, Structured EH, or just C ----------------------------------------------------------- - -From the source directory run nmake without any arguments to list -help information. E.g. - -$ nmake - -Microsoft (R) Program Maintenance Utility Version 6.00.8168.0 -Copyright (C) Microsoft Corp 1988-1998. All rights reserved. - -Run one of the following command lines: -nmake clean VCE (to build the MSVC dll with C++ exception handling) -nmake clean VSE (to build the MSVC dll with structured exception handling) -nmake clean VC (to build the MSVC dll with C cleanup code) -nmake clean VCE-inlined (to build the MSVC inlined dll with C++ exception handling) -nmake clean VSE-inlined (to build the MSVC inlined dll with structured exception handling) -nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code) -nmake clean VC-static (to build the MSVC static lib with C cleanup code) -nmake clean VCE-debug (to build the debug MSVC dll with C++ exception handling) -nmake clean VSE-debug (to build the debug MSVC dll with structured exception handling) -nmake clean VC-debug (to build the debug MSVC dll with C cleanup code) -nmake clean VCE-inlined-debug (to build the debug MSVC inlined dll with C++ exception handling) -nmake clean VSE-inlined-debug (to build the debug MSVC inlined dll with structured exception handling) -nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code) -nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code) - - -The pre-built dlls are normally built using the *-inlined targets. - -You can run the testsuite by changing to the "tests" directory and -running nmake. E.g.: - -$ cd tests -$ nmake - -Microsoft (R) Program Maintenance Utility Version 6.00.8168.0 -Copyright (C) Microsoft Corp 1988-1998. All rights reserved. - -Run one of the following command lines: -nmake clean VC (to test using VC dll with VC (no EH) applications) -nmake clean VCX (to test using VC dll with VC++ (EH) applications) -nmake clean VCE (to test using the VCE dll with VC++ EH applications) -nmake clean VSE (to test using VSE dll with VC (SEH) applications) -nmake clean VC-bench (to benchtest using VC dll with C bench app) -nmake clean VCX-bench (to benchtest using VC dll with C++ bench app) -nmake clean VCE-bench (to benchtest using VCE dll with C++ bench app) -nmake clean VSE-bench (to benchtest using VSE dll with SEH bench app) -nmake clean VC-static (to test using VC static lib with VC (no EH) applications) - - -Building under Mingw32 ----------------------- - -The dll can be built easily with recent versions of Mingw32. -(The distributed versions are built using Mingw32 and MsysDTK -from www.mingw32.org.) - -From the source directory, run make for help information. E.g.: - -$ make -Run one of the following command lines: -make clean GC (to build the GNU C dll with C cleanup code) -make clean GCE (to build the GNU C dll with C++ exception handling) -make clean GC-inlined (to build the GNU C inlined dll with C cleanup code) -make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling) -make clean GC-static (to build the GNU C inlined static lib with C cleanup code) -make clean GC-debug (to build the GNU C debug dll with C cleanup code) -make clean GCE-debug (to build the GNU C debug dll with C++ exception handling) -make clean GC-inlined-debug (to build the GNU C inlined debug dll with C cleanup code) -make clean GCE-inlined-debug (to build the GNU C inlined debug dll with C++ exception handling) -make clean GC-static-debug (to build the GNU C inlined static debug lib with C cleanup code) - - -The pre-built dlls are normally built using the *-inlined targets. - -You can run the testsuite by changing to the "tests" directory and -running make for help information. E.g.: - -$ cd tests -$ make -Run one of the following command lines: -make clean GC (to test using GC dll with C (no EH) applications) -make clean GCX (to test using GC dll with C++ (EH) applications) -make clean GCE (to test using GCE dll with C++ (EH) applications) -make clean GC-bench (to benchtest using GNU C dll with C cleanup code) -make clean GCE-bench (to benchtest using GNU C dll with C++ exception handling) -make clean GC-static (to test using GC static lib with C (no EH) applications) - - -Building under Linux using the Mingw32 cross development tools --------------------------------------------------------------- - -You can build the library without leaving Linux by using the Mingw32 cross -development toolchain. See http://www.libsdl.org/extras/win32/cross/ for -tools and info. The GNUmakefile contains some support for this, for example: - -make CROSS=i386-mingw32msvc- clean GC-inlined - -will build pthreadGCn.dll and libpthreadGCn.a (n=version#), provided your -cross-tools/bin directory is in your PATH (or use the cross-make.sh script -at the URL above). - - -Building the library as a statically linkable library ------------------------------------------------------ - -General: PTW32_STATIC_LIB must be defined for both the library build and the -application build. The makefiles supplied and used by the following 'make' -command lines will define this for you. - -MSVC (creates pthreadVCn.lib as a static link lib): - -nmake clean VC-static - - -MinGW32 (creates libpthreadGCn.a as a static link lib): - -make clean GC-static - - -Define PTW32_STATIC_LIB when building your application. Also, your -application must call a two non-portable routines to initialise the -some state on startup and cleanup before exit. One other routine needs -to be called to cleanup after any Win32 threads have called POSIX API -routines. See README.NONPORTABLE or the html reference manual pages for -details on these routines: - -BOOL pthread_win32_process_attach_np (void); -BOOL pthread_win32_process_detach_np (void); -BOOL pthread_win32_thread_attach_np (void); // Currently a no-op -BOOL pthread_win32_thread_detach_np (void); - - -The tests makefiles have the same targets but only check that the -static library is statically linkable. They don't run the full -testsuite. To run the full testsuite, build the dlls and run the -dll test targets. - - -Building the library under Cygwin ---------------------------------- - -Cygwin is implementing it's own POSIX threads routines and these -will be the ones to use if you develop using Cygwin. - - -Ready to run binaries ---------------------- - -For convenience, the following ready-to-run files can be downloaded -from the FTP site (see under "Availability" below): - - pthread.h - semaphore.h - sched.h - pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp - pthreadVC.lib - pthreadVCE.dll - built with MSVC++ compiler using C++ EH - pthreadVCE.lib - pthreadVSE.dll - built with MSVC compiler using SEH - pthreadVSE.lib - pthreadGC.dll - built with Mingw32 GCC - libpthreadGC.a - derived from pthreadGC.dll - pthreadGCE.dll - built with Mingw32 G++ - libpthreadGCE.a - derived from pthreadGCE.dll - -As of August 2003 pthreads-win32 pthreadG* versions are built and tested -using the MinGW + MsysDTK environment current as of that date or later. -The following file MAY be needed for older MinGW environments. - - gcc.dll - needed to build and run applications that use - pthreadGCE.dll. - - -Building applications with GNU compilers ----------------------------------------- - -If you're using pthreadGC.dll: - -With the three header files, pthreadGC.dll and libpthreadGC.a in the -same directory as your application myapp.c, you could compile, link -and run myapp.c under Mingw32 as follows: - - gcc -o myapp.exe myapp.c -I. -L. -lpthreadGC - myapp - -Or put pthreadGC.dll in an appropriate directory in your PATH, -put libpthreadGC.a in your system lib directory, and -put the three header files in your system include directory, -then use: - - gcc -o myapp.exe myapp.c -lpthreadGC - myapp - - -If you're using pthreadGCE.dll: - -With the three header files, pthreadGCE.dll, gcc.dll and libpthreadGCE.a -in the same directory as your application myapp.c, you could compile, -link and run myapp.c under Mingw32 as follows: - - gcc -x c++ -o myapp.exe myapp.c -I. -L. -lpthreadGCE - myapp - -Or put pthreadGCE.dll and gcc.dll in an appropriate directory in -your PATH, put libpthreadGCE.a in your system lib directory, and -put the three header files in your system include directory, -then use: - - gcc -x c++ -o myapp.exe myapp.c -lpthreadGCE - myapp - - -Availability ------------- - -The complete source code in either unbundled, self-extracting -Zip file, or tar/gzipped format can be found at: - - ftp://sources.redhat.com/pub/pthreads-win32 - -The pre-built DLL, export libraries and matching pthread.h can -be found at: - - ftp://sources.redhat.com/pub/pthreads-win32/dll-latest - -Home page: - - http://sources.redhat.com/pthreads-win32/ - - -Mailing list ------------- - -There is a mailing list for discussing pthreads on Win32. -To join, send email to: - - pthreads-win32-subscribe@sources.redhat.com - -Unsubscribe by sending mail to: - - pthreads-win32-unsubscribe@sources.redhat.com - - -Acknowledgements ----------------- - -See the ANNOUNCE file for acknowledgements. -See the 'CONTRIBUTORS' file for the list of contributors. - -As much as possible, the ChangeLog file attributes -contributions and patches that have been incorporated -in the library to the individuals responsible. - -Finally, thanks to all those who work on and contribute to the -POSIX and Single Unix Specification standards. The maturity of an -industry can be measured by it's open standards. - ----- -Ross Johnson - - - - - - - - - diff --git a/pthreads/src/attr.c b/pthreads/src/attr.c deleted file mode 100644 index a9d55f4..0000000 --- a/pthreads/src/attr.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * attr.c - * - * Description: - * This translation unit agregates operations on thread attribute objects. - * It is used for inline optimisation. - * - * The included modules are used separately when static executable sizes - * must be minimised. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -#include "pthread_attr_init.c" -#include "pthread_attr_destroy.c" -#include "pthread_attr_getdetachstate.c" -#include "pthread_attr_setdetachstate.c" -#include "pthread_attr_getstackaddr.c" -#include "pthread_attr_setstackaddr.c" -#include "pthread_attr_getstacksize.c" -#include "pthread_attr_setstacksize.c" -#include "pthread_attr_getscope.c" -#include "pthread_attr_setscope.c" diff --git a/pthreads/src/autostatic.c b/pthreads/src/autostatic.c deleted file mode 100644 index 092aff2..0000000 --- a/pthreads/src/autostatic.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * autostatic.c - * - * Description: - * This translation unit implements static auto-init and auto-exit logic. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if defined(PTW32_STATIC_LIB) - -#if defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER) - -#include "pthread.h" -#include "implement.h" - -static void on_process_init(void) -{ - pthread_win32_process_attach_np (); -} - -static void on_process_exit(void) -{ - pthread_win32_thread_detach_np (); - pthread_win32_process_detach_np (); -} - -#if defined(__MINGW64__) || defined(__MINGW32__) -# define attribute_section(a) __attribute__((section(a))) -#elif defined(_MSC_VER) -# define attribute_section(a) __pragma(section(a,long,read)); __declspec(allocate(a)) -#endif - -attribute_section(".ctors") void *gcc_ctor = on_process_init; -attribute_section(".dtors") void *gcc_dtor = on_process_exit; - -attribute_section(".CRT$XCU") void *msc_ctor = on_process_init; -attribute_section(".CRT$XPU") void *msc_dtor = on_process_exit; - -#endif /* defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER) */ - -#endif /* PTW32_STATIC_LIB */ diff --git a/pthreads/src/barrier.c b/pthreads/src/barrier.c deleted file mode 100644 index 41b950c..0000000 --- a/pthreads/src/barrier.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * barrier.c - * - * Description: - * This translation unit implements barrier primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -#include "pthread_barrier_init.c" -#include "pthread_barrier_destroy.c" -#include "pthread_barrier_wait.c" -#include "pthread_barrierattr_init.c" -#include "pthread_barrierattr_destroy.c" -#include "pthread_barrierattr_getpshared.c" -#include "pthread_barrierattr_setpshared.c" diff --git a/pthreads/src/cancel.c b/pthreads/src/cancel.c deleted file mode 100644 index 1bd14eb..0000000 --- a/pthreads/src/cancel.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * cancel.c - * - * Description: - * POSIX thread functions related to thread cancellation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -#include "pthread_setcancelstate.c" -#include "pthread_setcanceltype.c" -#include "pthread_testcancel.c" -#include "pthread_cancel.c" diff --git a/pthreads/src/cleanup.c b/pthreads/src/cleanup.c deleted file mode 100644 index 381d1e8..0000000 --- a/pthreads/src/cleanup.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * cleanup.c - * - * Description: - * This translation unit implements routines associated - * with cleaning up threads. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -/* - * The functions ptw32_pop_cleanup and ptw32_push_cleanup - * are implemented here for applications written in C with no - * SEH or C++ destructor support. - */ - -ptw32_cleanup_t * -ptw32_pop_cleanup (int execute) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function pops the most recently pushed cleanup - * handler. If execute is nonzero, then the cleanup handler - * is executed if non-null. - * - * PARAMETERS - * execute - * if nonzero, execute the cleanup handler - * - * - * DESCRIPTION - * This function pops the most recently pushed cleanup - * handler. If execute is nonzero, then the cleanup handler - * is executed if non-null. - * NOTE: specify 'execute' as nonzero to avoid duplication - * of common cleanup code. - * - * RESULTS - * N/A - * - * ------------------------------------------------------ - */ -{ - ptw32_cleanup_t *cleanup; - - cleanup = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey); - - if (cleanup != NULL) - { - if (execute && (cleanup->routine != NULL)) - { - - (*cleanup->routine) (cleanup->arg); - - } - - pthread_setspecific (ptw32_cleanupKey, (void *) cleanup->prev); - - } - - return (cleanup); - -} /* ptw32_pop_cleanup */ - - -void -ptw32_push_cleanup (ptw32_cleanup_t * cleanup, - ptw32_cleanup_callback_t routine, void *arg) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function pushes a new cleanup handler onto the thread's stack - * of cleanup handlers. Each cleanup handler pushed onto the stack is - * popped and invoked with the argument 'arg' when - * a) the thread exits by calling 'pthread_exit', - * b) when the thread acts on a cancellation request, - * c) or when the thread calls pthread_cleanup_pop with a nonzero - * 'execute' argument - * - * PARAMETERS - * cleanup - * a pointer to an instance of pthread_cleanup_t, - * - * routine - * pointer to a cleanup handler, - * - * arg - * parameter to be passed to the cleanup handler - * - * - * DESCRIPTION - * This function pushes a new cleanup handler onto the thread's stack - * of cleanup handlers. Each cleanup handler pushed onto the stack is - * popped and invoked with the argument 'arg' when - * a) the thread exits by calling 'pthread_exit', - * b) when the thread acts on a cancellation request, - * c) or when the thrad calls pthread_cleanup_pop with a nonzero - * 'execute' argument - * NOTE: pthread_push_cleanup, ptw32_pop_cleanup must be paired - * in the same lexical scope. - * - * RESULTS - * pthread_cleanup_t * - * pointer to the previous cleanup - * - * ------------------------------------------------------ - */ -{ - cleanup->routine = routine; - cleanup->arg = arg; - - cleanup->prev = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey); - - pthread_setspecific (ptw32_cleanupKey, (void *) cleanup); - -} /* ptw32_push_cleanup */ diff --git a/pthreads/src/condvar.c b/pthreads/src/condvar.c deleted file mode 100644 index 704f4d7..0000000 --- a/pthreads/src/condvar.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * condvar.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - */ - -#include "pthread.h" -#include "implement.h" - -#include "ptw32_cond_check_need_init.c" -#include "pthread_condattr_init.c" -#include "pthread_condattr_destroy.c" -#include "pthread_condattr_getpshared.c" -#include "pthread_condattr_setpshared.c" -#include "pthread_cond_init.c" -#include "pthread_cond_destroy.c" -#include "pthread_cond_wait.c" -#include "pthread_cond_signal.c" diff --git a/pthreads/src/config.h b/pthreads/src/config.h deleted file mode 100644 index e231724..0000000 --- a/pthreads/src/config.h +++ /dev/null @@ -1,153 +0,0 @@ -/* config.h */ - -#ifndef PTW32_CONFIG_H -#define PTW32_CONFIG_H - -/********************************************************************* - * Defaults: see target specific redefinitions below. - *********************************************************************/ - -/* We're building the pthreads-win32 library */ -#define PTW32_BUILD - -/* Do we know about the C type sigset_t? */ -#undef HAVE_SIGSET_T - -/* Define if you have the header file. */ -#undef HAVE_SIGNAL_H - -/* Define if you have the Borland TASM32 or compatible assembler. */ -#undef HAVE_TASM32 - -/* Define if you don't have Win32 DuplicateHandle. (eg. WinCE) */ -#undef NEED_DUPLICATEHANDLE - -/* Define if you don't have Win32 _beginthreadex. (eg. WinCE) */ -#undef NEED_CREATETHREAD - -/* Define if you don't have Win32 errno. (eg. WinCE) */ -#undef NEED_ERRNO - -/* Define if you don't have Win32 calloc. (eg. WinCE) */ -#undef NEED_CALLOC - -/* Define if you don't have Win32 ftime. (eg. WinCE) */ -#undef NEED_FTIME - -/* Define if you don't have Win32 semaphores. (eg. WinCE 2.1 or earlier) */ -#undef NEED_SEM - -/* Define if you need to convert string parameters to unicode. (eg. WinCE) */ -#undef NEED_UNICODE_CONSTS - -/* Define if your C (not C++) compiler supports "inline" functions. */ -#undef HAVE_C_INLINE - -/* Do we know about type mode_t? */ -#undef HAVE_MODE_T - -/* - * Define if GCC has atomic builtins, i.e. __sync_* intrinsics - * __sync_lock_* is implemented in mingw32 gcc 4.5.2 at least - * so this define does not turn those on or off. If you get an - * error from __sync_lock* then consider upgrading your gcc. - */ -#undef HAVE_GCC_ATOMIC_BUILTINS - -/* Define if you have the timespec struct */ -#undef HAVE_STRUCT_TIMESPEC - -/* Define if you don't have the GetProcessAffinityMask() */ -#undef NEED_PROCESS_AFFINITY_MASK - -/* Define if your version of Windows TLSGetValue() clears WSALastError - * and calling SetLastError() isn't enough restore it. You'll also need to - * link against wsock32.lib (or libwsock32.a for MinGW). - */ -#undef RETAIN_WSALASTERROR - -/* -# ---------------------------------------------------------------------- -# The library can be built with some alternative behaviour to better -# facilitate development of applications on Win32 that will be ported -# to other POSIX systems. -# -# Nothing described here will make the library non-compliant and strictly -# compliant applications will not be affected in any way, but -# applications that make assumptions that POSIX does not guarantee are -# not strictly compliant and may fail or misbehave with some settings. -# -# PTW32_THREAD_ID_REUSE_INCREMENT -# Purpose: -# POSIX says that applications should assume that thread IDs can be -# recycled. However, Solaris (and some other systems) use a [very large] -# sequence number as the thread ID, which provides virtual uniqueness. -# This provides a very high but finite level of safety for applications -# that are not meticulous in tracking thread lifecycles e.g. applications -# that call functions which target detached threads without some form of -# thread exit synchronisation. -# -# Usage: -# Set to any value in the range: 0 <= value < 2^wordsize. -# Set to 0 to emulate reusable thread ID behaviour like Linux or *BSD. -# Set to 1 for unique thread IDs like Solaris (this is the default). -# Set to some factor of 2^wordsize to emulate smaller word size types -# (i.e. will wrap sooner). This might be useful to emulate some embedded -# systems. -# -# define PTW32_THREAD_ID_REUSE_INCREMENT 0 -# -# ---------------------------------------------------------------------- - */ -#undef PTW32_THREAD_ID_REUSE_INCREMENT - - -/********************************************************************* - * Target specific groups - * - * If you find that these are incorrect or incomplete please report it - * to the pthreads-win32 maintainer. Thanks. - *********************************************************************/ -#if defined(WINCE) -#define NEED_DUPLICATEHANDLE -#define NEED_CREATETHREAD -#define NEED_ERRNO -#define NEED_CALLOC -#define NEED_FTIME -/* #define NEED_SEM */ -#define NEED_UNICODE_CONSTS -#define NEED_PROCESS_AFFINITY_MASK -/* This may not be needed */ -#define RETAIN_WSALASTERROR -#endif - -#if defined(_UWIN) -#define HAVE_MODE_T -#define HAVE_STRUCT_TIMESPEC -#endif - -#if defined(__GNUC__) -#define HAVE_C_INLINE -#endif - -#if defined(__MINGW64__) -#define HAVE_MODE_T -#define HAVE_STRUCT_TIMESPEC -#elif defined(__MINGW32__) -#define HAVE_MODE_T -#endif - -#if defined(__BORLANDC__) -#endif - -#if defined(__WATCOMC__) -#endif - -#if defined(__DMC__) -#define HAVE_SIGNAL_H -#define HAVE_C_INLINE -#endif - - - -#endif diff --git a/pthreads/src/context.h b/pthreads/src/context.h deleted file mode 100644 index 3d4511f..0000000 --- a/pthreads/src/context.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * context.h - * - * Description: - * POSIX thread macros related to thread cancellation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#ifndef PTW32_CONTEXT_H -#define PTW32_CONTEXT_H - -#undef PTW32_PROGCTR - -#if defined(_M_IX86) || (defined(_X86_) && !defined(__amd64__)) -#define PTW32_PROGCTR(Context) ((Context).Eip) -#endif - -#if defined (_M_IA64) || defined(_IA64) -#define PTW32_PROGCTR(Context) ((Context).StIIP) -#endif - -#if defined(_MIPS_) || defined(MIPS) -#define PTW32_PROGCTR(Context) ((Context).Fir) -#endif - -#if defined(_ALPHA_) -#define PTW32_PROGCTR(Context) ((Context).Fir) -#endif - -#if defined(_PPC_) -#define PTW32_PROGCTR(Context) ((Context).Iar) -#endif - -#if defined(_AMD64_) || defined(__amd64__) -#define PTW32_PROGCTR(Context) ((Context).Rip) -#endif - -#if defined(_ARM_) || defined(ARM) -#define PTW32_PROGCTR(Context) ((Context).Pc) -#endif - -#if !defined(PTW32_PROGCTR) -#error Module contains CPU-specific code; modify and recompile. -#endif - -#endif diff --git a/pthreads/src/create.c b/pthreads/src/create.c deleted file mode 100644 index e154185..0000000 --- a/pthreads/src/create.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * create.c - * - * Description: - * This translation unit implements routines associated with spawning a new - * thread. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#if ! defined(_UWIN) && ! defined(WINCE) -#include -#endif - -int -pthread_create (pthread_t * tid, - const pthread_attr_t * attr, - void *(*start) (void *), void *arg) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function creates a thread running the start function, - * passing it the parameter value, 'arg'. The 'attr' - * argument specifies optional creation attributes. - * The identity of the new thread is returned - * via 'tid', which should not be NULL. - * - * PARAMETERS - * tid - * pointer to an instance of pthread_t - * - * attr - * optional pointer to an instance of pthread_attr_t - * - * start - * pointer to the starting routine for the new thread - * - * arg - * optional parameter passed to 'start' - * - * - * DESCRIPTION - * This function creates a thread running the start function, - * passing it the parameter value, 'arg'. The 'attr' - * argument specifies optional creation attributes. - * The identity of the new thread is returned - * via 'tid', which should not be the NULL pointer. - * - * RESULTS - * 0 successfully created thread, - * EINVAL attr invalid, - * EAGAIN insufficient resources. - * - * ------------------------------------------------------ - */ -{ - pthread_t thread; - ptw32_thread_t * tp; - register pthread_attr_t a; - HANDLE threadH = 0; - int result = EAGAIN; - int run = PTW32_TRUE; - ThreadParms *parms = NULL; - unsigned int stackSize; - int priority; - pthread_t self; - - /* - * Before doing anything, check that tid can be stored through - * without invoking a memory protection error (segfault). - * Make sure that the assignment below can't be optimised out by the compiler. - * This is assured by conditionally assigning *tid again at the end. - */ - tid->x = 0; - - if (attr != NULL) - { - a = *attr; - } - else - { - a = NULL; - } - - if ((thread = ptw32_new ()).p == NULL) - { - goto FAIL0; - } - - tp = (ptw32_thread_t *) thread.p; - - priority = tp->sched_priority; - - if ((parms = (ThreadParms *) malloc (sizeof (*parms))) == NULL) - { - goto FAIL0; - } - - parms->tid = thread; - parms->start = start; - parms->arg = arg; - -#if defined(HAVE_SIGSET_T) - - /* - * Threads inherit their initial sigmask from their creator thread. - */ - self = pthread_self(); - tp->sigmask = ((ptw32_thread_t *)self.p)->sigmask; - -#endif /* HAVE_SIGSET_T */ - - - if (a != NULL) - { - stackSize = (unsigned int)a->stacksize; - tp->detachState = a->detachstate; - priority = a->param.sched_priority; - -#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) - /* WinCE */ -#else - /* Everything else */ - - /* - * Thread priority must be set to a valid system level - * without altering the value set by pthread_attr_setschedparam(). - */ - - /* - * PTHREAD_EXPLICIT_SCHED is the default because Win32 threads - * don't inherit their creator's priority. They are started with - * THREAD_PRIORITY_NORMAL (win32 value). The result of not supplying - * an 'attr' arg to pthread_create() is equivalent to defaulting to - * PTHREAD_EXPLICIT_SCHED and priority THREAD_PRIORITY_NORMAL. - */ - if (PTHREAD_INHERIT_SCHED == a->inheritsched) - { - /* - * If the thread that called pthread_create() is a Win32 thread - * then the inherited priority could be the result of a temporary - * system adjustment. This is not the case for POSIX threads. - */ -#if ! defined(HAVE_SIGSET_T) - self = pthread_self (); -#endif - priority = ((ptw32_thread_t *) self.p)->sched_priority; - } - -#endif - - } - else - { - /* - * Default stackSize - */ - stackSize = PTHREAD_STACK_MIN; - } - - tp->state = run ? PThreadStateInitial : PThreadStateSuspended; - - tp->keys = NULL; - - /* - * Threads must be started in suspended mode and resumed if necessary - * after _beginthreadex returns us the handle. Otherwise we set up a - * race condition between the creating and the created threads. - * Note that we also retain a local copy of the handle for use - * by us in case thread.p->threadH gets NULLed later but before we've - * finished with it here. - */ - -#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__) - - tp->threadH = - threadH = - (HANDLE) _beginthreadex ((void *) NULL, /* No security info */ - stackSize, /* default stack size */ - ptw32_threadStart, - parms, - (unsigned) - CREATE_SUSPENDED, - (unsigned *) &(tp->thread)); - - if (threadH != 0) - { - if (a != NULL) - { - (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority); - } - - if (run) - { - ResumeThread (threadH); - } - } - -#else - - { - ptw32_mcs_local_node_t stateLock; - - /* - * This lock will force pthread_threadStart() to wait until we have - * the thread handle and have set the priority. - */ - ptw32_mcs_lock_acquire(&tp->stateLock, &stateLock); - - tp->threadH = - threadH = - (HANDLE) _beginthread (ptw32_threadStart, stackSize, /* default stack size */ - parms); - - /* - * Make the return code match _beginthreadex's. - */ - if (threadH == (HANDLE) - 1L) - { - tp->threadH = threadH = 0; - } - else - { - if (!run) - { - /* - * beginthread does not allow for create flags, so we do it now. - * Note that beginthread itself creates the thread in SUSPENDED - * mode, and then calls ResumeThread to start it. - */ - SuspendThread (threadH); - } - - if (a != NULL) - { - (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority); - } - } - - ptw32_mcs_lock_release (&stateLock); - } -#endif - - result = (threadH != 0) ? 0 : EAGAIN; - - /* - * Fall Through Intentionally - */ - - /* - * ------------ - * Failure Code - * ------------ - */ - -FAIL0: - if (result != 0) - { - - ptw32_threadDestroy (thread); - tp = NULL; - - if (parms != NULL) - { - free (parms); - } - } - else - { - *tid = thread; - } - -#if defined(_UWIN) - if (result == 0) - pthread_count++; -#endif - return (result); - -} /* pthread_create */ diff --git a/pthreads/src/dll.c b/pthreads/src/dll.c deleted file mode 100644 index 05e01be..0000000 --- a/pthreads/src/dll.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * dll.c - * - * Description: - * This translation unit implements DLL initialisation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined(PTW32_STATIC_LIB) - -#include "pthread.h" -#include "implement.h" - -#if defined(_MSC_VER) -/* - * lpvReserved yields an unreferenced formal parameter; - * ignore it - */ -#pragma warning( disable : 4100 ) -#endif - -#if defined(__cplusplus) -/* - * Dear c++: Please don't mangle this name. -thanks - */ -extern "C" -#endif /* __cplusplus */ - BOOL WINAPI -DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) -{ - BOOL result = PTW32_TRUE; - - switch (fdwReason) - { - - case DLL_PROCESS_ATTACH: - result = pthread_win32_process_attach_np (); - break; - - case DLL_THREAD_ATTACH: - /* - * A thread is being created - */ - result = pthread_win32_thread_attach_np (); - break; - - case DLL_THREAD_DETACH: - /* - * A thread is exiting cleanly - */ - result = pthread_win32_thread_detach_np (); - break; - - case DLL_PROCESS_DETACH: - (void) pthread_win32_thread_detach_np (); - result = pthread_win32_process_detach_np (); - break; - } - - return (result); - -} /* DllMain */ - -#endif /* PTW32_STATIC_LIB */ diff --git a/pthreads/src/errno.c b/pthreads/src/errno.c deleted file mode 100644 index 78aa920..0000000 --- a/pthreads/src/errno.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * errno.c - * - * Description: - * This translation unit implements routines associated with spawning a new - * thread. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if defined(NEED_ERRNO) - -#include "pthread.h" -#include "implement.h" - -static int reallyBad = ENOMEM; - -/* - * Re-entrant errno. - * - * Each thread has it's own errno variable in pthread_t. - * - * The benefit of using the pthread_t structure - * instead of another TSD key is TSD keys are limited - * on Win32 to 64 per process. Secondly, to implement - * it properly without using pthread_t you'd need - * to dynamically allocate an int on starting the thread - * and store it manually into TLS and then ensure that you free - * it on thread termination. We get all that for free - * by simply storing the errno on the pthread_t structure. - * - * MSVC and Mingw32 already have their own thread-safe errno. - * - * #if defined( _REENTRANT ) || defined( _MT ) - * #define errno *_errno() - * - * int *_errno( void ); - * #else - * extern int errno; - * #endif - * - */ - -int * -_errno (void) -{ - pthread_t self; - int *result; - - if ((self = pthread_self ()).p == NULL) - { - /* - * Yikes! unable to allocate a thread! - * Throw an exception? return an error? - */ - result = &reallyBad; - } - else - { - result = (int *)(&self.p->exitStatus); - } - - return (result); - -} /* _errno */ - -#endif /* (NEED_ERRNO) */ diff --git a/pthreads/src/exit.c b/pthreads/src/exit.c deleted file mode 100644 index 94369d0..0000000 --- a/pthreads/src/exit.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * exit.c - * - * Description: - * This translation unit implements routines associated with exiting from - * a thread. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#if ! defined(_UWIN) && ! defined(WINCE) -# include -#endif - -#include "pthread_exit.c" diff --git a/pthreads/src/fork.c b/pthreads/src/fork.c deleted file mode 100644 index 8a29550..0000000 --- a/pthreads/src/fork.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * fork.c - * - * Description: - * Implementation of fork() for POSIX threads. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - - -#include "pthread.h" -#include "implement.h" diff --git a/pthreads/src/global.c b/pthreads/src/global.c deleted file mode 100644 index f1e9b3f..0000000 --- a/pthreads/src/global.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * global.c - * - * Description: - * This translation unit instantiates data associated with the implementation - * as a whole. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int ptw32_processInitialized = PTW32_FALSE; -ptw32_thread_t * ptw32_threadReuseTop = PTW32_THREAD_REUSE_EMPTY; -ptw32_thread_t * ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY; -pthread_key_t ptw32_selfThreadKey = NULL; -pthread_key_t ptw32_cleanupKey = NULL; -pthread_cond_t ptw32_cond_list_head = NULL; -pthread_cond_t ptw32_cond_list_tail = NULL; - -int ptw32_concurrency = 0; - -/* What features have been auto-detected */ -int ptw32_features = 0; - -/* - * Global [process wide] thread sequence Number - */ -unsigned __int64 ptw32_threadSeqNumber = 0; - -/* - * Function pointer to QueueUserAPCEx if it exists, otherwise - * it will be set at runtime to a substitute routine which cannot unblock - * blocked threads. - */ -DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD) = NULL; - -/* - * Global lock for managing pthread_t struct reuse. - */ -ptw32_mcs_lock_t ptw32_thread_reuse_lock = 0; - -/* - * Global lock for testing internal state of statically declared mutexes. - */ -ptw32_mcs_lock_t ptw32_mutex_test_init_lock = 0; - -/* - * Global lock for testing internal state of PTHREAD_COND_INITIALIZER - * created condition variables. - */ -ptw32_mcs_lock_t ptw32_cond_test_init_lock = 0; - -/* - * Global lock for testing internal state of PTHREAD_RWLOCK_INITIALIZER - * created read/write locks. - */ -ptw32_mcs_lock_t ptw32_rwlock_test_init_lock = 0; - -/* - * Global lock for testing internal state of PTHREAD_SPINLOCK_INITIALIZER - * created spin locks. - */ -ptw32_mcs_lock_t ptw32_spinlock_test_init_lock = 0; - -/* - * Global lock for condition variable linked list. The list exists - * to wake up CVs when a WM_TIMECHANGE message arrives. See - * w32_TimeChangeHandler.c. - */ -ptw32_mcs_lock_t ptw32_cond_list_lock = 0; - -#if defined(_UWIN) -/* - * Keep a count of the number of threads. - */ -int pthread_count = 0; -#endif diff --git a/pthreads/src/implement.h b/pthreads/src/implement.h deleted file mode 100644 index 6b9f425..0000000 --- a/pthreads/src/implement.h +++ /dev/null @@ -1,943 +0,0 @@ -/* - * implement.h - * - * Definitions that don't need to be public. - * - * Keeps all the internals out of pthread.h - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: Ross.Johnson@homemail.com.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined(_IMPLEMENT_H) -#define _IMPLEMENT_H - -#if !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0400 -#endif - -#include - -/* - * In case windows.h doesn't define it (e.g. WinCE perhaps) - */ -#if defined(WINCE) -typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam); -#endif - -/* - * note: ETIMEDOUT is correctly defined in winsock.h - */ -#include - -/* - * In case ETIMEDOUT hasn't been defined above somehow. - */ -#if !defined(ETIMEDOUT) -# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ -#endif - -#if !defined(malloc) -#include -#endif - -#if defined(__CLEANUP_C) -# include -#endif - -#if !defined(INT_MAX) -#include -#endif - -/* use local include files during development */ -#include "semaphore.h" -#include "sched.h" - -#if defined(HAVE_C_INLINE) || defined(__cplusplus) -#define INLINE inline -#else -#define INLINE -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1300 -/* - * MSVC 6 does not use the "volatile" qualifier - */ -#define PTW32_INTERLOCKED_VOLATILE -#else -#define PTW32_INTERLOCKED_VOLATILE volatile -#endif -#define PTW32_INTERLOCKED_LONG long -#define PTW32_INTERLOCKED_SIZE size_t -#define PTW32_INTERLOCKED_PVOID PVOID -#define PTW32_INTERLOCKED_LONGPTR PTW32_INTERLOCKED_VOLATILE long* -#define PTW32_INTERLOCKED_SIZEPTR PTW32_INTERLOCKED_VOLATILE size_t* -#define PTW32_INTERLOCKED_PVOID_PTR PTW32_INTERLOCKED_VOLATILE PVOID* - -#if defined(__MINGW64__) || defined(__MINGW32__) -# include -#elif defined(__BORLANDC__) -# define int64_t ULONGLONG -#else -# define int64_t _int64 -# if defined(_MSC_VER) && _MSC_VER < 1300 - typedef long intptr_t; -# endif -#endif - -typedef enum -{ - /* - * This enumeration represents the state of the thread; - * The thread is still "alive" if the numeric value of the - * state is greater or equal "PThreadStateRunning". - */ - PThreadStateInitial = 0, /* Thread not running */ - PThreadStateRunning, /* Thread alive & kicking */ - PThreadStateSuspended, /* Thread alive but suspended */ - PThreadStateCancelPending, /* Thread alive but */ - /* has cancelation pending. */ - PThreadStateCanceling, /* Thread alive but is */ - /* in the process of terminating */ - /* due to a cancellation request */ - PThreadStateExiting, /* Thread alive but exiting */ - /* due to an exception */ - PThreadStateLast, /* All handlers have been run and now */ - /* final cleanup can be done. */ - PThreadStateReuse /* In reuse pool. */ -} -PThreadState; - -typedef struct ptw32_mcs_node_t_ ptw32_mcs_local_node_t; -typedef struct ptw32_mcs_node_t_* ptw32_mcs_lock_t; -typedef struct ptw32_robust_node_t_ ptw32_robust_node_t; -typedef struct ptw32_thread_t_ ptw32_thread_t; - - -struct ptw32_thread_t_ -{ - unsigned __int64 seqNumber; /* Process-unique thread sequence number */ - HANDLE threadH; /* Win32 thread handle - POSIX thread is invalid if threadH == 0 */ - pthread_t ptHandle; /* This thread's permanent pthread_t handle */ - ptw32_thread_t * prevReuse; /* Links threads on reuse stack */ - volatile PThreadState state; - ptw32_mcs_lock_t threadLock; /* Used for serialised access to public thread state */ - ptw32_mcs_lock_t stateLock; /* Used for async-cancel safety */ - HANDLE cancelEvent; - void *exitStatus; - void *parms; - void *keys; - void *nextAssoc; -#if defined(__CLEANUP_C) - jmp_buf start_mark; /* Jump buffer follows void* so should be aligned */ -#endif /* __CLEANUP_C */ -#if defined(HAVE_SIGSET_T) - sigset_t sigmask; -#endif /* HAVE_SIGSET_T */ - ptw32_mcs_lock_t - robustMxListLock; /* robustMxList lock */ - ptw32_robust_node_t* - robustMxList; /* List of currenty held robust mutexes */ - int ptErrno; - int detachState; - int sched_priority; /* As set, not as currently is */ - int cancelState; - int cancelType; - int implicit:1; - DWORD thread; /* Win32 thread ID */ -#if defined(_UWIN) - DWORD dummy[5]; -#endif - size_t align; /* Force alignment if this struct is packed */ -}; - - -/* - * Special value to mark attribute objects as valid. - */ -#define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE) - -struct pthread_attr_t_ -{ - unsigned long valid; - void *stackaddr; - size_t stacksize; - int detachstate; - struct sched_param param; - int inheritsched; - int contentionscope; -#if defined(HAVE_SIGSET_T) - sigset_t sigmask; -#endif /* HAVE_SIGSET_T */ -}; - - -/* - * ==================== - * ==================== - * Semaphores, Mutexes and Condition Variables - * ==================== - * ==================== - */ - -struct sem_t_ -{ - int value; - pthread_mutex_t lock; - HANDLE sem; -#if defined(NEED_SEM) - int leftToUnblock; -#endif -}; - -#define PTW32_OBJECT_AUTO_INIT ((void *)(size_t) -1) -#define PTW32_OBJECT_INVALID NULL - -struct pthread_mutex_t_ -{ - LONG lock_idx; /* Provides exclusive access to mutex state - via the Interlocked* mechanism. - 0: unlocked/free. - 1: locked - no other waiters. - -1: locked - with possible other waiters. - */ - int recursive_count; /* Number of unlocks a thread needs to perform - before the lock is released (recursive - mutexes only). */ - int kind; /* Mutex type. */ - pthread_t ownerThread; - HANDLE event; /* Mutex release notification to waiting - threads. */ - ptw32_robust_node_t* - robustNode; /* Extra state for robust mutexes */ -}; - -enum ptw32_robust_state_t_ -{ - PTW32_ROBUST_CONSISTENT, - PTW32_ROBUST_INCONSISTENT, - PTW32_ROBUST_NOTRECOVERABLE -}; - -typedef enum ptw32_robust_state_t_ ptw32_robust_state_t; - -/* - * Node used to manage per-thread lists of currently-held robust mutexes. - */ -struct ptw32_robust_node_t_ -{ - pthread_mutex_t mx; - ptw32_robust_state_t stateInconsistent; - ptw32_robust_node_t* prev; - ptw32_robust_node_t* next; -}; - -struct pthread_mutexattr_t_ -{ - int pshared; - int kind; - int robustness; -}; - -/* - * Possible values, other than PTW32_OBJECT_INVALID, - * for the "interlock" element in a spinlock. - * - * In this implementation, when a spinlock is initialised, - * the number of cpus available to the process is checked. - * If there is only one cpu then "interlock" is set equal to - * PTW32_SPIN_USE_MUTEX and u.mutex is an initialised mutex. - * If the number of cpus is greater than 1 then "interlock" - * is set equal to PTW32_SPIN_UNLOCKED and the number is - * stored in u.cpus. This arrangement allows the spinlock - * routines to attempt an InterlockedCompareExchange on "interlock" - * immediately and, if that fails, to try the inferior mutex. - * - * "u.cpus" isn't used for anything yet, but could be used at - * some point to optimise spinlock behaviour. - */ -#define PTW32_SPIN_INVALID (0) -#define PTW32_SPIN_UNLOCKED (1) -#define PTW32_SPIN_LOCKED (2) -#define PTW32_SPIN_USE_MUTEX (3) - -struct pthread_spinlock_t_ -{ - long interlock; /* Locking element for multi-cpus. */ - union - { - int cpus; /* No. of cpus if multi cpus, or */ - pthread_mutex_t mutex; /* mutex if single cpu. */ - } u; -}; - -/* - * MCS lock queue node - see ptw32_MCS_lock.c - */ -struct ptw32_mcs_node_t_ -{ - struct ptw32_mcs_node_t_ **lock; /* ptr to tail of queue */ - struct ptw32_mcs_node_t_ *next; /* ptr to successor in queue */ - HANDLE readyFlag; /* set after lock is released by - predecessor */ - HANDLE nextFlag; /* set after 'next' ptr is set by - successor */ -}; - - -struct pthread_barrier_t_ -{ - unsigned int nCurrentBarrierHeight; - unsigned int nInitialBarrierHeight; - int pshared; - sem_t semBarrierBreeched; - ptw32_mcs_lock_t lock; - ptw32_mcs_local_node_t proxynode; -}; - -struct pthread_barrierattr_t_ -{ - int pshared; -}; - -struct pthread_key_t_ -{ - DWORD key; - void (*destructor) (void *); - ptw32_mcs_lock_t keyLock; - void *threads; -}; - - -typedef struct ThreadParms ThreadParms; - -struct ThreadParms -{ - pthread_t tid; - void *(*start) (void *); - void *arg; -}; - - -struct pthread_cond_t_ -{ - long nWaitersBlocked; /* Number of threads blocked */ - long nWaitersGone; /* Number of threads timed out */ - long nWaitersToUnblock; /* Number of threads to unblock */ - sem_t semBlockQueue; /* Queue up threads waiting for the */ - /* condition to become signalled */ - sem_t semBlockLock; /* Semaphore that guards access to */ - /* | waiters blocked count/block queue */ - /* +-> Mandatory Sync.LEVEL-1 */ - pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */ - /* | waiters (to)unblock(ed) counts */ - /* +-> Optional* Sync.LEVEL-2 */ - pthread_cond_t next; /* Doubly linked list */ - pthread_cond_t prev; -}; - - -struct pthread_condattr_t_ -{ - int pshared; -}; - -#define PTW32_RWLOCK_MAGIC 0xfacade2 - -struct pthread_rwlock_t_ -{ - pthread_mutex_t mtxExclusiveAccess; - pthread_mutex_t mtxSharedAccessCompleted; - pthread_cond_t cndSharedAccessCompleted; - int nSharedAccessCount; - int nExclusiveAccessCount; - int nCompletedSharedAccessCount; - int nMagic; -}; - -struct pthread_rwlockattr_t_ -{ - int pshared; -}; - -typedef struct ThreadKeyAssoc ThreadKeyAssoc; - -struct ThreadKeyAssoc -{ - /* - * Purpose: - * This structure creates an association between a thread and a key. - * It is used to implement the implicit invocation of a user defined - * destroy routine for thread specific data registered by a user upon - * exiting a thread. - * - * Graphically, the arrangement is as follows, where: - * - * K - Key with destructor - * (head of chain is key->threads) - * T - Thread that has called pthread_setspecific(Kn) - * (head of chain is thread->keys) - * A - Association. Each association is a node at the - * intersection of two doubly-linked lists. - * - * T1 T2 T3 - * | | | - * | | | - * K1 -----+-----A-----A-----> - * | | | - * | | | - * K2 -----A-----A-----+-----> - * | | | - * | | | - * K3 -----A-----+-----A-----> - * | | | - * | | | - * V V V - * - * Access to the association is guarded by two locks: the key's - * general lock (guarding the row) and the thread's general - * lock (guarding the column). This avoids the need for a - * dedicated lock for each association, which not only consumes - * more handles but requires that the lock resources persist - * until both the key is deleted and the thread has called the - * destructor. The two-lock arrangement allows those resources - * to be freed as soon as either thread or key is concluded. - * - * To avoid deadlock, whenever both locks are required both the - * key and thread locks are acquired consistently in the order - * "key lock then thread lock". An exception to this exists - * when a thread calls the destructors, however, this is done - * carefully (but inelegantly) to avoid deadlock. - * - * An association is created when a thread first calls - * pthread_setspecific() on a key that has a specified - * destructor. - * - * An association is destroyed either immediately after the - * thread calls the key destructor function on thread exit, or - * when the key is deleted. - * - * Attributes: - * thread - * reference to the thread that owns the - * association. This is actually the pointer to the - * thread struct itself. Since the association is - * destroyed before the thread exits, this can never - * point to a different logical thread to the one that - * created the assoc, i.e. after thread struct reuse. - * - * key - * reference to the key that owns the association. - * - * nextKey - * The pthread_t->keys attribute is the head of a - * chain of associations that runs through the nextKey - * link. This chain provides the 1 to many relationship - * between a pthread_t and all pthread_key_t on which - * it called pthread_setspecific. - * - * prevKey - * Similarly. - * - * nextThread - * The pthread_key_t->threads attribute is the head of - * a chain of associations that runs through the - * nextThreads link. This chain provides the 1 to many - * relationship between a pthread_key_t and all the - * PThreads that have called pthread_setspecific for - * this pthread_key_t. - * - * prevThread - * Similarly. - * - * Notes: - * 1) As soon as either the key or the thread is no longer - * referencing the association, it can be destroyed. The - * association will be removed from both chains. - * - * 2) Under WIN32, an association is only created by - * pthread_setspecific if the user provided a - * destroyRoutine when they created the key. - * - * - */ - ptw32_thread_t * thread; - pthread_key_t key; - ThreadKeyAssoc *nextKey; - ThreadKeyAssoc *nextThread; - ThreadKeyAssoc *prevKey; - ThreadKeyAssoc *prevThread; -}; - - -#if defined(__CLEANUP_SEH) -/* - * -------------------------------------------------------------- - * MAKE_SOFTWARE_EXCEPTION - * This macro constructs a software exception code following - * the same format as the standard Win32 error codes as defined - * in WINERROR.H - * Values are 32 bit values laid out as follows: - * - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +---+-+-+-----------------------+-------------------------------+ - * |Sev|C|R| Facility | Code | - * +---+-+-+-----------------------+-------------------------------+ - * - * Severity Values: - */ -#define SE_SUCCESS 0x00 -#define SE_INFORMATION 0x01 -#define SE_WARNING 0x02 -#define SE_ERROR 0x03 - -#define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \ -( (DWORD) ( ( (_severity) << 30 ) | /* Severity code */ \ - ( 1 << 29 ) | /* MS=0, User=1 */ \ - ( 0 << 28 ) | /* Reserved */ \ - ( (_facility) << 16 ) | /* Facility Code */ \ - ( (_exception) << 0 ) /* Exception Code */ \ - ) ) - -/* - * We choose one specific Facility/Error code combination to - * identify our software exceptions vs. WIN32 exceptions. - * We store our actual component and error code within - * the optional information array. - */ -#define EXCEPTION_PTW32_SERVICES \ - MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \ - PTW32_SERVICES_FACILITY, \ - PTW32_SERVICES_ERROR ) - -#define PTW32_SERVICES_FACILITY 0xBAD -#define PTW32_SERVICES_ERROR 0xDEED - -#endif /* __CLEANUP_SEH */ - -/* - * Services available through EXCEPTION_PTW32_SERVICES - * and also used [as parameters to ptw32_throw()] as - * generic exception selectors. - */ - -#define PTW32_EPS_EXIT (1) -#define PTW32_EPS_CANCEL (2) - - -/* Useful macros */ -#define PTW32_MAX(a,b) ((a)<(b)?(b):(a)) -#define PTW32_MIN(a,b) ((a)>(b)?(b):(a)) - - -/* Declared in pthread_cancel.c */ -extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD); - -/* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */ -#define PTW32_THREAD_REUSE_EMPTY ((ptw32_thread_t *)(size_t) 1) - -extern int ptw32_processInitialized; -extern ptw32_thread_t * ptw32_threadReuseTop; -extern ptw32_thread_t * ptw32_threadReuseBottom; -extern pthread_key_t ptw32_selfThreadKey; -extern pthread_key_t ptw32_cleanupKey; -extern pthread_cond_t ptw32_cond_list_head; -extern pthread_cond_t ptw32_cond_list_tail; - -extern int ptw32_mutex_default_kind; - -extern unsigned __int64 ptw32_threadSeqNumber; - -extern int ptw32_concurrency; - -extern int ptw32_features; - -extern ptw32_mcs_lock_t ptw32_thread_reuse_lock; -extern ptw32_mcs_lock_t ptw32_mutex_test_init_lock; -extern ptw32_mcs_lock_t ptw32_cond_list_lock; -extern ptw32_mcs_lock_t ptw32_cond_test_init_lock; -extern ptw32_mcs_lock_t ptw32_rwlock_test_init_lock; -extern ptw32_mcs_lock_t ptw32_spinlock_test_init_lock; - -#if defined(_UWIN) -extern int pthread_count; -#endif - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -/* - * ===================== - * ===================== - * Forward Declarations - * ===================== - * ===================== - */ - - int ptw32_is_attr (const pthread_attr_t * attr); - - int ptw32_cond_check_need_init (pthread_cond_t * cond); - int ptw32_mutex_check_need_init (pthread_mutex_t * mutex); - int ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock); - - int ptw32_robust_mutex_inherit(pthread_mutex_t * mutex); - void ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self); - void ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp); - - DWORD - ptw32_RegisterCancelation (PAPCFUNC callback, - HANDLE threadH, DWORD callback_arg); - - int ptw32_processInitialize (void); - - void ptw32_processTerminate (void); - - void ptw32_threadDestroy (pthread_t tid); - - void ptw32_pop_cleanup_all (int execute); - - pthread_t ptw32_new (void); - - pthread_t ptw32_threadReusePop (void); - - void ptw32_threadReusePush (pthread_t thread); - - int ptw32_getprocessors (int *count); - - int ptw32_setthreadpriority (pthread_t thread, int policy, int priority); - - void ptw32_rwlock_cancelwrwait (void *arg); - -#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || (defined(__MSVCRT__) && ! defined(__DMC__)) - unsigned __stdcall -#else - void -#endif - ptw32_threadStart (void *vthreadParms); - - void ptw32_callUserDestroyRoutines (pthread_t thread); - - int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key); - - void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc); - - int ptw32_semwait (sem_t * sem); - - DWORD ptw32_relmillisecs (const struct timespec * abstime); - - void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node); - - int ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node); - - void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node); - - void ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node); - -#if defined(NEED_FTIME) - void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft); - void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts); -#endif - -/* Declared in misc.c */ -#if defined(NEED_CALLOC) -#define calloc(n, s) ptw32_calloc(n, s) - void *ptw32_calloc (size_t n, size_t s); -#endif - -/* Declared in private.c */ -#if defined(_MSC_VER) -/* - * Ignore the warning: - * "C++ exception specification ignored except to indicate that - * the function is not __declspec(nothrow)." - */ -#pragma warning(disable:4290) -#endif - void ptw32_throw (DWORD exception) -#if defined(__CLEANUP_CXX) - throw(ptw32_exception_cancel,ptw32_exception_exit) -#endif -; - -#if defined(__cplusplus) -} -#endif /* __cplusplus */ - - -#if defined(_UWIN_) -# if defined(_MT) -# if defined(__cplusplus) -extern "C" -{ -# endif - _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *), - unsigned, void *); - _CRTIMP void __cdecl _endthread (void); - _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned, - unsigned (__stdcall *) (void *), - void *, unsigned, unsigned *); - _CRTIMP void __cdecl _endthreadex (unsigned); -# if defined(__cplusplus) -} -# endif -# endif -#else -# include -# endif - - -/* - * Use intrinsic versions wherever possible. VC will do this - * automatically where possible and GCC define these if available: - * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 - * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 - * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 - * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 - * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 - * - * The full set of Interlocked intrinsics in GCC are (check versions): - * type __sync_fetch_and_add (type *ptr, type value, ...) - * type __sync_fetch_and_sub (type *ptr, type value, ...) - * type __sync_fetch_and_or (type *ptr, type value, ...) - * type __sync_fetch_and_and (type *ptr, type value, ...) - * type __sync_fetch_and_xor (type *ptr, type value, ...) - * type __sync_fetch_and_nand (type *ptr, type value, ...) - * type __sync_add_and_fetch (type *ptr, type value, ...) - * type __sync_sub_and_fetch (type *ptr, type value, ...) - * type __sync_or_and_fetch (type *ptr, type value, ...) - * type __sync_and_and_fetch (type *ptr, type value, ...) - * type __sync_xor_and_fetch (type *ptr, type value, ...) - * type __sync_nand_and_fetch (type *ptr, type value, ...) - * bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...) - * type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...) - * __sync_synchronize (...) // Full memory barrier - * type __sync_lock_test_and_set (type *ptr, type value, ...) // Acquire barrier - * void __sync_lock_release (type *ptr, ...) // Release barrier - * - * These are all overloaded and take 1,2,4,8 byte scalar or pointer types. - * - * The above aren't available in Mingw32 as of gcc 4.5.2 so define our own. - */ -#if defined(__GNUC__) -# if defined(_WIN64) -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_64(location, value, comparand) \ - ({ \ - __typeof (value) _result; \ - __asm__ __volatile__ \ - ( \ - "lock\n\t" \ - "cmpxchgq %2,(%1)" \ - :"=a" (_result) \ - :"r" (location), "r" (value), "a" (comparand) \ - :"memory", "cc"); \ - _result; \ - }) -# define PTW32_INTERLOCKED_EXCHANGE_64(location, value) \ - ({ \ - __typeof (value) _result; \ - __asm__ __volatile__ \ - ( \ - "xchgq %0,(%1)" \ - :"=r" (_result) \ - :"r" (location), "0" (value) \ - :"memory", "cc"); \ - _result; \ - }) -# define PTW32_INTERLOCKED_EXCHANGE_ADD_64(location, value) \ - ({ \ - __typeof (value) _result; \ - __asm__ __volatile__ \ - ( \ - "lock\n\t" \ - "xaddq %0,(%1)" \ - :"=r" (_result) \ - :"r" (location), "0" (value) \ - :"memory", "cc"); \ - _result; \ - }) -# define PTW32_INTERLOCKED_INCREMENT_64(location) \ - ({ \ - PTW32_INTERLOCKED_LONG _temp = 1; \ - __asm__ __volatile__ \ - ( \ - "lock\n\t" \ - "xaddq %0,(%1)" \ - :"+r" (_temp) \ - :"r" (location) \ - :"memory", "cc"); \ - ++_temp; \ - }) -# define PTW32_INTERLOCKED_DECREMENT_64(location) \ - ({ \ - PTW32_INTERLOCKED_LONG _temp = -1; \ - __asm__ __volatile__ \ - ( \ - "lock\n\t" \ - "xaddq %2,(%1)" \ - :"+r" (_temp) \ - :"r" (location) \ - :"memory", "cc"); \ - --_temp; \ - }) -#endif -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \ - ({ \ - __typeof (value) _result; \ - __asm__ __volatile__ \ - ( \ - "lock\n\t" \ - "cmpxchgl %2,(%1)" \ - :"=a" (_result) \ - :"r" (location), "r" (value), "a" (comparand) \ - :"memory", "cc"); \ - _result; \ - }) -# define PTW32_INTERLOCKED_EXCHANGE_LONG(location, value) \ - ({ \ - __typeof (value) _result; \ - __asm__ __volatile__ \ - ( \ - "xchgl %0,(%1)" \ - :"=r" (_result) \ - :"r" (location), "0" (value) \ - :"memory", "cc"); \ - _result; \ - }) -# define PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(location, value) \ - ({ \ - __typeof (value) _result; \ - __asm__ __volatile__ \ - ( \ - "lock\n\t" \ - "xaddl %0,(%1)" \ - :"=r" (_result) \ - :"r" (location), "0" (value) \ - :"memory", "cc"); \ - _result; \ - }) -# define PTW32_INTERLOCKED_INCREMENT_LONG(location) \ - ({ \ - PTW32_INTERLOCKED_LONG _temp = 1; \ - __asm__ __volatile__ \ - ( \ - "lock\n\t" \ - "xaddl %0,(%1)" \ - :"+r" (_temp) \ - :"r" (location) \ - :"memory", "cc"); \ - ++_temp; \ - }) -# define PTW32_INTERLOCKED_DECREMENT_LONG(location) \ - ({ \ - PTW32_INTERLOCKED_LONG _temp = -1; \ - __asm__ __volatile__ \ - ( \ - "lock\n\t" \ - "xaddl %0,(%1)" \ - :"+r" (_temp) \ - :"r" (location) \ - :"memory", "cc"); \ - --_temp; \ - }) -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(location, value, comparand) \ - PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE((PTW32_INTERLOCKED_SIZEPTR)location, \ - (PTW32_INTERLOCKED_SIZE)value, \ - (PTW32_INTERLOCKED_SIZE)comparand) -# define PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \ - PTW32_INTERLOCKED_EXCHANGE_SIZE((PTW32_INTERLOCKED_SIZEPTR)location, \ - (PTW32_INTERLOCKED_SIZE)value) -#else -# if defined(_WIN64) -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_64 InterlockedCompareExchange64 -# define PTW32_INTERLOCKED_EXCHANGE_64 InterlockedExchange64 -# define PTW32_INTERLOCKED_EXCHANGE_ADD_64 InterlockedExchangeAdd64 -# define PTW32_INTERLOCKED_INCREMENT_64 InterlockedIncrement64 -# define PTW32_INTERLOCKED_DECREMENT_64 InterlockedDecrement64 -# endif -# if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(_WIN64) /* MSVC 6 */ -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \ - ((LONG)InterlockedCompareExchange((PVOID *)(location), (PVOID)(value), (PVOID)(comparand))) -# else -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG InterlockedCompareExchange -# endif -# define PTW32_INTERLOCKED_EXCHANGE_LONG InterlockedExchange -# define PTW32_INTERLOCKED_EXCHANGE_ADD_LONG InterlockedExchangeAdd -# define PTW32_INTERLOCKED_INCREMENT_LONG InterlockedIncrement -# define PTW32_INTERLOCKED_DECREMENT_LONG InterlockedDecrement -# if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(_WIN64) /* MSVC 6 */ -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchange -# define PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \ - ((PVOID)InterlockedExchange((LPLONG)(location), (LONG)(value))) -# else -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchangePointer -# define PTW32_INTERLOCKED_EXCHANGE_PTR InterlockedExchangePointer -# endif -#endif -#if defined(_WIN64) -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE PTW32_INTERLOCKED_COMPARE_EXCHANGE_64 -# define PTW32_INTERLOCKED_EXCHANGE_SIZE PTW32_INTERLOCKED_EXCHANGE_64 -# define PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE PTW32_INTERLOCKED_EXCHANGE_ADD_64 -# define PTW32_INTERLOCKED_INCREMENT_SIZE PTW32_INTERLOCKED_INCREMENT_64 -# define PTW32_INTERLOCKED_DECREMENT_SIZE PTW32_INTERLOCKED_DECREMENT_64 -#else -# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG -# define PTW32_INTERLOCKED_EXCHANGE_SIZE PTW32_INTERLOCKED_EXCHANGE_LONG -# define PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE PTW32_INTERLOCKED_EXCHANGE_ADD_LONG -# define PTW32_INTERLOCKED_INCREMENT_SIZE PTW32_INTERLOCKED_INCREMENT_LONG -# define PTW32_INTERLOCKED_DECREMENT_SIZE PTW32_INTERLOCKED_DECREMENT_LONG -#endif - -#if defined(NEED_CREATETHREAD) - -/* - * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE - * in order to avoid warnings because of return type - */ - -#define _beginthreadex(security, \ - stack_size, \ - start_proc, \ - arg, \ - flags, \ - pid) \ - CreateThread(security, \ - stack_size, \ - (LPTHREAD_START_ROUTINE) start_proc, \ - arg, \ - flags, \ - pid) - -#define _endthreadex ExitThread - -#endif /* NEED_CREATETHREAD */ - - -#endif /* _IMPLEMENT_H */ diff --git a/pthreads/src/misc.c b/pthreads/src/misc.c deleted file mode 100644 index 9c2e6c5..0000000 --- a/pthreads/src/misc.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * misc.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -#include "pthread_kill.c" -#include "pthread_once.c" -#include "pthread_self.c" -#include "pthread_equal.c" -#include "pthread_setconcurrency.c" -#include "pthread_getconcurrency.c" -#include "ptw32_new.c" -#include "ptw32_calloc.c" -#include "ptw32_MCS_lock.c" -#include "ptw32_relmillisecs.c" -#include "ptw32_reuse.c" -#include "w32_CancelableWait.c" diff --git a/pthreads/src/mutex.c b/pthreads/src/mutex.c deleted file mode 100644 index c2b3607..0000000 --- a/pthreads/src/mutex.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * mutex.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if ! defined(_UWIN) && ! defined(WINCE) -# include -#endif -#if !defined(NEED_FTIME) -#include -#endif -#include "pthread.h" -#include "implement.h" - - -#include "ptw32_mutex_check_need_init.c" -#include "pthread_mutex_init.c" -#include "pthread_mutex_destroy.c" -#include "pthread_mutexattr_init.c" -#include "pthread_mutexattr_destroy.c" -#include "pthread_mutexattr_getpshared.c" -#include "pthread_mutexattr_setpshared.c" -#include "pthread_mutexattr_settype.c" -#include "pthread_mutexattr_gettype.c" -#include "pthread_mutexattr_setrobust.c" -#include "pthread_mutexattr_getrobust.c" -#include "pthread_mutex_lock.c" -#include "pthread_mutex_timedlock.c" -#include "pthread_mutex_unlock.c" -#include "pthread_mutex_trylock.c" -#include "pthread_mutex_consistent.c" diff --git a/pthreads/src/need_errno.h b/pthreads/src/need_errno.h deleted file mode 100644 index abf1c95..0000000 --- a/pthreads/src/need_errno.h +++ /dev/null @@ -1,145 +0,0 @@ -/*** -* errno.h - system wide error numbers (set by system calls) -* -* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved. -* -* Purpose: -* This file defines the system-wide error numbers (set by -* system calls). Conforms to the XENIX standard. Extended -* for compatibility with Uniforum standard. -* [System V] -* -* [Public] -* -****/ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#if !defined(_INC_ERRNO) -#define _INC_ERRNO - -#if !defined(_WIN32) -#error ERROR: Only Win32 targets supported! -#endif - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - - - -/* Define _CRTIMP */ - -#ifndef _CRTIMP -#if defined(_DLL) -#define _CRTIMP __declspec(dllimport) -#else /* ndef _DLL */ -#define _CRTIMP -#endif /* _DLL */ -#endif /* _CRTIMP */ - - -/* Define __cdecl for non-Microsoft compilers */ - -#if ( !defined(_MSC_VER) && !defined(__cdecl) ) -#define __cdecl -#endif - -/* Define _CRTAPI1 (for compatibility with the NT SDK) */ - -#if !defined(_CRTAPI1) -#if _MSC_VER >= 800 && _M_IX86 >= 300 -#define _CRTAPI1 __cdecl -#else -#define _CRTAPI1 -#endif -#endif - -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* declare reference to errno */ - -#if (defined(_MT) || defined(_MD) || defined(_DLL)) && !defined(_MAC) -PTW32_DLLPORT int * __cdecl _errno(void); -#define errno (*_errno()) -#else /* ndef _MT && ndef _MD && ndef _DLL */ -_CRTIMP extern int errno; -#endif /* _MT || _MD || _DLL */ - -/* Error Codes */ - -#define EPERM 1 -#define ENOENT 2 -#define ESRCH 3 -#define EINTR 4 -#define EIO 5 -#define ENXIO 6 -#define E2BIG 7 -#define ENOEXEC 8 -#define EBADF 9 -#define ECHILD 10 -#define EAGAIN 11 -#define ENOMEM 12 -#define EACCES 13 -#define EFAULT 14 -#define EBUSY 16 -#define EEXIST 17 -#define EXDEV 18 -#define ENODEV 19 -#define ENOTDIR 20 -#define EISDIR 21 -#define EINVAL 22 -#define ENFILE 23 -#define EMFILE 24 -#define ENOTTY 25 -#define EFBIG 27 -#define ENOSPC 28 -#define ESPIPE 29 -#define EROFS 30 -#define EMLINK 31 -#define EPIPE 32 -#define EDOM 33 -#define ERANGE 34 -#define EDEADLK 36 - -/* defined differently in winsock.h on WinCE */ -#if !defined(ENAMETOOLONG) -#define ENAMETOOLONG 38 -#endif - -#define ENOLCK 39 -#define ENOSYS 40 - -/* defined differently in winsock.h on WinCE */ -#if !defined(ENOTEMPTY) -#define ENOTEMPTY 41 -#endif - -#define EILSEQ 42 - -/* POSIX 2008 - robust mutexes */ -#define EOWNERDEAD 43 -#define ENOTRECOVERABLE 44 - -/* - * Support EDEADLOCK for compatibiity with older MS-C versions. - */ -#define EDEADLOCK EDEADLK - -#if defined(__cplusplus) -} -#endif - -#endif /* _INC_ERRNO */ diff --git a/pthreads/src/nonportable.c b/pthreads/src/nonportable.c deleted file mode 100644 index 742cb96..0000000 --- a/pthreads/src/nonportable.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * nonportable.c - * - * Description: - * This translation unit implements non-portable thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -#include "pthread_mutexattr_setkind_np.c" -#include "pthread_mutexattr_getkind_np.c" -#include "pthread_getw32threadhandle_np.c" -#include "pthread_getunique_np.c" -#include "pthread_delay_np.c" -#include "pthread_num_processors_np.c" -#include "pthread_win32_attach_detach_np.c" -#include "pthread_timechange_handler_np.c" diff --git a/pthreads/src/private.c b/pthreads/src/private.c deleted file mode 100644 index a16b776..0000000 --- a/pthreads/src/private.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * private.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -#include "ptw32_is_attr.c" -#include "ptw32_processInitialize.c" -#include "ptw32_processTerminate.c" -#include "ptw32_threadStart.c" -#include "ptw32_threadDestroy.c" -#include "ptw32_tkAssocCreate.c" -#include "ptw32_tkAssocDestroy.c" -#include "ptw32_callUserDestroyRoutines.c" -#include "ptw32_semwait.c" -#include "ptw32_timespec.c" -#include "ptw32_throw.c" -#include "ptw32_getprocessors.c" diff --git a/pthreads/src/pthread.c b/pthreads/src/pthread.c deleted file mode 100644 index 60b5341..0000000 --- a/pthreads/src/pthread.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * pthread.c - * - * Description: - * This translation unit agregates pthreads-win32 translation units. - * It is used for inline optimisation of the library, - * maximising for speed at the expense of size. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* The following are ordered for inlining */ - -#include "private.c" -#include "attr.c" -#include "barrier.c" -#include "cancel.c" -#include "cleanup.c" -#include "condvar.c" -#include "create.c" -#include "dll.c" -#include "autostatic.c" -#include "errno.c" -#include "exit.c" -#include "fork.c" -#include "global.c" -#include "misc.c" -#include "mutex.c" -#include "nonportable.c" -#include "rwlock.c" -#include "sched.c" -#include "semaphore.c" -#include "signal.c" -#include "spin.c" -#include "sync.c" -#include "tsd.c" diff --git a/pthreads/src/pthread.h b/pthreads/src/pthread.h deleted file mode 100644 index 9a19788..0000000 --- a/pthreads/src/pthread.h +++ /dev/null @@ -1,1368 +0,0 @@ -/* This is an implementation of the threads API of POSIX 1003.1-2001. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined( PTHREAD_H ) -#define PTHREAD_H - -/* - * See the README file for an explanation of the pthreads-win32 version - * numbering scheme and how the DLL is named etc. - */ -#define PTW32_VERSION 2,9,0,0 -#define PTW32_VERSION_STRING "2, 9, 0, 0\0" - -/* There are three implementations of cancel cleanup. - * Note that pthread.h is included in both application - * compilation units and also internally for the library. - * The code here and within the library aims to work - * for all reasonable combinations of environments. - * - * The three implementations are: - * - * WIN32 SEH - * C - * C++ - * - * Please note that exiting a push/pop block via - * "return", "exit", "break", or "continue" will - * lead to different behaviour amongst applications - * depending upon whether the library was built - * using SEH, C++, or C. For example, a library built - * with SEH will call the cleanup routine, while both - * C++ and C built versions will not. - */ - -/* - * Define defaults for cleanup code. - * Note: Unless the build explicitly defines one of the following, then - * we default to standard C style cleanup. This style uses setjmp/longjmp - * in the cancelation and thread exit implementations and therefore won't - * do stack unwinding if linked to applications that have it (e.g. - * C++ apps). This is currently consistent with most/all commercial Unix - * POSIX threads implementations. - */ -#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) -# define __CLEANUP_C -#endif - -#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) -#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. -#endif - -/* - * Stop here if we are being included by the resource compiler. - */ -#if !defined(RC_INVOKED) - -#undef PTW32_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_LEVEL -#define PTW32_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_LEVEL -#define PTW32_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_LEVEL_MAX 3 - -#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_LEVEL) -#define PTW32_LEVEL PTW32_LEVEL_MAX -/* Include everything */ -#endif - -#if defined(_UWIN) -# define HAVE_STRUCT_TIMESPEC 1 -# define HAVE_SIGNAL_H 1 -# undef HAVE_PTW32_CONFIG_H -# pragma comment(lib, "pthread") -#endif - -/* - * ------------------------------------------------------------- - * - * - * Module: pthread.h - * - * Purpose: - * Provides an implementation of PThreads based upon the - * standard: - * - * POSIX 1003.1-2001 - * and - * The Single Unix Specification version 3 - * - * (these two are equivalent) - * - * in order to enhance code portability between Windows, - * various commercial Unix implementations, and Linux. - * - * See the ANNOUNCE file for a full list of conforming - * routines and defined constants, and a list of missing - * routines and constants not defined in this implementation. - * - * Authors: - * There have been many contributors to this library. - * The initial implementation was contributed by - * John Bossom, and several others have provided major - * sections or revisions of parts of the implementation. - * Often significant effort has been contributed to - * find and fix important bugs and other problems to - * improve the reliability of the library, which sometimes - * is not reflected in the amount of code which changed as - * result. - * As much as possible, the contributors are acknowledged - * in the ChangeLog file in the source code distribution - * where their changes are noted in detail. - * - * Contributors are listed in the CONTRIBUTORS file. - * - * As usual, all bouquets go to the contributors, and all - * brickbats go to the project maintainer. - * - * Maintainer: - * The code base for this project is coordinated and - * eventually pre-tested, packaged, and made available by - * - * Ross Johnson - * - * QA Testers: - * Ultimately, the library is tested in the real world by - * a host of competent and demanding scientists and - * engineers who report bugs and/or provide solutions - * which are then fixed or incorporated into subsequent - * versions of the library. Each time a bug is fixed, a - * test case is written to prove the fix and ensure - * that later changes to the code don't reintroduce the - * same error. The number of test cases is slowly growing - * and therefore so is the code reliability. - * - * Compliance: - * See the file ANNOUNCE for the list of implemented - * and not-implemented routines and defined options. - * Of course, these are all defined is this file as well. - * - * Web site: - * The source code and other information about this library - * are available from - * - * http://sources.redhat.com/pthreads-win32/ - * - * ------------------------------------------------------------- - */ - -/* Try to avoid including windows.h */ -#if (defined(__MINGW64__) || defined(__MINGW32__)) && defined(__cplusplus) -#define PTW32_INCLUDE_WINDOWS_H -#endif - -#if defined(PTW32_INCLUDE_WINDOWS_H) -#include -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) -/* - * VC++6.0 or early compiler's header has no DWORD_PTR type. - */ -typedef unsigned long DWORD_PTR; -typedef unsigned long ULONG_PTR; -#endif -/* - * ----------------- - * autoconf switches - * ----------------- - */ - -#if defined(HAVE_PTW32_CONFIG_H) -#include "config.h" -#endif /* HAVE_PTW32_CONFIG_H */ - -#if !defined(NEED_FTIME) -#include -#else /* NEED_FTIME */ -/* use native WIN32 time API */ -#endif /* NEED_FTIME */ - -#if defined(HAVE_SIGNAL_H) -#include -#endif /* HAVE_SIGNAL_H */ - -#include - -/* - * Boolean values to make us independent of system includes. - */ -enum { - PTW32_FALSE = 0, - PTW32_TRUE = (! PTW32_FALSE) -}; - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Several systems don't define some error numbers. - */ -#if !defined(ENOTSUP) -# define ENOTSUP 48 /* This is the value in Solaris. */ -#endif - -#if !defined(ETIMEDOUT) -# define ETIMEDOUT 10060 /* Same as WSAETIMEDOUT */ -#endif - -#if !defined(ENOSYS) -# define ENOSYS 140 /* Semi-arbitrary value */ -#endif - -#if !defined(EDEADLK) -# if defined(EDEADLOCK) -# define EDEADLK EDEADLOCK -# else -# define EDEADLK 36 /* This is the value in MSVC. */ -# endif -#endif - -/* POSIX 2008 - related to robust mutexes */ -#if !defined(EOWNERDEAD) -# define EOWNERDEAD 43 -#endif -#if !defined(ENOTRECOVERABLE) -# define ENOTRECOVERABLE 44 -#endif - -#include - -/* - * To avoid including windows.h we define only those things that we - * actually need from it. - */ -#if !defined(PTW32_INCLUDE_WINDOWS_H) -#if !defined(HANDLE) -# define PTW32__HANDLE_DEF -# define HANDLE void * -#endif -#if !defined(DWORD) -# define PTW32__DWORD_DEF -# define DWORD unsigned long -#endif -#endif - -#if !defined(HAVE_STRUCT_TIMESPEC) -#define HAVE_STRUCT_TIMESPEC -#if !defined(_TIMESPEC_DEFINED) -#define _TIMESPEC_DEFINED -struct timespec { - time_t tv_sec; - long tv_nsec; -}; -#endif /* _TIMESPEC_DEFINED */ -#endif /* HAVE_STRUCT_TIMESPEC */ - -#if !defined(SIG_BLOCK) -#define SIG_BLOCK 0 -#endif /* SIG_BLOCK */ - -#if !defined(SIG_UNBLOCK) -#define SIG_UNBLOCK 1 -#endif /* SIG_UNBLOCK */ - -#if !defined(SIG_SETMASK) -#define SIG_SETMASK 2 -#endif /* SIG_SETMASK */ - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -/* - * ------------------------------------------------------------- - * - * POSIX 1003.1-2001 Options - * ========================= - * - * Options are normally set in , which is not provided - * with pthreads-win32. - * - * For conformance with the Single Unix Specification (version 3), all of the - * options below are defined, and have a value of either -1 (not supported) - * or 200112L (supported). - * - * These options can neither be left undefined nor have a value of 0, because - * either indicates that sysconf(), which is not implemented, may be used at - * runtime to check the status of the option. - * - * _POSIX_THREADS (== 200112L) - * If == 200112L, you can use threads - * - * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) - * If == 200112L, you can control the size of a thread's - * stack - * pthread_attr_getstacksize - * pthread_attr_setstacksize - * - * _POSIX_THREAD_ATTR_STACKADDR (== -1) - * If == 200112L, you can allocate and control a thread's - * stack. If not supported, the following functions - * will return ENOSYS, indicating they are not - * supported: - * pthread_attr_getstackaddr - * pthread_attr_setstackaddr - * - * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) - * If == 200112L, you can use realtime scheduling. - * This option indicates that the behaviour of some - * implemented functions conforms to the additional TPS - * requirements in the standard. E.g. rwlocks favour - * writers over readers when threads have equal priority. - * - * _POSIX_THREAD_PRIO_INHERIT (== -1) - * If == 200112L, you can create priority inheritance - * mutexes. - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprotocol + - * - * _POSIX_THREAD_PRIO_PROTECT (== -1) - * If == 200112L, you can create priority ceiling mutexes - * Indicates the availability of: - * pthread_mutex_getprioceiling - * pthread_mutex_setprioceiling - * pthread_mutexattr_getprioceiling - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprioceiling - * pthread_mutexattr_setprotocol + - * - * _POSIX_THREAD_PROCESS_SHARED (== -1) - * If set, you can create mutexes and condition - * variables that can be shared with another - * process.If set, indicates the availability - * of: - * pthread_mutexattr_getpshared - * pthread_mutexattr_setpshared - * pthread_condattr_getpshared - * pthread_condattr_setpshared - * - * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) - * If == 200112L you can use the special *_r library - * functions that provide thread-safe behaviour - * - * _POSIX_READER_WRITER_LOCKS (== 200112L) - * If == 200112L, you can use read/write locks - * - * _POSIX_SPIN_LOCKS (== 200112L) - * If == 200112L, you can use spin locks - * - * _POSIX_BARRIERS (== 200112L) - * If == 200112L, you can use barriers - * - * + These functions provide both 'inherit' and/or - * 'protect' protocol, based upon these macro - * settings. - * - * ------------------------------------------------------------- - */ - -/* - * POSIX Options - */ -#undef _POSIX_THREADS -#define _POSIX_THREADS 200809L - -#undef _POSIX_READER_WRITER_LOCKS -#define _POSIX_READER_WRITER_LOCKS 200809L - -#undef _POSIX_SPIN_LOCKS -#define _POSIX_SPIN_LOCKS 200809L - -#undef _POSIX_BARRIERS -#define _POSIX_BARRIERS 200809L - -#undef _POSIX_THREAD_SAFE_FUNCTIONS -#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L - -#undef _POSIX_THREAD_ATTR_STACKSIZE -#define _POSIX_THREAD_ATTR_STACKSIZE 200809L - -/* - * The following options are not supported - */ -#undef _POSIX_THREAD_ATTR_STACKADDR -#define _POSIX_THREAD_ATTR_STACKADDR -1 - -#undef _POSIX_THREAD_PRIO_INHERIT -#define _POSIX_THREAD_PRIO_INHERIT -1 - -#undef _POSIX_THREAD_PRIO_PROTECT -#define _POSIX_THREAD_PRIO_PROTECT -1 - -/* TPS is not fully supported. */ -#undef _POSIX_THREAD_PRIORITY_SCHEDULING -#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 - -#undef _POSIX_THREAD_PROCESS_SHARED -#define _POSIX_THREAD_PROCESS_SHARED -1 - - -/* - * POSIX 1003.1-2001 Limits - * =========================== - * - * These limits are normally set in , which is not provided with - * pthreads-win32. - * - * PTHREAD_DESTRUCTOR_ITERATIONS - * Maximum number of attempts to destroy - * a thread's thread-specific data on - * termination (must be at least 4) - * - * PTHREAD_KEYS_MAX - * Maximum number of thread-specific data keys - * available per process (must be at least 128) - * - * PTHREAD_STACK_MIN - * Minimum supported stack size for a thread - * - * PTHREAD_THREADS_MAX - * Maximum number of threads supported per - * process (must be at least 64). - * - * SEM_NSEMS_MAX - * The maximum number of semaphores a process can have. - * (must be at least 256) - * - * SEM_VALUE_MAX - * The maximum value a semaphore can have. - * (must be at least 32767) - * - */ -#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS -#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 - -#undef PTHREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS - -#undef _POSIX_THREAD_KEYS_MAX -#define _POSIX_THREAD_KEYS_MAX 128 - -#undef PTHREAD_KEYS_MAX -#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX - -#undef PTHREAD_STACK_MIN -#define PTHREAD_STACK_MIN 0 - -#undef _POSIX_THREAD_THREADS_MAX -#define _POSIX_THREAD_THREADS_MAX 64 - - /* Arbitrary value */ -#undef PTHREAD_THREADS_MAX -#define PTHREAD_THREADS_MAX 2019 - -#undef _POSIX_SEM_NSEMS_MAX -#define _POSIX_SEM_NSEMS_MAX 256 - - /* Arbitrary value */ -#undef SEM_NSEMS_MAX -#define SEM_NSEMS_MAX 1024 - -#undef _POSIX_SEM_VALUE_MAX -#define _POSIX_SEM_VALUE_MAX 32767 - -#undef SEM_VALUE_MAX -#define SEM_VALUE_MAX INT_MAX - - -#if defined(__GNUC__) && !defined(__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * The Open Watcom C/C++ compiler uses a non-standard calling convention - * that passes function args in registers unless __cdecl is explicitly specified - * in exposed function prototypes. - * - * We force all calls to cdecl even though this could slow Watcom code down - * slightly. If you know that the Watcom compiler will be used to build both - * the DLL and application, then you can probably define this as a null string. - * Remember that pthread.h (this file) is used for both the DLL and application builds. - */ -#define PTW32_CDECL __cdecl - -#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX -# include -#else -/* - * Generic handle type - intended to extend uniqueness beyond - * that available with a simple pointer. It should scale for either - * IA-32 or IA-64. - */ -typedef struct { - void * p; /* Pointer to actual object */ - unsigned int x; /* Extra information - reuse count etc */ -} ptw32_handle_t; - -typedef ptw32_handle_t pthread_t; -typedef struct pthread_attr_t_ * pthread_attr_t; -typedef struct pthread_once_t_ pthread_once_t; -typedef struct pthread_key_t_ * pthread_key_t; -typedef struct pthread_mutex_t_ * pthread_mutex_t; -typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; -typedef struct pthread_cond_t_ * pthread_cond_t; -typedef struct pthread_condattr_t_ * pthread_condattr_t; -#endif -typedef struct pthread_rwlock_t_ * pthread_rwlock_t; -typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; -typedef struct pthread_spinlock_t_ * pthread_spinlock_t; -typedef struct pthread_barrier_t_ * pthread_barrier_t; -typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; - -/* - * ==================== - * ==================== - * POSIX Threads - * ==================== - * ==================== - */ - -enum { -/* - * pthread_attr_{get,set}detachstate - */ - PTHREAD_CREATE_JOINABLE = 0, /* Default */ - PTHREAD_CREATE_DETACHED = 1, - -/* - * pthread_attr_{get,set}inheritsched - */ - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1, /* Default */ - -/* - * pthread_{get,set}scope - */ - PTHREAD_SCOPE_PROCESS = 0, - PTHREAD_SCOPE_SYSTEM = 1, /* Default */ - -/* - * pthread_setcancelstate paramters - */ - PTHREAD_CANCEL_ENABLE = 0, /* Default */ - PTHREAD_CANCEL_DISABLE = 1, - -/* - * pthread_setcanceltype parameters - */ - PTHREAD_CANCEL_ASYNCHRONOUS = 0, - PTHREAD_CANCEL_DEFERRED = 1, /* Default */ - -/* - * pthread_mutexattr_{get,set}pshared - * pthread_condattr_{get,set}pshared - */ - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1, - -/* - * pthread_mutexattr_{get,set}robust - */ - PTHREAD_MUTEX_STALLED = 0, /* Default */ - PTHREAD_MUTEX_ROBUST = 1, - -/* - * pthread_barrier_wait - */ - PTHREAD_BARRIER_SERIAL_THREAD = -1 -}; - -/* - * ==================== - * ==================== - * Cancelation - * ==================== - * ==================== - */ -#define PTHREAD_CANCELED ((void *)(size_t) -1) - - -/* - * ==================== - * ==================== - * Once Key - * ==================== - * ==================== - */ -#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} - -struct pthread_once_t_ -{ - int done; /* indicates if user function has been executed */ - void * lock; - int reserved1; - int reserved2; -}; - - -/* - * ==================== - * ==================== - * Object initialisers - * ==================== - * ==================== - */ -#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -1) -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -2) -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -3) - -/* - * Compatibility with LinuxThreads - */ -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER - -#define PTHREAD_COND_INITIALIZER ((pthread_cond_t)(size_t) -1) - -#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t)(size_t) -1) - -#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t)(size_t) -1) - - -/* - * Mutex types. - */ -enum -{ - /* Compatibility with LinuxThreads */ - PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, - /* For compatibility with POSIX */ - PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL -}; - - -typedef struct ptw32_cleanup_t ptw32_cleanup_t; - -#if defined(_MSC_VER) -/* Disable MSVC 'anachronism used' warning */ -#pragma warning( disable : 4229 ) -#endif - -typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); - -#if defined(_MSC_VER) -#pragma warning( default : 4229 ) -#endif - -struct ptw32_cleanup_t -{ - ptw32_cleanup_callback_t routine; - void *arg; - struct ptw32_cleanup_t *prev; -}; - -#if defined(__CLEANUP_SEH) - /* - * WIN32 SEH version of cancel cleanup. - */ - -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - ptw32_cleanup_t _cleanup; \ - \ - _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ - _cleanup.arg = (_arg); \ - __try \ - { \ - -#define pthread_cleanup_pop( _execute ) \ - } \ - __finally \ - { \ - if( _execute || AbnormalTermination()) \ - { \ - (*(_cleanup.routine))( _cleanup.arg ); \ - } \ - } \ - } - -#else /* __CLEANUP_SEH */ - -#if defined(__CLEANUP_C) - - /* - * C implementation of PThreads cancel cleanup - */ - -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - ptw32_cleanup_t _cleanup; \ - \ - ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ - -#define pthread_cleanup_pop( _execute ) \ - (void) ptw32_pop_cleanup( _execute ); \ - } - -#else /* __CLEANUP_C */ - -#if defined(__CLEANUP_CXX) - - /* - * C++ version of cancel cleanup. - * - John E. Bossom. - */ - - class PThreadCleanup { - /* - * PThreadCleanup - * - * Purpose - * This class is a C++ helper class that is - * used to implement pthread_cleanup_push/ - * pthread_cleanup_pop. - * The destructor of this class automatically - * pops the pushed cleanup routine regardless - * of how the code exits the scope - * (i.e. such as by an exception) - */ - ptw32_cleanup_callback_t cleanUpRout; - void * obj; - int executeIt; - - public: - PThreadCleanup() : - cleanUpRout( 0 ), - obj( 0 ), - executeIt( 0 ) - /* - * No cleanup performed - */ - { - } - - PThreadCleanup( - ptw32_cleanup_callback_t routine, - void * arg ) : - cleanUpRout( routine ), - obj( arg ), - executeIt( 1 ) - /* - * Registers a cleanup routine for 'arg' - */ - { - } - - ~PThreadCleanup() - { - if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) - { - (void) (*cleanUpRout)( obj ); - } - } - - void execute( int exec ) - { - executeIt = exec; - } - }; - - /* - * C++ implementation of PThreads cancel cleanup; - * This implementation takes advantage of a helper - * class who's destructor automatically calls the - * cleanup routine if we exit our scope weirdly - */ -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ - (void *) (_arg) ); - -#define pthread_cleanup_pop( _execute ) \ - cleanup.execute( _execute ); \ - } - -#else - -#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. - -#endif /* __CLEANUP_CXX */ - -#endif /* __CLEANUP_C */ - -#endif /* __CLEANUP_SEH */ - -/* - * =============== - * =============== - * Methods - * =============== - * =============== - */ - -/* - * PThread Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, - int *detachstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, - void **stackaddr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, - size_t * stacksize); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, - int detachstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, - void *stackaddr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, - size_t stacksize); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, - struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, - const struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, - int); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (const pthread_attr_t *, - int *); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, - int inheritsched); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(const pthread_attr_t * attr, - int * inheritsched); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, - int); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, - int *); - -/* - * PThread Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, - const pthread_attr_t * attr, - void *(*start) (void *), - void *arg); - -PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); - -PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, - pthread_t t2); - -PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); - -PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, - void **value_ptr); - -PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); - -PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); - -PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, - int *oldstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, - int *oldtype); - -PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); - -PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, - void (*init_routine) (void)); - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX -PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); - -PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, - void (*routine) (void *), - void *arg); -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Thread Specific Data Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, - void (*destructor) (void *)); - -PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); - -PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, - const void *value); - -PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); - - -/* - * Mutex Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t - * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, - int pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setrobust( - pthread_mutexattr_t *attr, - int robust); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getrobust( - const pthread_mutexattr_t * attr, - int * robust); - -/* - * Barrier Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t - * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, - int pshared); - -/* - * Mutex Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, - const pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t * mutex, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_consistent (pthread_mutex_t * mutex); - -/* - * Spinlock Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); - -/* - * Barrier Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, - const pthread_barrierattr_t * attr, - unsigned int count); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); - -/* - * Condition Variable Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, - int pshared); - -/* - * Condition Variable Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, - const pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, - pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, - pthread_mutex_t * mutex, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); - -/* - * Scheduling - */ -PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, - int policy, - const struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, - int *policy, - struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); - -PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); - -/* - * Read-Write Lock Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, - const pthread_rwlockattr_t *attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, - int pshared); - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 - -/* - * Signal Functions. Should be defined in but MSVC and MinGW32 - * already have signal.h that don't define these. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); - -/* - * Non-portable functions - */ - -/* - * Compatibility with Linux. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, - int kind); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, - int *kind); - -/* - * Possibly supported by other POSIX threads implementations - */ -PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); -PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); -PTW32_DLLPORT unsigned __int64 PTW32_CDECL pthread_getunique_np(pthread_t thread); - -/* - * Useful if an application wants to statically link - * the lib rather than load the DLL at run-time. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); - -/* - * Features that are auto-detected at load/run time. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); -enum ptw32_features { - PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ - PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ -}; - -/* - * Register a system time change with the library. - * Causes the library to perform various functions - * in response to the change. Should be called whenever - * the application's top level window receives a - * WM_TIMECHANGE message. It can be passed directly to - * pthread_create() as a new thread if desired. - */ -PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); - -#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* - * Returns the Win32 HANDLE for the POSIX thread. - */ -PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); -/* - * Returns the win32 thread ID for POSIX thread. - */ -PTW32_DLLPORT DWORD PTW32_CDECL pthread_getw32threadid_np (pthread_t thread); - - -/* - * Protected Methods - * - * This function blocks until the given WIN32 handle - * is signaled or pthread_cancel had been called. - * This function allows the caller to hook into the - * PThreads cancel mechanism. It is implemented using - * - * WaitForMultipleObjects - * - * on 'waitHandle' and a manually reset WIN32 Event - * used to implement pthread_cancel. The 'timeout' - * argument to TimedWait is simply passed to - * WaitForMultipleObjects. - */ -PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); -PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, - DWORD timeout); - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Thread-Safe C Runtime Library Mappings. - */ -#if !defined(_UWIN) -# if defined(NEED_ERRNO) - PTW32_DLLPORT int * PTW32_CDECL _errno( void ); -# else -# if !defined(errno) -# if (defined(_MT) || defined(_DLL)) - __declspec(dllimport) extern int * __cdecl _errno(void); -# define errno (*_errno()) -# endif -# endif -# endif -#endif - -/* - * Some compiler environments don't define some things. - */ -#if defined(__BORLANDC__) -# define _ftime ftime -# define _timeb timeb -#endif - -#if defined(__cplusplus) - -/* - * Internal exceptions - */ -class ptw32_exception {}; -class ptw32_exception_cancel : public ptw32_exception {}; -class ptw32_exception_exit : public ptw32_exception {}; - -#endif - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* FIXME: This is only required if the library was built using SEH */ -/* - * Get internal SEH tag - */ -PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -#if !defined(PTW32_BUILD) - -#if defined(__CLEANUP_SEH) - -/* - * Redefine the SEH __except keyword to ensure that applications - * propagate our internal exceptions up to the library's internal handlers. - */ -#define __except( E ) \ - __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ - ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) - -#endif /* __CLEANUP_SEH */ - -#if defined(__CLEANUP_CXX) - -/* - * Redefine the C++ catch keyword to ensure that applications - * propagate our internal exceptions up to the library's internal handlers. - */ -#if defined(_MSC_VER) - /* - * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' - * if you want Pthread-Win32 cancelation and pthread_exit to work. - */ - -#if !defined(PtW32NoCatchWarn) - -#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") -#pragma message("------------------------------------------------------------------") -#pragma message("When compiling applications with MSVC++ and C++ exception handling:") -#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") -#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") -#pragma message(" cancelation and pthread_exit to work. For example:") -#pragma message("") -#pragma message(" #if defined(PtW32CatchAll)") -#pragma message(" PtW32CatchAll") -#pragma message(" #else") -#pragma message(" catch(...)") -#pragma message(" #endif") -#pragma message(" {") -#pragma message(" /* Catchall block processing */") -#pragma message(" }") -#pragma message("------------------------------------------------------------------") - -#endif - -#define PtW32CatchAll \ - catch( ptw32_exception & ) { throw; } \ - catch( ... ) - -#else /* _MSC_VER */ - -#define catch( E ) \ - catch( ptw32_exception & ) { throw; } \ - catch( E ) - -#endif /* _MSC_VER */ - -#endif /* __CLEANUP_CXX */ - -#endif /* ! PTW32_BUILD */ - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#if defined(PTW32__HANDLE_DEF) -# undef HANDLE -#endif -#if defined(PTW32__DWORD_DEF) -# undef DWORD -#endif - -#undef PTW32_LEVEL -#undef PTW32_LEVEL_MAX - -#endif /* ! RC_INVOKED */ - -#endif /* PTHREAD_H */ diff --git a/pthreads/src/pthread_attr_destroy.c b/pthreads/src/pthread_attr_destroy.c deleted file mode 100644 index 8b3e04c..0000000 --- a/pthreads/src/pthread_attr_destroy.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * pthread_attr_destroy.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_attr_destroy (pthread_attr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Destroys a thread attributes object. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_attr_t - * - * - * DESCRIPTION - * Destroys a thread attributes object. - * - * NOTES: - * 1) Does not affect threads created with 'attr'. - * - * RESULTS - * 0 successfully destroyed attr, - * EINVAL 'attr' is invalid. - * - * ------------------------------------------------------ - */ -{ - if (ptw32_is_attr (attr) != 0) - { - return EINVAL; - } - - /* - * Set the attribute object to a specific invalid value. - */ - (*attr)->valid = 0; - free (*attr); - *attr = NULL; - - return 0; -} diff --git a/pthreads/src/pthread_attr_getdetachstate.c b/pthreads/src/pthread_attr_getdetachstate.c deleted file mode 100644 index 188533b..0000000 --- a/pthreads/src/pthread_attr_getdetachstate.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * pthread_attr_getdetachstate.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function determines whether threads created with - * 'attr' will run detached. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_attr_t - * - * detachstate - * pointer to an integer into which is returned one - * of: - * - * PTHREAD_CREATE_JOINABLE - * Thread ID is valid, must be joined - * - * PTHREAD_CREATE_DETACHED - * Thread ID is invalid, cannot be joined, - * canceled, or modified - * - * - * DESCRIPTION - * This function determines whether threads created with - * 'attr' will run detached. - * - * NOTES: - * 1) You cannot join or cancel detached threads. - * - * RESULTS - * 0 successfully retrieved detach state, - * EINVAL 'attr' is invalid - * - * ------------------------------------------------------ - */ -{ - if (ptw32_is_attr (attr) != 0 || detachstate == NULL) - { - return EINVAL; - } - - *detachstate = (*attr)->detachstate; - return 0; -} diff --git a/pthreads/src/pthread_attr_getinheritsched.c b/pthreads/src/pthread_attr_getinheritsched.c deleted file mode 100644 index 9c6885e..0000000 --- a/pthreads/src/pthread_attr_getinheritsched.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * pthread_attr_getinheritsched.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -pthread_attr_getinheritsched (const pthread_attr_t * attr, int *inheritsched) -{ - if (ptw32_is_attr (attr) != 0 || inheritsched == NULL) - { - return EINVAL; - } - - *inheritsched = (*attr)->inheritsched; - return 0; -} diff --git a/pthreads/src/pthread_attr_getschedparam.c b/pthreads/src/pthread_attr_getschedparam.c deleted file mode 100644 index ab89b22..0000000 --- a/pthreads/src/pthread_attr_getschedparam.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * pthread_attr_getschedparam.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -pthread_attr_getschedparam (const pthread_attr_t * attr, - struct sched_param *param) -{ - if (ptw32_is_attr (attr) != 0 || param == NULL) - { - return EINVAL; - } - - memcpy (param, &(*attr)->param, sizeof (*param)); - return 0; -} diff --git a/pthreads/src/pthread_attr_getschedpolicy.c b/pthreads/src/pthread_attr_getschedpolicy.c deleted file mode 100644 index 94a257d..0000000 --- a/pthreads/src/pthread_attr_getschedpolicy.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * pthread_attr_getschedpolicy.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -pthread_attr_getschedpolicy (const pthread_attr_t * attr, int *policy) -{ - if (ptw32_is_attr (attr) != 0 || policy == NULL) - { - return EINVAL; - } - - /* - * Validate the policy arg. - * Check that a policy constant wasn't passed rather than &policy. - */ - if (policy <= (int *) SCHED_MAX) - { - return EINVAL; - } - - *policy = SCHED_OTHER; - - return 0; -} diff --git a/pthreads/src/pthread_attr_getscope.c b/pthreads/src/pthread_attr_getscope.c deleted file mode 100644 index 2efdb2f..0000000 --- a/pthreads/src/pthread_attr_getscope.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * pthread_attr_getscope.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* ignore warning "unreferenced formal parameter" */ -#if defined(_MSC_VER) -#pragma warning( disable : 4100 ) -#endif - -int -pthread_attr_getscope (const pthread_attr_t * attr, int *contentionscope) -{ -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) - *contentionscope = (*attr)->contentionscope; - return 0; -#else - return ENOSYS; -#endif -} diff --git a/pthreads/src/pthread_attr_getstackaddr.c b/pthreads/src/pthread_attr_getstackaddr.c deleted file mode 100644 index 1a2da01..0000000 --- a/pthreads/src/pthread_attr_getstackaddr.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * pthread_attr_getstackaddr.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* ignore warning "unreferenced formal parameter" */ -#if defined(_MSC_VER) -#pragma warning( disable : 4100 ) -#endif - -int -pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function determines the address of the stack - * on which threads created with 'attr' will run. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_attr_t - * - * stackaddr - * pointer into which is returned the stack address. - * - * - * DESCRIPTION - * This function determines the address of the stack - * on which threads created with 'attr' will run. - * - * NOTES: - * 1) Function supported only if this macro is - * defined: - * - * _POSIX_THREAD_ATTR_STACKADDR - * - * 2) Create only one thread for each stack - * address.. - * - * RESULTS - * 0 successfully retreived stack address, - * EINVAL 'attr' is invalid - * ENOSYS function not supported - * - * ------------------------------------------------------ - */ -{ -#if defined( _POSIX_THREAD_ATTR_STACKADDR ) - - if (ptw32_is_attr (attr) != 0) - { - return EINVAL; - } - - *stackaddr = (*attr)->stackaddr; - return 0; - -#else - - return ENOSYS; - -#endif /* _POSIX_THREAD_ATTR_STACKADDR */ -} diff --git a/pthreads/src/pthread_attr_getstacksize.c b/pthreads/src/pthread_attr_getstacksize.c deleted file mode 100644 index dff9230..0000000 --- a/pthreads/src/pthread_attr_getstacksize.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * pthread_attr_getstacksize.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* ignore warning "unreferenced formal parameter" */ -#if defined(_MSC_VER) -#pragma warning( disable : 4100 ) -#endif - -int -pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * stacksize) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function determines the size of the stack on - * which threads created with 'attr' will run. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_attr_t - * - * stacksize - * pointer to size_t into which is returned the - * stack size, in bytes. - * - * - * DESCRIPTION - * This function determines the size of the stack on - * which threads created with 'attr' will run. - * - * NOTES: - * 1) Function supported only if this macro is - * defined: - * - * _POSIX_THREAD_ATTR_STACKSIZE - * - * 2) Use on newly created attributes object to - * find the default stack size. - * - * RESULTS - * 0 successfully retrieved stack size, - * EINVAL 'attr' is invalid - * ENOSYS function not supported - * - * ------------------------------------------------------ - */ -{ -#if defined(_POSIX_THREAD_ATTR_STACKSIZE) - - if (ptw32_is_attr (attr) != 0) - { - return EINVAL; - } - - /* Everything is okay. */ - *stacksize = (*attr)->stacksize; - return 0; - -#else - - return ENOSYS; - -#endif /* _POSIX_THREAD_ATTR_STACKSIZE */ - -} diff --git a/pthreads/src/pthread_attr_init.c b/pthreads/src/pthread_attr_init.c deleted file mode 100644 index ae9d3eb..0000000 --- a/pthreads/src/pthread_attr_init.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * pthread_attr_init.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_attr_init (pthread_attr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Initializes a thread attributes object with default - * attributes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_attr_t - * - * - * DESCRIPTION - * Initializes a thread attributes object with default - * attributes. - * - * NOTES: - * 1) Used to define thread attributes - * - * RESULTS - * 0 successfully initialized attr, - * ENOMEM insufficient memory for attr. - * - * ------------------------------------------------------ - */ -{ - pthread_attr_t attr_result; - - if (attr == NULL) - { - /* This is disallowed. */ - return EINVAL; - } - - attr_result = (pthread_attr_t) malloc (sizeof (*attr_result)); - - if (attr_result == NULL) - { - return ENOMEM; - } - -#if defined(_POSIX_THREAD_ATTR_STACKSIZE) - /* - * Default to zero size. Unless changed explicitly this - * will allow Win32 to set the size to that of the - * main thread. - */ - attr_result->stacksize = 0; -#endif - -#if defined(_POSIX_THREAD_ATTR_STACKADDR) - /* FIXME: Set this to something sensible when we support it. */ - attr_result->stackaddr = NULL; -#endif - - attr_result->detachstate = PTHREAD_CREATE_JOINABLE; - -#if defined(HAVE_SIGSET_T) - memset (&(attr_result->sigmask), 0, sizeof (sigset_t)); -#endif /* HAVE_SIGSET_T */ - - /* - * Win32 sets new threads to THREAD_PRIORITY_NORMAL and - * not to that of the parent thread. We choose to default to - * this arrangement. - */ - attr_result->param.sched_priority = THREAD_PRIORITY_NORMAL; - attr_result->inheritsched = PTHREAD_EXPLICIT_SCHED; - attr_result->contentionscope = PTHREAD_SCOPE_SYSTEM; - - attr_result->valid = PTW32_ATTR_VALID; - - *attr = attr_result; - - return 0; -} diff --git a/pthreads/src/pthread_attr_setdetachstate.c b/pthreads/src/pthread_attr_setdetachstate.c deleted file mode 100644 index 784642a..0000000 --- a/pthreads/src/pthread_attr_setdetachstate.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * pthread_attr_setdetachstate.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function specifies whether threads created with - * 'attr' will run detached. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_attr_t - * - * detachstate - * an integer containing one of: - * - * PTHREAD_CREATE_JOINABLE - * Thread ID is valid, must be joined - * - * PTHREAD_CREATE_DETACHED - * Thread ID is invalid, cannot be joined, - * canceled, or modified - * - * - * DESCRIPTION - * This function specifies whether threads created with - * 'attr' will run detached. - * - * NOTES: - * 1) You cannot join or cancel detached threads. - * - * RESULTS - * 0 successfully set detach state, - * EINVAL 'attr' or 'detachstate' is invalid - * - * ------------------------------------------------------ - */ -{ - if (ptw32_is_attr (attr) != 0) - { - return EINVAL; - } - - if (detachstate != PTHREAD_CREATE_JOINABLE && - detachstate != PTHREAD_CREATE_DETACHED) - { - return EINVAL; - } - - (*attr)->detachstate = detachstate; - return 0; -} diff --git a/pthreads/src/pthread_attr_setinheritsched.c b/pthreads/src/pthread_attr_setinheritsched.c deleted file mode 100644 index e0a407a..0000000 --- a/pthreads/src/pthread_attr_setinheritsched.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * pthread_attr_setinheritsched.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -pthread_attr_setinheritsched (pthread_attr_t * attr, int inheritsched) -{ - if (ptw32_is_attr (attr) != 0) - { - return EINVAL; - } - - if (PTHREAD_INHERIT_SCHED != inheritsched - && PTHREAD_EXPLICIT_SCHED != inheritsched) - { - return EINVAL; - } - - (*attr)->inheritsched = inheritsched; - return 0; -} diff --git a/pthreads/src/pthread_attr_setschedparam.c b/pthreads/src/pthread_attr_setschedparam.c deleted file mode 100644 index f246bfa..0000000 --- a/pthreads/src/pthread_attr_setschedparam.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * pthread_attr_setschedparam.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -pthread_attr_setschedparam (pthread_attr_t * attr, - const struct sched_param *param) -{ - int priority; - - if (ptw32_is_attr (attr) != 0 || param == NULL) - { - return EINVAL; - } - - priority = param->sched_priority; - - /* Validate priority level. */ - if (priority < sched_get_priority_min (SCHED_OTHER) || - priority > sched_get_priority_max (SCHED_OTHER)) - { - return EINVAL; - } - - memcpy (&(*attr)->param, param, sizeof (*param)); - return 0; -} diff --git a/pthreads/src/pthread_attr_setschedpolicy.c b/pthreads/src/pthread_attr_setschedpolicy.c deleted file mode 100644 index 45ff165..0000000 --- a/pthreads/src/pthread_attr_setschedpolicy.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * pthread_attr_setschedpolicy.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy) -{ - if (ptw32_is_attr (attr) != 0) - { - return EINVAL; - } - - if (policy != SCHED_OTHER) - { - return ENOTSUP; - } - - return 0; -} diff --git a/pthreads/src/pthread_attr_setscope.c b/pthreads/src/pthread_attr_setscope.c deleted file mode 100644 index 39a51df..0000000 --- a/pthreads/src/pthread_attr_setscope.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * pthread_attr_setscope.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* ignore warning "unreferenced formal parameter" */ -#if defined(_MSC_VER) -#pragma warning( disable : 4100 ) -#endif - -int -pthread_attr_setscope (pthread_attr_t * attr, int contentionscope) -{ -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) - switch (contentionscope) - { - case PTHREAD_SCOPE_SYSTEM: - (*attr)->contentionscope = contentionscope; - return 0; - case PTHREAD_SCOPE_PROCESS: - return ENOTSUP; - default: - return EINVAL; - } -#else - return ENOSYS; -#endif -} diff --git a/pthreads/src/pthread_attr_setstackaddr.c b/pthreads/src/pthread_attr_setstackaddr.c deleted file mode 100644 index 1316c06..0000000 --- a/pthreads/src/pthread_attr_setstackaddr.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * pthread_attr_setstackaddr.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_attr_setstackaddr (pthread_attr_t * attr, void *stackaddr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Threads created with 'attr' will run on the stack - * starting at 'stackaddr'. - * Stack must be at least PTHREAD_STACK_MIN bytes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_attr_t - * - * stackaddr - * the address of the stack to use - * - * - * DESCRIPTION - * Threads created with 'attr' will run on the stack - * starting at 'stackaddr'. - * Stack must be at least PTHREAD_STACK_MIN bytes. - * - * NOTES: - * 1) Function supported only if this macro is - * defined: - * - * _POSIX_THREAD_ATTR_STACKADDR - * - * 2) Create only one thread for each stack - * address.. - * - * 3) Ensure that stackaddr is aligned. - * - * RESULTS - * 0 successfully set stack address, - * EINVAL 'attr' is invalid - * ENOSYS function not supported - * - * ------------------------------------------------------ - */ -{ -#if defined( _POSIX_THREAD_ATTR_STACKADDR ) - - if (ptw32_is_attr (attr) != 0) - { - return EINVAL; - } - - (*attr)->stackaddr = stackaddr; - return 0; - -#else - - return ENOSYS; - -#endif /* _POSIX_THREAD_ATTR_STACKADDR */ -} diff --git a/pthreads/src/pthread_attr_setstacksize.c b/pthreads/src/pthread_attr_setstacksize.c deleted file mode 100644 index eb13589..0000000 --- a/pthreads/src/pthread_attr_setstacksize.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * pthread_attr_setstacksize.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_attr_setstacksize (pthread_attr_t * attr, size_t stacksize) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function specifies the size of the stack on - * which threads created with 'attr' will run. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_attr_t - * - * stacksize - * stack size, in bytes. - * - * - * DESCRIPTION - * This function specifies the size of the stack on - * which threads created with 'attr' will run. - * - * NOTES: - * 1) Function supported only if this macro is - * defined: - * - * _POSIX_THREAD_ATTR_STACKSIZE - * - * 2) Find the default first (using - * pthread_attr_getstacksize), then increase - * by multiplying. - * - * 3) Only use if thread needs more than the - * default. - * - * RESULTS - * 0 successfully set stack size, - * EINVAL 'attr' is invalid or stacksize too - * small or too big. - * ENOSYS function not supported - * - * ------------------------------------------------------ - */ -{ -#if defined(_POSIX_THREAD_ATTR_STACKSIZE) - -#if PTHREAD_STACK_MIN > 0 - - /* Verify that the stack size is within range. */ - if (stacksize < PTHREAD_STACK_MIN) - { - return EINVAL; - } - -#endif - - if (ptw32_is_attr (attr) != 0) - { - return EINVAL; - } - - /* Everything is okay. */ - (*attr)->stacksize = stacksize; - return 0; - -#else - - return ENOSYS; - -#endif /* _POSIX_THREAD_ATTR_STACKSIZE */ - -} diff --git a/pthreads/src/pthread_barrier_destroy.c b/pthreads/src/pthread_barrier_destroy.c deleted file mode 100644 index 55163cc..0000000 --- a/pthreads/src/pthread_barrier_destroy.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * pthread_barrier_destroy.c - * - * Description: - * This translation unit implements barrier primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -int -pthread_barrier_destroy (pthread_barrier_t * barrier) -{ - int result = 0; - pthread_barrier_t b; - ptw32_mcs_local_node_t node; - - if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID) - { - return EINVAL; - } - - if (0 != ptw32_mcs_lock_try_acquire(&(*barrier)->lock, &node)) - { - return EBUSY; - } - - b = *barrier; - - if (b->nCurrentBarrierHeight < b->nInitialBarrierHeight) - { - result = EBUSY; - } - else - { - if (0 == (result = sem_destroy (&(b->semBarrierBreeched)))) - { - *barrier = (pthread_barrier_t) PTW32_OBJECT_INVALID; - /* - * Release the lock before freeing b. - * - * FIXME: There may be successors which, when we release the lock, - * will be linked into b->lock, which will be corrupted at some - * point with undefined results for the application. To fix this - * will require changing pthread_barrier_t from a pointer to - * pthread_barrier_t_ to an instance. This is a change to the ABI - * and will require a major version number increment. - */ - ptw32_mcs_lock_release(&node); - (void) free (b); - return 0; - } - else - { - /* - * This should not ever be reached. - * Restore the barrier to working condition before returning. - */ - (void) sem_init (&(b->semBarrierBreeched), b->pshared, 0); - } - - if (result != 0) - { - /* - * The barrier still exists and is valid - * in the event of any error above. - */ - result = EBUSY; - } - } - - ptw32_mcs_lock_release(&node); - return (result); -} diff --git a/pthreads/src/pthread_barrier_init.c b/pthreads/src/pthread_barrier_init.c deleted file mode 100644 index 618bfae..0000000 --- a/pthreads/src/pthread_barrier_init.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * pthread_barrier_init.c - * - * Description: - * This translation unit implements barrier primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_barrier_init (pthread_barrier_t * barrier, - const pthread_barrierattr_t * attr, unsigned int count) -{ - pthread_barrier_t b; - - if (barrier == NULL || count == 0) - { - return EINVAL; - } - - if (NULL != (b = (pthread_barrier_t) calloc (1, sizeof (*b)))) - { - b->pshared = (attr != NULL && *attr != NULL - ? (*attr)->pshared : PTHREAD_PROCESS_PRIVATE); - - b->nCurrentBarrierHeight = b->nInitialBarrierHeight = count; - b->lock = 0; - - if (0 == sem_init (&(b->semBarrierBreeched), b->pshared, 0)) - { - *barrier = b; - return 0; - } - (void) free (b); - } - - return ENOMEM; -} diff --git a/pthreads/src/pthread_barrier_wait.c b/pthreads/src/pthread_barrier_wait.c deleted file mode 100644 index e0e97e6..0000000 --- a/pthreads/src/pthread_barrier_wait.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * pthread_barrier_wait.c - * - * Description: - * This translation unit implements barrier primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_barrier_wait (pthread_barrier_t * barrier) -{ - int result; - pthread_barrier_t b; - - ptw32_mcs_local_node_t node; - - if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID) - { - return EINVAL; - } - - ptw32_mcs_lock_acquire(&(*barrier)->lock, &node); - - b = *barrier; - if (--b->nCurrentBarrierHeight == 0) - { - /* - * We are the last thread to arrive at the barrier before it releases us. - * Move our MCS local node to the global scope barrier handle so that the - * last thread out (not necessarily us) can release the lock. - */ - ptw32_mcs_node_transfer(&b->proxynode, &node); - - /* - * Any threads that have not quite entered sem_wait below when the - * multiple_post has completed will nevertheless continue through - * the semaphore (barrier). - */ - result = (b->nInitialBarrierHeight > 1 - ? sem_post_multiple (&(b->semBarrierBreeched), - b->nInitialBarrierHeight - 1) : 0); - } - else - { - ptw32_mcs_lock_release(&node); - /* - * Use the non-cancelable version of sem_wait(). - * - * It is possible that all nInitialBarrierHeight-1 threads are - * at this point when the last thread enters the barrier, resets - * nCurrentBarrierHeight = nInitialBarrierHeight and leaves. - * If pthread_barrier_destroy is called at that moment then the - * barrier will be destroyed along with the semas. - */ - result = ptw32_semwait (&(b->semBarrierBreeched)); - } - - if ((PTW32_INTERLOCKED_LONG)PTW32_INTERLOCKED_INCREMENT_LONG((PTW32_INTERLOCKED_LONGPTR)&b->nCurrentBarrierHeight) - == (PTW32_INTERLOCKED_LONG)b->nInitialBarrierHeight) - { - /* - * We are the last thread to cross this barrier - */ - ptw32_mcs_lock_release(&b->proxynode); - if (0 == result) - { - result = PTHREAD_BARRIER_SERIAL_THREAD; - } - } - - return (result); -} diff --git a/pthreads/src/pthread_barrierattr_destroy.c b/pthreads/src/pthread_barrierattr_destroy.c deleted file mode 100644 index 5ab662e..0000000 --- a/pthreads/src/pthread_barrierattr_destroy.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * pthread_barrier_attr_destroy.c - * - * Description: - * This translation unit implements barrier primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_barrierattr_destroy (pthread_barrierattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Destroys a barrier attributes object. The object can - * no longer be used. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_barrierattr_t - * - * - * DESCRIPTION - * Destroys a barrier attributes object. The object can - * no longer be used. - * - * NOTES: - * 1) Does not affect barrieres created using 'attr' - * - * RESULTS - * 0 successfully released attr, - * EINVAL 'attr' is invalid. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - - if (attr == NULL || *attr == NULL) - { - result = EINVAL; - } - else - { - pthread_barrierattr_t ba = *attr; - - *attr = NULL; - free (ba); - } - - return (result); -} /* pthread_barrierattr_destroy */ diff --git a/pthreads/src/pthread_barrierattr_getpshared.c b/pthreads/src/pthread_barrierattr_getpshared.c deleted file mode 100644 index 44c467e..0000000 --- a/pthreads/src/pthread_barrierattr_getpshared.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * pthread_barrier_attr_getpshared.c - * - * Description: - * This translation unit implements barrier primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr, - int *pshared) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Determine whether barriers created with 'attr' can be - * shared between processes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_barrierattr_t - * - * pshared - * will be set to one of: - * - * PTHREAD_PROCESS_SHARED - * May be shared if in shared memory - * - * PTHREAD_PROCESS_PRIVATE - * Cannot be shared. - * - * - * DESCRIPTION - * Mutexes creatd with 'attr' can be shared between - * processes if pthread_barrier_t variable is allocated - * in memory shared by these processes. - * NOTES: - * 1) pshared barriers MUST be allocated in shared - * memory. - * 2) The following macro is defined if shared barriers - * are supported: - * _POSIX_THREAD_PROCESS_SHARED - * - * RESULTS - * 0 successfully retrieved attribute, - * EINVAL 'attr' is invalid, - * - * ------------------------------------------------------ - */ -{ - int result; - - if ((attr != NULL && *attr != NULL) && (pshared != NULL)) - { - *pshared = (*attr)->pshared; - result = 0; - } - else - { - result = EINVAL; - } - - return (result); -} /* pthread_barrierattr_getpshared */ diff --git a/pthreads/src/pthread_barrierattr_init.c b/pthreads/src/pthread_barrierattr_init.c deleted file mode 100644 index 342f8b0..0000000 --- a/pthreads/src/pthread_barrierattr_init.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * pthread_barrier_attr_init.c - * - * Description: - * This translation unit implements barrier primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_barrierattr_init (pthread_barrierattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Initializes a barrier attributes object with default - * attributes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_barrierattr_t - * - * - * DESCRIPTION - * Initializes a barrier attributes object with default - * attributes. - * - * NOTES: - * 1) Used to define barrier types - * - * RESULTS - * 0 successfully initialized attr, - * ENOMEM insufficient memory for attr. - * - * ------------------------------------------------------ - */ -{ - pthread_barrierattr_t ba; - int result = 0; - - ba = (pthread_barrierattr_t) calloc (1, sizeof (*ba)); - - if (ba == NULL) - { - result = ENOMEM; - } - else - { - ba->pshared = PTHREAD_PROCESS_PRIVATE; - } - - *attr = ba; - - return (result); -} /* pthread_barrierattr_init */ diff --git a/pthreads/src/pthread_barrierattr_setpshared.c b/pthreads/src/pthread_barrierattr_setpshared.c deleted file mode 100644 index 08c6fde..0000000 --- a/pthreads/src/pthread_barrierattr_setpshared.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * pthread_barrier_attr_setpshared.c - * - * Description: - * This translation unit implements barrier primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, int pshared) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Barriers created with 'attr' can be shared between - * processes if pthread_barrier_t variable is allocated - * in memory shared by these processes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_barrierattr_t - * - * pshared - * must be one of: - * - * PTHREAD_PROCESS_SHARED - * May be shared if in shared memory - * - * PTHREAD_PROCESS_PRIVATE - * Cannot be shared. - * - * DESCRIPTION - * Mutexes creatd with 'attr' can be shared between - * processes if pthread_barrier_t variable is allocated - * in memory shared by these processes. - * - * NOTES: - * 1) pshared barriers MUST be allocated in shared - * memory. - * - * 2) The following macro is defined if shared barriers - * are supported: - * _POSIX_THREAD_PROCESS_SHARED - * - * RESULTS - * 0 successfully set attribute, - * EINVAL 'attr' or pshared is invalid, - * ENOSYS PTHREAD_PROCESS_SHARED not supported, - * - * ------------------------------------------------------ - */ -{ - int result; - - if ((attr != NULL && *attr != NULL) && - ((pshared == PTHREAD_PROCESS_SHARED) || - (pshared == PTHREAD_PROCESS_PRIVATE))) - { - if (pshared == PTHREAD_PROCESS_SHARED) - { - -#if !defined( _POSIX_THREAD_PROCESS_SHARED ) - - result = ENOSYS; - pshared = PTHREAD_PROCESS_PRIVATE; - -#else - - result = 0; - -#endif /* _POSIX_THREAD_PROCESS_SHARED */ - - } - else - { - result = 0; - } - - (*attr)->pshared = pshared; - } - else - { - result = EINVAL; - } - - return (result); - -} /* pthread_barrierattr_setpshared */ diff --git a/pthreads/src/pthread_cancel.c b/pthreads/src/pthread_cancel.c deleted file mode 100644 index ae60b72..0000000 --- a/pthreads/src/pthread_cancel.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * pthread_cancel.c - * - * Description: - * POSIX thread functions related to thread cancellation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "context.h" - -static void -ptw32_cancel_self (void) -{ - ptw32_throw (PTW32_EPS_CANCEL); - - /* Never reached */ -} - -static void CALLBACK -ptw32_cancel_callback (ULONG_PTR unused) -{ - ptw32_throw (PTW32_EPS_CANCEL); - - /* Never reached */ -} - -/* - * ptw32_RegisterCancelation() - - * Must have args of same type as QueueUserAPCEx because this function - * is a substitute for QueueUserAPCEx if it's not available. - */ -DWORD -ptw32_RegisterCancelation (PAPCFUNC unused1, HANDLE threadH, DWORD unused2) -{ - CONTEXT context; - - context.ContextFlags = CONTEXT_CONTROL; - GetThreadContext (threadH, &context); - PTW32_PROGCTR (context) = (DWORD_PTR) ptw32_cancel_self; - SetThreadContext (threadH, &context); - return 0; -} - -int -pthread_cancel (pthread_t thread) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function requests cancellation of 'thread'. - * - * PARAMETERS - * thread - * reference to an instance of pthread_t - * - * - * DESCRIPTION - * This function requests cancellation of 'thread'. - * NOTE: cancellation is asynchronous; use pthread_join to - * wait for termination of 'thread' if necessary. - * - * RESULTS - * 0 successfully requested cancellation, - * ESRCH no thread found corresponding to 'thread', - * ENOMEM implicit self thread create failed. - * ------------------------------------------------------ - */ -{ - int result; - int cancel_self; - pthread_t self; - ptw32_thread_t * tp; - ptw32_mcs_local_node_t stateLock; - - result = pthread_kill (thread, 0); - - if (0 != result) - { - return result; - } - - if ((self = pthread_self ()).p == NULL) - { - return ENOMEM; - }; - - /* - * For self cancellation we need to ensure that a thread can't - * deadlock itself trying to cancel itself asynchronously - * (pthread_cancel is required to be an async-cancel - * safe function). - */ - cancel_self = pthread_equal (thread, self); - - tp = (ptw32_thread_t *) thread.p; - - /* - * Lock for async-cancel safety. - */ - ptw32_mcs_lock_acquire (&tp->stateLock, &stateLock); - - if (tp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS - && tp->cancelState == PTHREAD_CANCEL_ENABLE - && tp->state < PThreadStateCanceling) - { - if (cancel_self) - { - tp->state = PThreadStateCanceling; - tp->cancelState = PTHREAD_CANCEL_DISABLE; - - ptw32_mcs_lock_release (&stateLock); - ptw32_throw (PTW32_EPS_CANCEL); - - /* Never reached */ - } - else - { - HANDLE threadH = tp->threadH; - - SuspendThread (threadH); - - if (WaitForSingleObject (threadH, 0) == WAIT_TIMEOUT) - { - tp->state = PThreadStateCanceling; - tp->cancelState = PTHREAD_CANCEL_DISABLE; - /* - * If alertdrv and QueueUserAPCEx is available then the following - * will result in a call to QueueUserAPCEx with the args given, otherwise - * this will result in a call to ptw32_RegisterCancelation and only - * the threadH arg will be used. - */ - ptw32_register_cancelation ((PAPCFUNC)ptw32_cancel_callback, threadH, 0); - ptw32_mcs_lock_release (&stateLock); - ResumeThread (threadH); - } - } - } - else - { - /* - * Set for deferred cancellation. - */ - if (tp->state < PThreadStateCancelPending) - { - tp->state = PThreadStateCancelPending; - if (!SetEvent (tp->cancelEvent)) - { - result = ESRCH; - } - } - else if (tp->state >= PThreadStateCanceling) - { - result = ESRCH; - } - - ptw32_mcs_lock_release (&stateLock); - } - - return (result); -} diff --git a/pthreads/src/pthread_cond_destroy.c b/pthreads/src/pthread_cond_destroy.c deleted file mode 100644 index 40d4a08..0000000 --- a/pthreads/src/pthread_cond_destroy.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * pthread_cond_destroy.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -int -pthread_cond_destroy (pthread_cond_t * cond) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function destroys a condition variable - * - * - * PARAMETERS - * cond - * pointer to an instance of pthread_cond_t - * - * - * DESCRIPTION - * This function destroys a condition variable. - * - * NOTES: - * 1) A condition variable can be destroyed - * immediately after all the threads that - * are blocked on it are awakened. e.g. - * - * struct list { - * pthread_mutex_t lm; - * ... - * } - * - * struct elt { - * key k; - * int busy; - * pthread_cond_t notbusy; - * ... - * } - * - * - * struct elt * - * list_find(struct list *lp, key k) - * { - * struct elt *ep; - * - * pthread_mutex_lock(&lp->lm); - * while ((ep = find_elt(l,k) != NULL) && ep->busy) - * pthread_cond_wait(&ep->notbusy, &lp->lm); - * if (ep != NULL) - * ep->busy = 1; - * pthread_mutex_unlock(&lp->lm); - * return(ep); - * } - * - * delete_elt(struct list *lp, struct elt *ep) - * { - * pthread_mutex_lock(&lp->lm); - * assert(ep->busy); - * ... remove ep from list ... - * ep->busy = 0; - * (A) pthread_cond_broadcast(&ep->notbusy); - * pthread_mutex_unlock(&lp->lm); - * (B) pthread_cond_destroy(&rp->notbusy); - * free(ep); - * } - * - * In this example, the condition variable - * and its list element may be freed (line B) - * immediately after all threads waiting for - * it are awakened (line A), since the mutex - * and the code ensure that no other thread - * can touch the element to be deleted. - * - * RESULTS - * 0 successfully released condition variable, - * EINVAL 'cond' is invalid, - * EBUSY 'cond' is in use, - * - * ------------------------------------------------------ - */ -{ - pthread_cond_t cv; - int result = 0, result1 = 0, result2 = 0; - - /* - * Assuming any race condition here is harmless. - */ - if (cond == NULL || *cond == NULL) - { - return EINVAL; - } - - if (*cond != PTHREAD_COND_INITIALIZER) - { - ptw32_mcs_local_node_t node; - ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node); - - cv = *cond; - - /* - * Close the gate; this will synchronize this thread with - * all already signaled waiters to let them retract their - * waiter status - SEE NOTE 1 ABOVE!!! - */ - if (ptw32_semwait (&(cv->semBlockLock)) != 0) /* Non-cancelable */ - { - result = errno; - } - else - { - /* - * !TRY! lock mtxUnblockLock; try will detect busy condition - * and will not cause a deadlock with respect to concurrent - * signal/broadcast. - */ - if ((result = pthread_mutex_trylock (&(cv->mtxUnblockLock))) != 0) - { - (void) sem_post (&(cv->semBlockLock)); - } - } - - if (result != 0) - { - ptw32_mcs_lock_release(&node); - return result; - } - - /* - * Check whether cv is still busy (still has waiters) - */ - if (cv->nWaitersBlocked > cv->nWaitersGone) - { - if (sem_post (&(cv->semBlockLock)) != 0) - { - result = errno; - } - result1 = pthread_mutex_unlock (&(cv->mtxUnblockLock)); - result2 = EBUSY; - } - else - { - /* - * Now it is safe to destroy - */ - *cond = NULL; - - if (sem_destroy (&(cv->semBlockLock)) != 0) - { - result = errno; - } - if (sem_destroy (&(cv->semBlockQueue)) != 0) - { - result1 = errno; - } - if ((result2 = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0) - { - result2 = pthread_mutex_destroy (&(cv->mtxUnblockLock)); - } - - /* Unlink the CV from the list */ - - if (ptw32_cond_list_head == cv) - { - ptw32_cond_list_head = cv->next; - } - else - { - cv->prev->next = cv->next; - } - - if (ptw32_cond_list_tail == cv) - { - ptw32_cond_list_tail = cv->prev; - } - else - { - cv->next->prev = cv->prev; - } - - (void) free (cv); - } - - ptw32_mcs_lock_release(&node); - } - else - { - ptw32_mcs_local_node_t node; - /* - * See notes in ptw32_cond_check_need_init() above also. - */ - ptw32_mcs_lock_acquire(&ptw32_cond_test_init_lock, &node); - - /* - * Check again. - */ - if (*cond == PTHREAD_COND_INITIALIZER) - { - /* - * This is all we need to do to destroy a statically - * initialised cond that has not yet been used (initialised). - * If we get to here, another thread waiting to initialise - * this cond will get an EINVAL. That's OK. - */ - *cond = NULL; - } - else - { - /* - * The cv has been initialised while we were waiting - * so assume it's in use. - */ - result = EBUSY; - } - - ptw32_mcs_lock_release(&node); - } - - return ((result != 0) ? result : ((result1 != 0) ? result1 : result2)); -} diff --git a/pthreads/src/pthread_cond_init.c b/pthreads/src/pthread_cond_init.c deleted file mode 100644 index f28fd67..0000000 --- a/pthreads/src/pthread_cond_init.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * pthread_cond_init.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function initializes a condition variable. - * - * PARAMETERS - * cond - * pointer to an instance of pthread_cond_t - * - * attr - * specifies optional creation attributes. - * - * - * DESCRIPTION - * This function initializes a condition variable. - * - * RESULTS - * 0 successfully created condition variable, - * EINVAL 'attr' is invalid, - * EAGAIN insufficient resources (other than - * memory, - * ENOMEM insufficient memory, - * EBUSY 'cond' is already initialized, - * - * ------------------------------------------------------ - */ -{ - int result; - pthread_cond_t cv = NULL; - - if (cond == NULL) - { - return EINVAL; - } - - if ((attr != NULL && *attr != NULL) && - ((*attr)->pshared == PTHREAD_PROCESS_SHARED)) - { - /* - * Creating condition variable that can be shared between - * processes. - */ - result = ENOSYS; - goto DONE; - } - - cv = (pthread_cond_t) calloc (1, sizeof (*cv)); - - if (cv == NULL) - { - result = ENOMEM; - goto DONE; - } - - cv->nWaitersBlocked = 0; - cv->nWaitersToUnblock = 0; - cv->nWaitersGone = 0; - - if (sem_init (&(cv->semBlockLock), 0, 1) != 0) - { - result = errno; - goto FAIL0; - } - - if (sem_init (&(cv->semBlockQueue), 0, 0) != 0) - { - result = errno; - goto FAIL1; - } - - if ((result = pthread_mutex_init (&(cv->mtxUnblockLock), 0)) != 0) - { - goto FAIL2; - } - - result = 0; - - goto DONE; - - /* - * ------------- - * Failed... - * ------------- - */ -FAIL2: - (void) sem_destroy (&(cv->semBlockQueue)); - -FAIL1: - (void) sem_destroy (&(cv->semBlockLock)); - -FAIL0: - (void) free (cv); - cv = NULL; - -DONE: - if (0 == result) - { - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node); - - cv->next = NULL; - cv->prev = ptw32_cond_list_tail; - - if (ptw32_cond_list_tail != NULL) - { - ptw32_cond_list_tail->next = cv; - } - - ptw32_cond_list_tail = cv; - - if (ptw32_cond_list_head == NULL) - { - ptw32_cond_list_head = cv; - } - - ptw32_mcs_lock_release(&node); - } - - *cond = cv; - - return result; - -} /* pthread_cond_init */ diff --git a/pthreads/src/pthread_cond_signal.c b/pthreads/src/pthread_cond_signal.c deleted file mode 100644 index 2b4f6d4..0000000 --- a/pthreads/src/pthread_cond_signal.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * pthread_cond_signal.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * ------------------------------------------------------------- - * Algorithm: - * See the comments at the top of pthread_cond_wait.c. - */ - -#include "pthread.h" -#include "implement.h" - -static INLINE int -ptw32_cond_unblock (pthread_cond_t * cond, int unblockAll) - /* - * Notes. - * - * Does not use the external mutex for synchronisation, - * therefore semBlockLock is needed. - * mtxUnblockLock is for LEVEL-2 synch. LEVEL-2 is the - * state where the external mutex is not necessarily locked by - * any thread, ie. between cond_wait unlocking and re-acquiring - * the lock after having been signaled or a timeout or - * cancellation. - * - * Uses the following CV elements: - * nWaitersBlocked - * nWaitersToUnblock - * nWaitersGone - * mtxUnblockLock - * semBlockLock - * semBlockQueue - */ -{ - int result; - pthread_cond_t cv; - int nSignalsToIssue; - - if (cond == NULL || *cond == NULL) - { - return EINVAL; - } - - cv = *cond; - - /* - * No-op if the CV is static and hasn't been initialised yet. - * Assuming that any race condition is harmless. - */ - if (cv == PTHREAD_COND_INITIALIZER) - { - return 0; - } - - if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0) - { - return result; - } - - if (0 != cv->nWaitersToUnblock) - { - if (0 == cv->nWaitersBlocked) - { - return pthread_mutex_unlock (&(cv->mtxUnblockLock)); - } - if (unblockAll) - { - cv->nWaitersToUnblock += (nSignalsToIssue = cv->nWaitersBlocked); - cv->nWaitersBlocked = 0; - } - else - { - nSignalsToIssue = 1; - cv->nWaitersToUnblock++; - cv->nWaitersBlocked--; - } - } - else if (cv->nWaitersBlocked > cv->nWaitersGone) - { - /* Use the non-cancellable version of sem_wait() */ - if (ptw32_semwait (&(cv->semBlockLock)) != 0) - { - result = errno; - (void) pthread_mutex_unlock (&(cv->mtxUnblockLock)); - return result; - } - if (0 != cv->nWaitersGone) - { - cv->nWaitersBlocked -= cv->nWaitersGone; - cv->nWaitersGone = 0; - } - if (unblockAll) - { - nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked; - cv->nWaitersBlocked = 0; - } - else - { - nSignalsToIssue = cv->nWaitersToUnblock = 1; - cv->nWaitersBlocked--; - } - } - else - { - return pthread_mutex_unlock (&(cv->mtxUnblockLock)); - } - - if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0) - { - if (sem_post_multiple (&(cv->semBlockQueue), nSignalsToIssue) != 0) - { - result = errno; - } - } - - return result; - -} /* ptw32_cond_unblock */ - -int -pthread_cond_signal (pthread_cond_t * cond) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function signals a condition variable, waking - * one waiting thread. - * If SCHED_FIFO or SCHED_RR policy threads are waiting - * the highest priority waiter is awakened; otherwise, - * an unspecified waiter is awakened. - * - * PARAMETERS - * cond - * pointer to an instance of pthread_cond_t - * - * - * DESCRIPTION - * This function signals a condition variable, waking - * one waiting thread. - * If SCHED_FIFO or SCHED_RR policy threads are waiting - * the highest priority waiter is awakened; otherwise, - * an unspecified waiter is awakened. - * - * NOTES: - * - * 1) Use when any waiter can respond and only one need - * respond (all waiters being equal). - * - * RESULTS - * 0 successfully signaled condition, - * EINVAL 'cond' is invalid, - * - * ------------------------------------------------------ - */ -{ - /* - * The '0'(FALSE) unblockAll arg means unblock ONE waiter. - */ - return (ptw32_cond_unblock (cond, 0)); - -} /* pthread_cond_signal */ - -int -pthread_cond_broadcast (pthread_cond_t * cond) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function broadcasts the condition variable, - * waking all current waiters. - * - * PARAMETERS - * cond - * pointer to an instance of pthread_cond_t - * - * - * DESCRIPTION - * This function signals a condition variable, waking - * all waiting threads. - * - * NOTES: - * - * 1) Use when more than one waiter may respond to - * predicate change or if any waiting thread may - * not be able to respond - * - * RESULTS - * 0 successfully signalled condition to all - * waiting threads, - * EINVAL 'cond' is invalid - * ENOSPC a required resource has been exhausted, - * - * ------------------------------------------------------ - */ -{ - /* - * The TRUE unblockAll arg means unblock ALL waiters. - */ - return (ptw32_cond_unblock (cond, PTW32_TRUE)); - -} /* pthread_cond_broadcast */ diff --git a/pthreads/src/pthread_cond_wait.c b/pthreads/src/pthread_cond_wait.c deleted file mode 100644 index 359219a..0000000 --- a/pthreads/src/pthread_cond_wait.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * pthread_cond_wait.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * ------------------------------------------------------------- - * Algorithm: - * The algorithm used in this implementation is that developed by - * Alexander Terekhov in colaboration with Louis Thomas. The bulk - * of the discussion is recorded in the file README.CV, which contains - * several generations of both colaborators original algorithms. The final - * algorithm used here is the one referred to as - * - * Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL - * - * presented below in pseudo-code as it appeared: - * - * - * given: - * semBlockLock - bin.semaphore - * semBlockQueue - semaphore - * mtxExternal - mutex or CS - * mtxUnblockLock - mutex or CS - * nWaitersGone - int - * nWaitersBlocked - int - * nWaitersToUnblock - int - * - * wait( timeout ) { - * - * [auto: register int result ] // error checking omitted - * [auto: register int nSignalsWasLeft ] - * [auto: register int nWaitersWasGone ] - * - * sem_wait( semBlockLock ); - * nWaitersBlocked++; - * sem_post( semBlockLock ); - * - * unlock( mtxExternal ); - * bTimedOut = sem_wait( semBlockQueue,timeout ); - * - * lock( mtxUnblockLock ); - * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { - * if ( bTimeout ) { // timeout (or canceled) - * if ( 0 != nWaitersBlocked ) { - * nWaitersBlocked--; - * } - * else { - * nWaitersGone++; // count spurious wakeups. - * } - * } - * if ( 0 == --nWaitersToUnblock ) { - * if ( 0 != nWaitersBlocked ) { - * sem_post( semBlockLock ); // open the gate. - * nSignalsWasLeft = 0; // do not open the gate - * // below again. - * } - * else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { - * nWaitersGone = 0; - * } - * } - * } - * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or - * // spurious semaphore :-) - * sem_wait( semBlockLock ); - * nWaitersBlocked -= nWaitersGone; // something is going on here - * // - test of timeouts? :-) - * sem_post( semBlockLock ); - * nWaitersGone = 0; - * } - * unlock( mtxUnblockLock ); - * - * if ( 1 == nSignalsWasLeft ) { - * if ( 0 != nWaitersWasGone ) { - * // sem_adjust( semBlockQueue,-nWaitersWasGone ); - * while ( nWaitersWasGone-- ) { - * sem_wait( semBlockQueue ); // better now than spurious later - * } - * } sem_post( semBlockLock ); // open the gate - * } - * - * lock( mtxExternal ); - * - * return ( bTimedOut ) ? ETIMEOUT : 0; - * } - * - * signal(bAll) { - * - * [auto: register int result ] - * [auto: register int nSignalsToIssue] - * - * lock( mtxUnblockLock ); - * - * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! - * if ( 0 == nWaitersBlocked ) { // NO-OP - * return unlock( mtxUnblockLock ); - * } - * if (bAll) { - * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; - * nWaitersBlocked = 0; - * } - * else { - * nSignalsToIssue = 1; - * nWaitersToUnblock++; - * nWaitersBlocked--; - * } - * } - * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! - * sem_wait( semBlockLock ); // close the gate - * if ( 0 != nWaitersGone ) { - * nWaitersBlocked -= nWaitersGone; - * nWaitersGone = 0; - * } - * if (bAll) { - * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; - * nWaitersBlocked = 0; - * } - * else { - * nSignalsToIssue = nWaitersToUnblock = 1; - * nWaitersBlocked--; - * } - * } - * else { // NO-OP - * return unlock( mtxUnblockLock ); - * } - * - * unlock( mtxUnblockLock ); - * sem_post( semBlockQueue,nSignalsToIssue ); - * return result; - * } - * ------------------------------------------------------------- - * - * Algorithm 9 / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL - * - * presented below in pseudo-code; basically 8a... - * ...BUT W/O "spurious wakes" prevention: - * - * - * given: - * semBlockLock - bin.semaphore - * semBlockQueue - semaphore - * mtxExternal - mutex or CS - * mtxUnblockLock - mutex or CS - * nWaitersGone - int - * nWaitersBlocked - int - * nWaitersToUnblock - int - * - * wait( timeout ) { - * - * [auto: register int result ] // error checking omitted - * [auto: register int nSignalsWasLeft ] - * - * sem_wait( semBlockLock ); - * ++nWaitersBlocked; - * sem_post( semBlockLock ); - * - * unlock( mtxExternal ); - * bTimedOut = sem_wait( semBlockQueue,timeout ); - * - * lock( mtxUnblockLock ); - * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { - * --nWaitersToUnblock; - * } - * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or - * // spurious semaphore :-) - * sem_wait( semBlockLock ); - * nWaitersBlocked -= nWaitersGone; // something is going on here - * // - test of timeouts? :-) - * sem_post( semBlockLock ); - * nWaitersGone = 0; - * } - * unlock( mtxUnblockLock ); - * - * if ( 1 == nSignalsWasLeft ) { - * sem_post( semBlockLock ); // open the gate - * } - * - * lock( mtxExternal ); - * - * return ( bTimedOut ) ? ETIMEOUT : 0; - * } - * - * signal(bAll) { - * - * [auto: register int result ] - * [auto: register int nSignalsToIssue] - * - * lock( mtxUnblockLock ); - * - * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! - * if ( 0 == nWaitersBlocked ) { // NO-OP - * return unlock( mtxUnblockLock ); - * } - * if (bAll) { - * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; - * nWaitersBlocked = 0; - * } - * else { - * nSignalsToIssue = 1; - * ++nWaitersToUnblock; - * --nWaitersBlocked; - * } - * } - * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! - * sem_wait( semBlockLock ); // close the gate - * if ( 0 != nWaitersGone ) { - * nWaitersBlocked -= nWaitersGone; - * nWaitersGone = 0; - * } - * if (bAll) { - * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; - * nWaitersBlocked = 0; - * } - * else { - * nSignalsToIssue = nWaitersToUnblock = 1; - * --nWaitersBlocked; - * } - * } - * else { // NO-OP - * return unlock( mtxUnblockLock ); - * } - * - * unlock( mtxUnblockLock ); - * sem_post( semBlockQueue,nSignalsToIssue ); - * return result; - * } - * ------------------------------------------------------------- - * - */ - -#include "pthread.h" -#include "implement.h" - -/* - * Arguments for cond_wait_cleanup, since we can only pass a - * single void * to it. - */ -typedef struct -{ - pthread_mutex_t *mutexPtr; - pthread_cond_t cv; - int *resultPtr; -} ptw32_cond_wait_cleanup_args_t; - -static void PTW32_CDECL -ptw32_cond_wait_cleanup (void *args) -{ - ptw32_cond_wait_cleanup_args_t *cleanup_args = - (ptw32_cond_wait_cleanup_args_t *) args; - pthread_cond_t cv = cleanup_args->cv; - int *resultPtr = cleanup_args->resultPtr; - int nSignalsWasLeft; - int result; - - /* - * Whether we got here as a result of signal/broadcast or because of - * timeout on wait or thread cancellation we indicate that we are no - * longer waiting. The waiter is responsible for adjusting waiters - * (to)unblock(ed) counts (protected by unblock lock). - */ - if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0) - { - *resultPtr = result; - return; - } - - if (0 != (nSignalsWasLeft = cv->nWaitersToUnblock)) - { - --(cv->nWaitersToUnblock); - } - else if (INT_MAX / 2 == ++(cv->nWaitersGone)) - { - /* Use the non-cancellable version of sem_wait() */ - if (ptw32_semwait (&(cv->semBlockLock)) != 0) - { - *resultPtr = errno; - /* - * This is a fatal error for this CV, - * so we deliberately don't unlock - * cv->mtxUnblockLock before returning. - */ - return; - } - cv->nWaitersBlocked -= cv->nWaitersGone; - if (sem_post (&(cv->semBlockLock)) != 0) - { - *resultPtr = errno; - /* - * This is a fatal error for this CV, - * so we deliberately don't unlock - * cv->mtxUnblockLock before returning. - */ - return; - } - cv->nWaitersGone = 0; - } - - if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) != 0) - { - *resultPtr = result; - return; - } - - if (1 == nSignalsWasLeft) - { - if (sem_post (&(cv->semBlockLock)) != 0) - { - *resultPtr = errno; - return; - } - } - - /* - * XSH: Upon successful return, the mutex has been locked and is owned - * by the calling thread. - */ - if ((result = pthread_mutex_lock (cleanup_args->mutexPtr)) != 0) - { - *resultPtr = result; - } -} /* ptw32_cond_wait_cleanup */ - -static INLINE int -ptw32_cond_timedwait (pthread_cond_t * cond, - pthread_mutex_t * mutex, const struct timespec *abstime) -{ - int result = 0; - pthread_cond_t cv; - ptw32_cond_wait_cleanup_args_t cleanup_args; - - if (cond == NULL || *cond == NULL) - { - return EINVAL; - } - - /* - * We do a quick check to see if we need to do more work - * to initialise a static condition variable. We check - * again inside the guarded section of ptw32_cond_check_need_init() - * to avoid race conditions. - */ - if (*cond == PTHREAD_COND_INITIALIZER) - { - result = ptw32_cond_check_need_init (cond); - } - - if (result != 0 && result != EBUSY) - { - return result; - } - - cv = *cond; - - /* Thread can be cancelled in sem_wait() but this is OK */ - if (sem_wait (&(cv->semBlockLock)) != 0) - { - return errno; - } - - ++(cv->nWaitersBlocked); - - if (sem_post (&(cv->semBlockLock)) != 0) - { - return errno; - } - - /* - * Setup this waiter cleanup handler - */ - cleanup_args.mutexPtr = mutex; - cleanup_args.cv = cv; - cleanup_args.resultPtr = &result; - -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth(0) -#endif - pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args); - - /* - * Now we can release 'mutex' and... - */ - if ((result = pthread_mutex_unlock (mutex)) == 0) - { - - /* - * ...wait to be awakened by - * pthread_cond_signal, or - * pthread_cond_broadcast, or - * timeout, or - * thread cancellation - * - * Note: - * - * sem_timedwait is a cancellation point, - * hence providing the mechanism for making - * pthread_cond_wait a cancellation point. - * We use the cleanup mechanism to ensure we - * re-lock the mutex and adjust (to)unblock(ed) waiters - * counts if we are cancelled, timed out or signalled. - */ - if (sem_timedwait (&(cv->semBlockQueue), abstime) != 0) - { - result = errno; - } - } - - /* - * Always cleanup - */ - pthread_cleanup_pop (1); -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth() -#endif - - /* - * "result" can be modified by the cleanup handler. - */ - return result; - -} /* ptw32_cond_timedwait */ - - -int -pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function waits on a condition variable until - * awakened by a signal or broadcast. - * - * Caller MUST be holding the mutex lock; the - * lock is released and the caller is blocked waiting - * on 'cond'. When 'cond' is signaled, the mutex - * is re-acquired before returning to the caller. - * - * PARAMETERS - * cond - * pointer to an instance of pthread_cond_t - * - * mutex - * pointer to an instance of pthread_mutex_t - * - * - * DESCRIPTION - * This function waits on a condition variable until - * awakened by a signal or broadcast. - * - * NOTES: - * - * 1) The function must be called with 'mutex' LOCKED - * by the calling thread, or undefined behaviour - * will result. - * - * 2) This routine atomically releases 'mutex' and causes - * the calling thread to block on the condition variable. - * The blocked thread may be awakened by - * pthread_cond_signal or - * pthread_cond_broadcast. - * - * Upon successful completion, the 'mutex' has been locked and - * is owned by the calling thread. - * - * - * RESULTS - * 0 caught condition; mutex released, - * EINVAL 'cond' or 'mutex' is invalid, - * EINVAL different mutexes for concurrent waits, - * EINVAL mutex is not held by the calling thread, - * - * ------------------------------------------------------ - */ -{ - /* - * The NULL abstime arg means INFINITE waiting. - */ - return (ptw32_cond_timedwait (cond, mutex, NULL)); - -} /* pthread_cond_wait */ - - -int -pthread_cond_timedwait (pthread_cond_t * cond, - pthread_mutex_t * mutex, - const struct timespec *abstime) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function waits on a condition variable either until - * awakened by a signal or broadcast; or until the time - * specified by abstime passes. - * - * PARAMETERS - * cond - * pointer to an instance of pthread_cond_t - * - * mutex - * pointer to an instance of pthread_mutex_t - * - * abstime - * pointer to an instance of (const struct timespec) - * - * - * DESCRIPTION - * This function waits on a condition variable either until - * awakened by a signal or broadcast; or until the time - * specified by abstime passes. - * - * NOTES: - * 1) The function must be called with 'mutex' LOCKED - * by the calling thread, or undefined behaviour - * will result. - * - * 2) This routine atomically releases 'mutex' and causes - * the calling thread to block on the condition variable. - * The blocked thread may be awakened by - * pthread_cond_signal or - * pthread_cond_broadcast. - * - * - * RESULTS - * 0 caught condition; mutex released, - * EINVAL 'cond', 'mutex', or abstime is invalid, - * EINVAL different mutexes for concurrent waits, - * EINVAL mutex is not held by the calling thread, - * ETIMEDOUT abstime ellapsed before cond was signaled. - * - * ------------------------------------------------------ - */ -{ - if (abstime == NULL) - { - return EINVAL; - } - - return (ptw32_cond_timedwait (cond, mutex, abstime)); - -} /* pthread_cond_timedwait */ diff --git a/pthreads/src/pthread_condattr_destroy.c b/pthreads/src/pthread_condattr_destroy.c deleted file mode 100644 index 58a1482..0000000 --- a/pthreads/src/pthread_condattr_destroy.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * condvar_attr_destroy.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_condattr_destroy (pthread_condattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Destroys a condition variable attributes object. - * The object can no longer be used. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_condattr_t - * - * - * DESCRIPTION - * Destroys a condition variable attributes object. - * The object can no longer be used. - * - * NOTES: - * 1) Does not affect condition variables created - * using 'attr' - * - * RESULTS - * 0 successfully released attr, - * EINVAL 'attr' is invalid. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - - if (attr == NULL || *attr == NULL) - { - result = EINVAL; - } - else - { - (void) free (*attr); - - *attr = NULL; - result = 0; - } - - return result; - -} /* pthread_condattr_destroy */ diff --git a/pthreads/src/pthread_condattr_getpshared.c b/pthreads/src/pthread_condattr_getpshared.c deleted file mode 100644 index a0ac6d8..0000000 --- a/pthreads/src/pthread_condattr_getpshared.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * pthread_condattr_getpshared.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Determine whether condition variables created with 'attr' - * can be shared between processes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_condattr_t - * - * pshared - * will be set to one of: - * - * PTHREAD_PROCESS_SHARED - * May be shared if in shared memory - * - * PTHREAD_PROCESS_PRIVATE - * Cannot be shared. - * - * - * DESCRIPTION - * Condition Variables created with 'attr' can be shared - * between processes if pthread_cond_t variable is allocated - * in memory shared by these processes. - * NOTES: - * 1) pshared condition variables MUST be allocated in - * shared memory. - * - * 2) The following macro is defined if shared mutexes - * are supported: - * _POSIX_THREAD_PROCESS_SHARED - * - * RESULTS - * 0 successfully retrieved attribute, - * EINVAL 'attr' or 'pshared' is invalid, - * - * ------------------------------------------------------ - */ -{ - int result; - - if ((attr != NULL && *attr != NULL) && (pshared != NULL)) - { - *pshared = (*attr)->pshared; - result = 0; - } - else - { - result = EINVAL; - } - - return result; - -} /* pthread_condattr_getpshared */ diff --git a/pthreads/src/pthread_condattr_init.c b/pthreads/src/pthread_condattr_init.c deleted file mode 100644 index 5987878..0000000 --- a/pthreads/src/pthread_condattr_init.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * pthread_condattr_init.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_condattr_init (pthread_condattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Initializes a condition variable attributes object - * with default attributes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_condattr_t - * - * - * DESCRIPTION - * Initializes a condition variable attributes object - * with default attributes. - * - * NOTES: - * 1) Use to define condition variable types - * 2) It is up to the application to ensure - * that it doesn't re-init an attribute - * without destroying it first. Otherwise - * a memory leak is created. - * - * RESULTS - * 0 successfully initialized attr, - * ENOMEM insufficient memory for attr. - * - * ------------------------------------------------------ - */ -{ - pthread_condattr_t attr_result; - int result = 0; - - attr_result = (pthread_condattr_t) calloc (1, sizeof (*attr_result)); - - if (attr_result == NULL) - { - result = ENOMEM; - } - - *attr = attr_result; - - return result; - -} /* pthread_condattr_init */ diff --git a/pthreads/src/pthread_condattr_setpshared.c b/pthreads/src/pthread_condattr_setpshared.c deleted file mode 100644 index 954fb38..0000000 --- a/pthreads/src/pthread_condattr_setpshared.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * pthread_condattr_setpshared.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Mutexes created with 'attr' can be shared between - * processes if pthread_mutex_t variable is allocated - * in memory shared by these processes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_mutexattr_t - * - * pshared - * must be one of: - * - * PTHREAD_PROCESS_SHARED - * May be shared if in shared memory - * - * PTHREAD_PROCESS_PRIVATE - * Cannot be shared. - * - * DESCRIPTION - * Mutexes creatd with 'attr' can be shared between - * processes if pthread_mutex_t variable is allocated - * in memory shared by these processes. - * - * NOTES: - * 1) pshared mutexes MUST be allocated in shared - * memory. - * - * 2) The following macro is defined if shared mutexes - * are supported: - * _POSIX_THREAD_PROCESS_SHARED - * - * RESULTS - * 0 successfully set attribute, - * EINVAL 'attr' or pshared is invalid, - * ENOSYS PTHREAD_PROCESS_SHARED not supported, - * - * ------------------------------------------------------ - */ -{ - int result; - - if ((attr != NULL && *attr != NULL) - && ((pshared == PTHREAD_PROCESS_SHARED) - || (pshared == PTHREAD_PROCESS_PRIVATE))) - { - if (pshared == PTHREAD_PROCESS_SHARED) - { - -#if !defined( _POSIX_THREAD_PROCESS_SHARED ) - result = ENOSYS; - pshared = PTHREAD_PROCESS_PRIVATE; -#else - result = 0; - -#endif /* _POSIX_THREAD_PROCESS_SHARED */ - - } - else - { - result = 0; - } - - (*attr)->pshared = pshared; - } - else - { - result = EINVAL; - } - - return result; - -} /* pthread_condattr_setpshared */ diff --git a/pthreads/src/pthread_delay_np.c b/pthreads/src/pthread_delay_np.c deleted file mode 100644 index e6c96d8..0000000 --- a/pthreads/src/pthread_delay_np.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * pthreads_delay_np.c - * - * Description: - * This translation unit implements non-portable thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * pthread_delay_np - * - * DESCRIPTION - * - * This routine causes a thread to delay execution for a specific period of time. - * This period ends at the current time plus the specified interval. The routine - * will not return before the end of the period is reached, but may return an - * arbitrary amount of time after the period has gone by. This can be due to - * system load, thread priorities, and system timer granularity. - * - * Specifying an interval of zero (0) seconds and zero (0) nanoseconds is - * allowed and can be used to force the thread to give up the processor or to - * deliver a pending cancelation request. - * - * The timespec structure contains the following two fields: - * - * tv_sec is an integer number of seconds. - * tv_nsec is an integer number of nanoseconds. - * - * Return Values - * - * If an error condition occurs, this routine returns an integer value indicating - * the type of error. Possible return values are as follows: - * - * 0 - * Successful completion. - * [EINVAL] - * The value specified by interval is invalid. - * - * Example - * - * The following code segment would wait for 5 and 1/2 seconds - * - * struct timespec tsWait; - * int intRC; - * - * tsWait.tv_sec = 5; - * tsWait.tv_nsec = 500000000L; - * intRC = pthread_delay_np(&tsWait); - */ -int -pthread_delay_np (struct timespec *interval) -{ - DWORD wait_time; - DWORD secs_in_millisecs; - DWORD millisecs; - DWORD status; - pthread_t self; - ptw32_thread_t * sp; - - if (interval == NULL) - { - return EINVAL; - } - - if (interval->tv_sec == 0L && interval->tv_nsec == 0L) - { - pthread_testcancel (); - Sleep (0); - pthread_testcancel (); - return (0); - } - - /* convert secs to millisecs */ - secs_in_millisecs = (DWORD)interval->tv_sec * 1000L; - - /* convert nanosecs to millisecs (rounding up) */ - millisecs = (interval->tv_nsec + 999999L) / 1000000L; - -#if defined(__WATCOMC__) -#pragma disable_message (124) -#endif - - /* - * Most compilers will issue a warning 'comparison always 0' - * because the variable type is unsigned, but we need to keep this - * for some reason I can't recall now. - */ - if (0 > (wait_time = secs_in_millisecs + millisecs)) - { - return EINVAL; - } - -#if defined(__WATCOMC__) -#pragma enable_message (124) -#endif - - if (NULL == (self = pthread_self ()).p) - { - return ENOMEM; - } - - sp = (ptw32_thread_t *) self.p; - - if (sp->cancelState == PTHREAD_CANCEL_ENABLE) - { - /* - * Async cancelation won't catch us until wait_time is up. - * Deferred cancelation will cancel us immediately. - */ - if (WAIT_OBJECT_0 == - (status = WaitForSingleObject (sp->cancelEvent, wait_time))) - { - ptw32_mcs_local_node_t stateLock; - /* - * Canceling! - */ - ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); - if (sp->state < PThreadStateCanceling) - { - sp->state = PThreadStateCanceling; - sp->cancelState = PTHREAD_CANCEL_DISABLE; - ptw32_mcs_lock_release (&stateLock); - - ptw32_throw (PTW32_EPS_CANCEL); - } - - ptw32_mcs_lock_release (&stateLock); - return ESRCH; - } - else if (status != WAIT_TIMEOUT) - { - return EINVAL; - } - } - else - { - Sleep (wait_time); - } - - return (0); -} diff --git a/pthreads/src/pthread_detach.c b/pthreads/src/pthread_detach.c deleted file mode 100644 index 9ff6587..0000000 --- a/pthreads/src/pthread_detach.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * pthread_detach.c - * - * Description: - * This translation unit implements functions related to thread - * synchronisation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * Not needed yet, but defining it should indicate clashes with build target - * environment that should be fixed. - */ -#if !defined(WINCE) -# include -#endif - - -int -pthread_detach (pthread_t thread) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function detaches the given thread. - * - * PARAMETERS - * thread - * an instance of a pthread_t - * - * - * DESCRIPTION - * This function detaches the given thread. You may use it to - * detach the main thread or to detach a joinable thread. - * NOTE: detached threads cannot be joined; - * storage is freed immediately on termination. - * - * RESULTS - * 0 successfully detached the thread, - * EINVAL thread is not a joinable thread, - * ENOSPC a required resource has been exhausted, - * ESRCH no thread could be found for 'thread', - * - * ------------------------------------------------------ - */ -{ - int result; - BOOL destroyIt = PTW32_FALSE; - ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); - - if (NULL == tp - || thread.x != tp->ptHandle.x) - { - result = ESRCH; - } - else if (PTHREAD_CREATE_DETACHED == tp->detachState) - { - result = EINVAL; - } - else - { - ptw32_mcs_local_node_t stateLock; - /* - * Joinable ptw32_thread_t structs are not scavenged until - * a join or detach is done. The thread may have exited already, - * but all of the state and locks etc are still there. - */ - result = 0; - - ptw32_mcs_lock_acquire (&tp->stateLock, &stateLock); - if (tp->state != PThreadStateLast) - { - tp->detachState = PTHREAD_CREATE_DETACHED; - } - else if (tp->detachState != PTHREAD_CREATE_DETACHED) - { - /* - * Thread is joinable and has exited or is exiting. - */ - destroyIt = PTW32_TRUE; - } - ptw32_mcs_lock_release (&stateLock); - } - - ptw32_mcs_lock_release(&node); - - if (result == 0) - { - /* Thread is joinable */ - - if (destroyIt) - { - /* The thread has exited or is exiting but has not been joined or - * detached. Need to wait in case it's still exiting. - */ - (void) WaitForSingleObject(tp->threadH, INFINITE); - ptw32_threadDestroy (thread); - } - } - - return (result); - -} /* pthread_detach */ diff --git a/pthreads/src/pthread_equal.c b/pthreads/src/pthread_equal.c deleted file mode 100644 index 5ddd82a..0000000 --- a/pthreads/src/pthread_equal.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * pthread_equal.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_equal (pthread_t t1, pthread_t t2) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function returns nonzero if t1 and t2 are equal, else - * returns zero - * - * PARAMETERS - * t1, - * t2 - * thread IDs - * - * - * DESCRIPTION - * This function returns nonzero if t1 and t2 are equal, else - * returns zero. - * - * RESULTS - * non-zero if t1 and t2 refer to the same thread, - * 0 t1 and t2 do not refer to the same thread - * - * ------------------------------------------------------ - */ -{ - int result; - - /* - * We also accept NULL == NULL - treating NULL as a thread - * for this special case, because there is no error that we can return. - */ - result = ( t1.p == t2.p && t1.x == t2.x ); - - return (result); - -} /* pthread_equal */ diff --git a/pthreads/src/pthread_exit.c b/pthreads/src/pthread_exit.c deleted file mode 100644 index 37b3c09..0000000 --- a/pthreads/src/pthread_exit.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * pthread_exit.c - * - * Description: - * This translation unit implements routines associated with exiting from - * a thread. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#if !defined(_UWIN) -/*# include */ -#endif - -void -pthread_exit (void *value_ptr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function terminates the calling thread, returning - * the value 'value_ptr' to any joining thread. - * - * PARAMETERS - * value_ptr - * a generic data value (i.e. not the address of a value) - * - * - * DESCRIPTION - * This function terminates the calling thread, returning - * the value 'value_ptr' to any joining thread. - * NOTE: thread should be joinable. - * - * RESULTS - * N/A - * - * ------------------------------------------------------ - */ -{ - ptw32_thread_t * sp; - - /* - * Don't use pthread_self() to avoid creating an implicit POSIX thread handle - * unnecessarily. - */ - sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); - -#if defined(_UWIN) - if (--pthread_count <= 0) - exit ((int) value_ptr); -#endif - - if (NULL == sp) - { - /* - * A POSIX thread handle was never created. I.e. this is a - * Win32 thread that has never called a pthreads-win32 routine that - * required a POSIX handle. - * - * Implicit POSIX handles are cleaned up in ptw32_throw() now. - */ - -#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__) - _endthreadex ((unsigned) (size_t) value_ptr); -#else - _endthread (); -#endif - - /* Never reached */ - } - - sp->exitStatus = value_ptr; - - ptw32_throw (PTW32_EPS_EXIT); - - /* Never reached. */ - -} diff --git a/pthreads/src/pthread_getconcurrency.c b/pthreads/src/pthread_getconcurrency.c deleted file mode 100644 index cf9e9c8..0000000 --- a/pthreads/src/pthread_getconcurrency.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * pthread_getconcurrency.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_getconcurrency (void) -{ - return ptw32_concurrency; -} diff --git a/pthreads/src/pthread_getschedparam.c b/pthreads/src/pthread_getschedparam.c deleted file mode 100644 index 0afcfb7..0000000 --- a/pthreads/src/pthread_getschedparam.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * sched_getschedparam.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -pthread_getschedparam (pthread_t thread, int *policy, - struct sched_param *param) -{ - int result; - - /* Validate the thread id. */ - result = pthread_kill (thread, 0); - if (0 != result) - { - return result; - } - - /* - * Validate the policy and param args. - * Check that a policy constant wasn't passed rather than &policy. - */ - if (policy <= (int *) SCHED_MAX || param == NULL) - { - return EINVAL; - } - - /* Fill out the policy. */ - *policy = SCHED_OTHER; - - /* - * This function must return the priority value set by - * the most recent pthread_setschedparam() or pthread_create() - * for the target thread. It must not return the actual thread - * priority as altered by any system priority adjustments etc. - */ - param->sched_priority = ((ptw32_thread_t *)thread.p)->sched_priority; - - return 0; -} diff --git a/pthreads/src/pthread_getspecific.c b/pthreads/src/pthread_getspecific.c deleted file mode 100644 index 5ee1641..0000000 --- a/pthreads/src/pthread_getspecific.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * pthread_getspecific.c - * - * Description: - * POSIX thread functions which implement thread-specific data (TSD). - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -void * -pthread_getspecific (pthread_key_t key) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function returns the current value of key in the - * calling thread. If no value has been set for 'key' in - * the thread, NULL is returned. - * - * PARAMETERS - * key - * an instance of pthread_key_t - * - * - * DESCRIPTION - * This function returns the current value of key in the - * calling thread. If no value has been set for 'key' in - * the thread, NULL is returned. - * - * RESULTS - * key value or NULL on failure - * - * ------------------------------------------------------ - */ -{ - void * ptr; - - if (key == NULL) - { - ptr = NULL; - } - else - { - int lasterror = GetLastError (); -#if defined(RETAIN_WSALASTERROR) - int lastWSAerror = WSAGetLastError (); -#endif - ptr = TlsGetValue (key->key); - - SetLastError (lasterror); -#if defined(RETAIN_WSALASTERROR) - WSASetLastError (lastWSAerror); -#endif - } - - return ptr; -} diff --git a/pthreads/src/pthread_getunique_np.c b/pthreads/src/pthread_getunique_np.c deleted file mode 100644 index 4496c68..0000000 --- a/pthreads/src/pthread_getunique_np.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * pthread_getunique_np.c - * - * Description: - * This translation unit implements non-portable thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * - */ -unsigned __int64 -pthread_getunique_np (pthread_t thread) -{ - return ((ptw32_thread_t*)thread.p)->seqNumber; -} diff --git a/pthreads/src/pthread_getw32threadhandle_np.c b/pthreads/src/pthread_getw32threadhandle_np.c deleted file mode 100644 index 309a8f2..0000000 --- a/pthreads/src/pthread_getw32threadhandle_np.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * pthread_getw32threadhandle_np.c - * - * Description: - * This translation unit implements non-portable thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * pthread_getw32threadhandle_np() - * - * Returns the win32 thread handle that the POSIX - * thread "thread" is running as. - * - * Applications can use the win32 handle to set - * win32 specific attributes of the thread. - */ -HANDLE -pthread_getw32threadhandle_np (pthread_t thread) -{ - return ((ptw32_thread_t *)thread.p)->threadH; -} - -/* - * pthread_getw32threadid_np() - * - * Returns the win32 thread id that the POSIX - * thread "thread" is running as. - */ -DWORD -pthread_getw32threadid_np (pthread_t thread) -{ - return ((ptw32_thread_t *)thread.p)->thread; -} diff --git a/pthreads/src/pthread_join.c b/pthreads/src/pthread_join.c deleted file mode 100644 index c2b7c1e..0000000 --- a/pthreads/src/pthread_join.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * pthread_join.c - * - * Description: - * This translation unit implements functions related to thread - * synchronisation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * Not needed yet, but defining it should indicate clashes with build target - * environment that should be fixed. - */ -#if !defined(WINCE) -# include -#endif - - -int -pthread_join (pthread_t thread, void **value_ptr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function waits for 'thread' to terminate and - * returns the thread's exit value if 'value_ptr' is not - * NULL. This also detaches the thread on successful - * completion. - * - * PARAMETERS - * thread - * an instance of pthread_t - * - * value_ptr - * pointer to an instance of pointer to void - * - * - * DESCRIPTION - * This function waits for 'thread' to terminate and - * returns the thread's exit value if 'value_ptr' is not - * NULL. This also detaches the thread on successful - * completion. - * NOTE: detached threads cannot be joined or canceled - * - * RESULTS - * 0 'thread' has completed - * EINVAL thread is not a joinable thread, - * ESRCH no thread could be found with ID 'thread', - * ENOENT thread couldn't find it's own valid handle, - * EDEADLK attempt to join thread with self - * - * ------------------------------------------------------ - */ -{ - int result; - pthread_t self; - ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); - - if (NULL == tp - || thread.x != tp->ptHandle.x) - { - result = ESRCH; - } - else if (PTHREAD_CREATE_DETACHED == tp->detachState) - { - result = EINVAL; - } - else - { - result = 0; - } - - ptw32_mcs_lock_release(&node); - - if (result == 0) - { - /* - * The target thread is joinable and can't be reused before we join it. - */ - self = pthread_self(); - - if (NULL == self.p) - { - result = ENOENT; - } - else if (pthread_equal (self, thread)) - { - result = EDEADLK; - } - else - { - /* - * Pthread_join is a cancelation point. - * If we are canceled then our target thread must not be - * detached (destroyed). This is guarranteed because - * pthreadCancelableWait will not return if we - * are canceled. - */ - result = pthreadCancelableWait (tp->threadH); - - if (0 == result) - { - if (value_ptr != NULL) - { - *value_ptr = tp->exitStatus; - } - - /* - * The result of making multiple simultaneous calls to - * pthread_join() or pthread_detach() specifying the same - * target is undefined. - */ - result = pthread_detach (thread); - } - else - { - result = ESRCH; - } - } - } - - return (result); - -} /* pthread_join */ diff --git a/pthreads/src/pthread_key_create.c b/pthreads/src/pthread_key_create.c deleted file mode 100644 index bdeee09..0000000 --- a/pthreads/src/pthread_key_create.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * pthread_key_create.c - * - * Description: - * POSIX thread functions which implement thread-specific data (TSD). - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -/* TLS_OUT_OF_INDEXES not defined on WinCE */ -#if !defined(TLS_OUT_OF_INDEXES) -#define TLS_OUT_OF_INDEXES 0xffffffff -#endif - -int -pthread_key_create (pthread_key_t * key, void (*destructor) (void *)) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function creates a thread-specific data key visible - * to all threads. All existing and new threads have a value - * NULL for key until set using pthread_setspecific. When any - * thread with a non-NULL value for key terminates, 'destructor' - * is called with key's current value for that thread. - * - * PARAMETERS - * key - * pointer to an instance of pthread_key_t - * - * - * DESCRIPTION - * This function creates a thread-specific data key visible - * to all threads. All existing and new threads have a value - * NULL for key until set using pthread_setspecific. When any - * thread with a non-NULL value for key terminates, 'destructor' - * is called with key's current value for that thread. - * - * RESULTS - * 0 successfully created semaphore, - * EAGAIN insufficient resources or PTHREAD_KEYS_MAX - * exceeded, - * ENOMEM insufficient memory to create the key, - * - * ------------------------------------------------------ - */ -{ - int result = 0; - pthread_key_t newkey; - - if ((newkey = (pthread_key_t) calloc (1, sizeof (*newkey))) == NULL) - { - result = ENOMEM; - } - else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES) - { - result = EAGAIN; - - free (newkey); - newkey = NULL; - } - else if (destructor != NULL) - { - /* - * Have to manage associations between thread and key; - * Therefore, need a lock that allows competing threads - * to gain exclusive access to the key->threads list. - * - * The mutex will only be created when it is first locked. - */ - newkey->keyLock = 0; - newkey->destructor = destructor; - } - - *key = newkey; - - return (result); -} diff --git a/pthreads/src/pthread_key_delete.c b/pthreads/src/pthread_key_delete.c deleted file mode 100644 index 09d70c6..0000000 --- a/pthreads/src/pthread_key_delete.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * pthread_key_delete.c - * - * Description: - * POSIX thread functions which implement thread-specific data (TSD). - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_key_delete (pthread_key_t key) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function deletes a thread-specific data key. This - * does not change the value of the thread specific data key - * for any thread and does not run the key's destructor - * in any thread so it should be used with caution. - * - * PARAMETERS - * key - * pointer to an instance of pthread_key_t - * - * - * DESCRIPTION - * This function deletes a thread-specific data key. This - * does not change the value of the thread specific data key - * for any thread and does not run the key's destructor - * in any thread so it should be used with caution. - * - * RESULTS - * 0 successfully deleted the key, - * EINVAL key is invalid, - * - * ------------------------------------------------------ - */ -{ - ptw32_mcs_local_node_t keyLock; - int result = 0; - - if (key != NULL) - { - if (key->threads != NULL && key->destructor != NULL) - { - ThreadKeyAssoc *assoc; - ptw32_mcs_lock_acquire (&(key->keyLock), &keyLock); - /* - * Run through all Thread<-->Key associations - * for this key. - * - * While we hold at least one of the locks guarding - * the assoc, we know that the assoc pointed to by - * key->threads is valid. - */ - while ((assoc = (ThreadKeyAssoc *) key->threads) != NULL) - { - ptw32_mcs_local_node_t threadLock; - ptw32_thread_t * thread = assoc->thread; - - if (assoc == NULL) - { - /* Finished */ - break; - } - - ptw32_mcs_lock_acquire (&(thread->threadLock), &threadLock); - /* - * Since we are starting at the head of the key's threads - * chain, this will also point key->threads at the next assoc. - * While we hold key->keyLock, no other thread can insert - * a new assoc via pthread_setspecific. - */ - ptw32_tkAssocDestroy (assoc); - ptw32_mcs_lock_release (&threadLock); - ptw32_mcs_lock_release (&keyLock); - } - } - - TlsFree (key->key); - if (key->destructor != NULL) - { - /* A thread could be holding the keyLock */ - ptw32_mcs_lock_acquire (&(key->keyLock), &keyLock); - ptw32_mcs_lock_release (&keyLock); - } - -#if defined( _DEBUG ) - memset ((char *) key, 0, sizeof (*key)); -#endif - free (key); - } - - return (result); -} diff --git a/pthreads/src/pthread_kill.c b/pthreads/src/pthread_kill.c deleted file mode 100644 index 5473b43..0000000 --- a/pthreads/src/pthread_kill.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * pthread_kill.c - * - * Description: - * This translation unit implements the pthread_kill routine. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * Not needed yet, but defining it should indicate clashes with build target - * environment that should be fixed. - */ -#if !defined(WINCE) -# include -#endif - -int -pthread_kill (pthread_t thread, int sig) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function requests that a signal be delivered to the - * specified thread. If sig is zero, error checking is - * performed but no signal is actually sent such that this - * function can be used to check for a valid thread ID. - * - * PARAMETERS - * thread reference to an instances of pthread_t - * sig signal. Currently only a value of 0 is supported. - * - * - * DESCRIPTION - * This function requests that a signal be delivered to the - * specified thread. If sig is zero, error checking is - * performed but no signal is actually sent such that this - * function can be used to check for a valid thread ID. - * - * RESULTS - * ESRCH the thread is not a valid thread ID, - * EINVAL the value of the signal is invalid - * or unsupported. - * 0 the signal was successfully sent. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - ptw32_thread_t * tp; - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); - - tp = (ptw32_thread_t *) thread.p; - - if (NULL == tp - || thread.x != tp->ptHandle.x - || NULL == tp->threadH) - { - result = ESRCH; - } - - ptw32_mcs_lock_release(&node); - - if (0 == result && 0 != sig) - { - /* - * Currently does not support any signals. - */ - result = EINVAL; - } - - return result; - -} /* pthread_kill */ diff --git a/pthreads/src/pthread_mutex_consistent.c b/pthreads/src/pthread_mutex_consistent.c deleted file mode 100644 index b7805e7..0000000 --- a/pthreads/src/pthread_mutex_consistent.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * pthread_mutex_consistent.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -/* - * From the Sun Multi-threaded Programming Guide - * - * robustness defines the behavior when the owner of the mutex terminates without unlocking the - * mutex, usually because its process terminated abnormally. The value of robustness that is - * defined in pthread.h is PTHREAD_MUTEX_ROBUST or PTHREAD_MUTEX_STALLED. The - * default value is PTHREAD_MUTEX_STALLED . - * ■ PTHREAD_MUTEX_STALLED - * When the owner of the mutex terminates without unlocking the mutex, all subsequent calls - * to pthread_mutex_lock() are blocked from progress in an unspecified manner. - * ■ PTHREAD_MUTEX_ROBUST - * When the owner of the mutex terminates without unlocking the mutex, the mutex is - * unlocked. The next owner of this mutex acquires the mutex with an error return of - * EOWNERDEAD. - * Note – Your application must always check the return code from pthread_mutex_lock() for - * a mutex initialized with the PTHREAD_MUTEX_ROBUST attribute. - * ■ The new owner of this mutex should make the state protected by the mutex consistent. - * This state might have been left inconsistent when the previous owner terminated. - * ■ If the new owner is able to make the state consistent, call - * pthread_mutex_consistent() for the mutex before unlocking the mutex. This - * marks the mutex as consistent and subsequent calls to pthread_mutex_lock() and - * pthread_mutex_unlock() will behave in the normal manner. - * ■ If the new owner is not able to make the state consistent, do not call - * pthread_mutex_consistent() for the mutex, but unlock the mutex. - * All waiters are woken up and all subsequent calls to pthread_mutex_lock() fail to - * acquire the mutex. The return code is ENOTRECOVERABLE. The mutex can be made - * consistent by calling pthread_mutex_destroy() to uninitialize the mutex, and calling - * pthread_mutex_int() to reinitialize the mutex.However, the state that was protected - * by the mutex remains inconsistent and some form of application recovery is required. - * ■ If the thread that acquires the lock with EOWNERDEAD terminates without unlocking the - * mutex, the next owner acquires the lock with an EOWNERDEAD return code. - */ -#if !defined(_UWIN) -/*# include */ -#endif -#include "pthread.h" -#include "implement.h" - -INLINE -int -ptw32_robust_mutex_inherit(pthread_mutex_t * mutex) -{ - int result; - pthread_mutex_t mx = *mutex; - ptw32_robust_node_t* robust = mx->robustNode; - - switch ((LONG)PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR)&robust->stateInconsistent, - (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT, - (PTW32_INTERLOCKED_LONG)-1 /* The terminating thread sets this */)) - { - case -1L: - result = EOWNERDEAD; - break; - case (LONG)PTW32_ROBUST_NOTRECOVERABLE: - result = ENOTRECOVERABLE; - break; - default: - result = 0; - break; - } - - return result; -} - -/* - * The next two internal support functions depend on only being - * called by the thread that owns the robust mutex. This enables - * us to avoid additional locks. - * Any mutex currently in the thread's robust mutex list is held - * by the thread, again eliminating the need for locks. - * The forward/backward links allow the thread to unlock mutexes - * in any order, not necessarily the reverse locking order. - * This is all possible because it is an error if a thread that - * does not own the [robust] mutex attempts to unlock it. - */ - -INLINE -void -ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self) -{ - ptw32_robust_node_t** list; - pthread_mutex_t mx = *mutex; - ptw32_thread_t* tp = (ptw32_thread_t*)self.p; - ptw32_robust_node_t* robust = mx->robustNode; - - list = &tp->robustMxList; - mx->ownerThread = self; - if (NULL == *list) - { - robust->prev = NULL; - robust->next = NULL; - *list = robust; - } - else - { - robust->prev = NULL; - robust->next = *list; - (*list)->prev = robust; - *list = robust; - } -} - -INLINE -void -ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp) -{ - ptw32_robust_node_t** list; - pthread_mutex_t mx = *mutex; - ptw32_robust_node_t* robust = mx->robustNode; - - list = &(((ptw32_thread_t*)mx->ownerThread.p)->robustMxList); - mx->ownerThread.p = otp; - if (robust->next != NULL) - { - robust->next->prev = robust->prev; - } - if (robust->prev != NULL) - { - robust->prev->next = robust->next; - } - if (*list == robust) - { - *list = robust->next; - } -} - - -int -pthread_mutex_consistent (pthread_mutex_t* mutex) -{ - pthread_mutex_t mx = *mutex; - int result = 0; - - /* - * Let the system deal with invalid pointers. - */ - if (mx == NULL) - { - return EINVAL; - } - - if (mx->kind >= 0 - || (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT != PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent, - (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_CONSISTENT, - (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT)) - { - result = EINVAL; - } - - return (result); -} - diff --git a/pthreads/src/pthread_mutex_destroy.c b/pthreads/src/pthread_mutex_destroy.c deleted file mode 100644 index 7b8c9cd..0000000 --- a/pthreads/src/pthread_mutex_destroy.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * pthread_mutex_destroy.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutex_destroy (pthread_mutex_t * mutex) -{ - int result = 0; - pthread_mutex_t mx; - - /* - * Let the system deal with invalid pointers. - */ - - /* - * Check to see if we have something to delete. - */ - if (*mutex < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) - { - mx = *mutex; - - result = pthread_mutex_trylock (&mx); - - /* - * If trylock succeeded and the mutex is not recursively locked it - * can be destroyed. - */ - if (0 == result || ENOTRECOVERABLE == result) - { - if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 1 == mx->recursive_count) - { - /* - * FIXME!!! - * The mutex isn't held by another thread but we could still - * be too late invalidating the mutex below since another thread - * may already have entered mutex_lock and the check for a valid - * *mutex != NULL. - */ - *mutex = NULL; - - result = (0 == result)?pthread_mutex_unlock(&mx):0; - - if (0 == result) - { - if (mx->robustNode != NULL) - { - free(mx->robustNode); - } - if (!CloseHandle (mx->event)) - { - *mutex = mx; - result = EINVAL; - } - else - { - free (mx); - } - } - else - { - /* - * Restore the mutex before we return the error. - */ - *mutex = mx; - } - } - else /* mx->recursive_count > 1 */ - { - /* - * The mutex must be recursive and already locked by us (this thread). - */ - mx->recursive_count--; /* Undo effect of pthread_mutex_trylock() above */ - result = EBUSY; - } - } - } - else - { - ptw32_mcs_local_node_t node; - - /* - * See notes in ptw32_mutex_check_need_init() above also. - */ - - ptw32_mcs_lock_acquire(&ptw32_mutex_test_init_lock, &node); - - /* - * Check again. - */ - if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) - { - /* - * This is all we need to do to destroy a statically - * initialised mutex that has not yet been used (initialised). - * If we get to here, another thread - * waiting to initialise this mutex will get an EINVAL. - */ - *mutex = NULL; - } - else - { - /* - * The mutex has been initialised while we were waiting - * so assume it's in use. - */ - result = EBUSY; - } - ptw32_mcs_lock_release(&node); - } - - return (result); -} diff --git a/pthreads/src/pthread_mutex_init.c b/pthreads/src/pthread_mutex_init.c deleted file mode 100644 index daf805e..0000000 --- a/pthreads/src/pthread_mutex_init.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * pthread_mutex_init.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr) -{ - int result = 0; - pthread_mutex_t mx; - - if (mutex == NULL) - { - return EINVAL; - } - - if (attr != NULL && *attr != NULL) - { - if ((*attr)->pshared == PTHREAD_PROCESS_SHARED) - { - /* - * Creating mutex that can be shared between - * processes. - */ -#if _POSIX_THREAD_PROCESS_SHARED >= 0 - - /* - * Not implemented yet. - */ - -#error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet. - -#else - - return ENOSYS; - -#endif /* _POSIX_THREAD_PROCESS_SHARED */ - } - } - - mx = (pthread_mutex_t) calloc (1, sizeof (*mx)); - - if (mx == NULL) - { - result = ENOMEM; - } - else - { - mx->lock_idx = 0; - mx->recursive_count = 0; - mx->robustNode = NULL; - if (attr == NULL || *attr == NULL) - { - mx->kind = PTHREAD_MUTEX_DEFAULT; - } - else - { - mx->kind = (*attr)->kind; - if ((*attr)->robustness == PTHREAD_MUTEX_ROBUST) - { - /* - * Use the negative range to represent robust types. - * Replaces a memory fetch with a register negate and incr - * in pthread_mutex_lock etc. - * - * Map 0,1,..,n to -1,-2,..,(-n)-1 - */ - mx->kind = -mx->kind - 1; - - mx->robustNode = (ptw32_robust_node_t*) malloc(sizeof(ptw32_robust_node_t)); - mx->robustNode->stateInconsistent = PTW32_ROBUST_CONSISTENT; - mx->robustNode->mx = mx; - mx->robustNode->next = NULL; - mx->robustNode->prev = NULL; - } - } - - mx->ownerThread.p = NULL; - - mx->event = CreateEvent (NULL, PTW32_FALSE, /* manual reset = No */ - PTW32_FALSE, /* initial state = not signaled */ - NULL); /* event name */ - - if (0 == mx->event) - { - result = ENOSPC; - free (mx); - mx = NULL; - } - } - - *mutex = mx; - - return (result); -} diff --git a/pthreads/src/pthread_mutex_lock.c b/pthreads/src/pthread_mutex_lock.c deleted file mode 100644 index eee9abe..0000000 --- a/pthreads/src/pthread_mutex_lock.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * pthread_mutex_lock.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined(_UWIN) -/*# include */ -#endif -#include "pthread.h" -#include "implement.h" - -int -pthread_mutex_lock (pthread_mutex_t * mutex) -{ - int kind; - pthread_mutex_t mx; - int result = 0; - - /* - * Let the system deal with invalid pointers. - */ - if (*mutex == NULL) - { - return EINVAL; - } - - /* - * We do a quick check to see if we need to do more work - * to initialise a static mutex. We check - * again inside the guarded section of ptw32_mutex_check_need_init() - * to avoid race conditions. - */ - if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) - { - if ((result = ptw32_mutex_check_need_init (mutex)) != 0) - { - return (result); - } - } - - mx = *mutex; - kind = mx->kind; - - if (kind >= 0) - { - /* Non-robust */ - if (PTHREAD_MUTEX_NORMAL == kind) - { - if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1) != 0) - { - while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) -1) != 0) - { - if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE)) - { - result = EINVAL; - break; - } - } - } - } - else - { - pthread_t self = pthread_self(); - - if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1, - (PTW32_INTERLOCKED_LONG) 0) == 0) - { - mx->recursive_count = 1; - mx->ownerThread = self; - } - else - { - if (pthread_equal (mx->ownerThread, self)) - { - if (kind == PTHREAD_MUTEX_RECURSIVE) - { - mx->recursive_count++; - } - else - { - result = EDEADLK; - } - } - else - { - while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) -1) != 0) - { - if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE)) - { - result = EINVAL; - break; - } - } - - if (0 == result) - { - mx->recursive_count = 1; - mx->ownerThread = self; - } - } - } - } - } - else - { - /* - * Robust types - * All types record the current owner thread. - * The mutex is added to a per thread list when ownership is acquired. - */ - ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent; - - if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == PTW32_INTERLOCKED_EXCHANGE_ADD_LONG( - (PTW32_INTERLOCKED_LONGPTR)statePtr, - (PTW32_INTERLOCKED_LONG)0)) - { - result = ENOTRECOVERABLE; - } - else - { - pthread_t self = pthread_self(); - - kind = -kind - 1; /* Convert to non-robust range */ - - if (PTHREAD_MUTEX_NORMAL == kind) - { - if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1) != 0) - { - while (0 == (result = ptw32_robust_mutex_inherit(mutex)) - && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) -1) != 0) - { - if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE)) - { - result = EINVAL; - break; - } - if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == - PTW32_INTERLOCKED_EXCHANGE_ADD_LONG( - (PTW32_INTERLOCKED_LONGPTR)statePtr, - (PTW32_INTERLOCKED_LONG)0)) - { - /* Unblock the next thread */ - SetEvent(mx->event); - result = ENOTRECOVERABLE; - break; - } - } - } - if (0 == result || EOWNERDEAD == result) - { - /* - * Add mutex to the per-thread robust mutex currently-held list. - * If the thread terminates, all mutexes in this list will be unlocked. - */ - ptw32_robust_mutex_add(mutex, self); - } - } - else - { - if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1, - (PTW32_INTERLOCKED_LONG) 0) == 0) - { - mx->recursive_count = 1; - /* - * Add mutex to the per-thread robust mutex currently-held list. - * If the thread terminates, all mutexes in this list will be unlocked. - */ - ptw32_robust_mutex_add(mutex, self); - } - else - { - if (pthread_equal (mx->ownerThread, self)) - { - if (PTHREAD_MUTEX_RECURSIVE == kind) - { - mx->recursive_count++; - } - else - { - result = EDEADLK; - } - } - else - { - while (0 == (result = ptw32_robust_mutex_inherit(mutex)) - && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) -1) != 0) - { - if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE)) - { - result = EINVAL; - break; - } - if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == - PTW32_INTERLOCKED_EXCHANGE_ADD_LONG( - (PTW32_INTERLOCKED_LONGPTR)statePtr, - (PTW32_INTERLOCKED_LONG)0)) - { - /* Unblock the next thread */ - SetEvent(mx->event); - result = ENOTRECOVERABLE; - break; - } - } - - if (0 == result || EOWNERDEAD == result) - { - mx->recursive_count = 1; - /* - * Add mutex to the per-thread robust mutex currently-held list. - * If the thread terminates, all mutexes in this list will be unlocked. - */ - ptw32_robust_mutex_add(mutex, self); - } - } - } - } - } - } - - return (result); -} - diff --git a/pthreads/src/pthread_mutex_timedlock.c b/pthreads/src/pthread_mutex_timedlock.c deleted file mode 100644 index 1745316..0000000 --- a/pthreads/src/pthread_mutex_timedlock.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * pthread_mutex_timedlock.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -static INLINE int -ptw32_timed_eventwait (HANDLE event, const struct timespec *abstime) - /* - * ------------------------------------------------------ - * DESCRIPTION - * This function waits on an event until signaled or until - * abstime passes. - * If abstime has passed when this routine is called then - * it returns a result to indicate this. - * - * If 'abstime' is a NULL pointer then this function will - * block until it can successfully decrease the value or - * until interrupted by a signal. - * - * This routine is not a cancelation point. - * - * RESULTS - * 0 successfully signaled, - * ETIMEDOUT abstime passed - * EINVAL 'event' is not a valid event, - * - * ------------------------------------------------------ - */ -{ - - DWORD milliseconds; - DWORD status; - - if (event == NULL) - { - return EINVAL; - } - else - { - if (abstime == NULL) - { - milliseconds = INFINITE; - } - else - { - /* - * Calculate timeout as milliseconds from current system time. - */ - milliseconds = ptw32_relmillisecs (abstime); - } - - status = WaitForSingleObject (event, milliseconds); - - if (status == WAIT_OBJECT_0) - { - return 0; - } - else if (status == WAIT_TIMEOUT) - { - return ETIMEDOUT; - } - else - { - return EINVAL; - } - } - - return 0; - -} /* ptw32_timed_semwait */ - - -int -pthread_mutex_timedlock (pthread_mutex_t * mutex, - const struct timespec *abstime) -{ - pthread_mutex_t mx; - int kind; - int result = 0; - - /* - * Let the system deal with invalid pointers. - */ - - /* - * We do a quick check to see if we need to do more work - * to initialise a static mutex. We check - * again inside the guarded section of ptw32_mutex_check_need_init() - * to avoid race conditions. - */ - if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) - { - if ((result = ptw32_mutex_check_need_init (mutex)) != 0) - { - return (result); - } - } - - mx = *mutex; - kind = mx->kind; - - if (kind >= 0) - { - if (mx->kind == PTHREAD_MUTEX_NORMAL) - { - if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1) != 0) - { - while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) -1) != 0) - { - if (0 != (result = ptw32_timed_eventwait (mx->event, abstime))) - { - return result; - } - } - } - } - else - { - pthread_t self = pthread_self(); - - if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1, - (PTW32_INTERLOCKED_LONG) 0) == 0) - { - mx->recursive_count = 1; - mx->ownerThread = self; - } - else - { - if (pthread_equal (mx->ownerThread, self)) - { - if (mx->kind == PTHREAD_MUTEX_RECURSIVE) - { - mx->recursive_count++; - } - else - { - return EDEADLK; - } - } - else - { - while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) -1) != 0) - { - if (0 != (result = ptw32_timed_eventwait (mx->event, abstime))) - { - return result; - } - } - - mx->recursive_count = 1; - mx->ownerThread = self; - } - } - } - } - else - { - /* - * Robust types - * All types record the current owner thread. - * The mutex is added to a per thread list when ownership is acquired. - */ - ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent; - - if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == PTW32_INTERLOCKED_EXCHANGE_ADD_LONG( - (PTW32_INTERLOCKED_LONGPTR)statePtr, - (PTW32_INTERLOCKED_LONG)0)) - { - result = ENOTRECOVERABLE; - } - else - { - pthread_t self = pthread_self(); - - kind = -kind - 1; /* Convert to non-robust range */ - - if (PTHREAD_MUTEX_NORMAL == kind) - { - if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1) != 0) - { - while (0 == (result = ptw32_robust_mutex_inherit(mutex)) - && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) -1) != 0) - { - if (0 != (result = ptw32_timed_eventwait (mx->event, abstime))) - { - return result; - } - if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == - PTW32_INTERLOCKED_EXCHANGE_ADD_LONG( - (PTW32_INTERLOCKED_LONGPTR)statePtr, - (PTW32_INTERLOCKED_LONG)0)) - { - /* Unblock the next thread */ - SetEvent(mx->event); - result = ENOTRECOVERABLE; - break; - } - } - - if (0 == result || EOWNERDEAD == result) - { - /* - * Add mutex to the per-thread robust mutex currently-held list. - * If the thread terminates, all mutexes in this list will be unlocked. - */ - ptw32_robust_mutex_add(mutex, self); - } - } - } - else - { - pthread_t self = pthread_self(); - - if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1, - (PTW32_INTERLOCKED_LONG) 0)) - { - mx->recursive_count = 1; - /* - * Add mutex to the per-thread robust mutex currently-held list. - * If the thread terminates, all mutexes in this list will be unlocked. - */ - ptw32_robust_mutex_add(mutex, self); - } - else - { - if (pthread_equal (mx->ownerThread, self)) - { - if (PTHREAD_MUTEX_RECURSIVE == kind) - { - mx->recursive_count++; - } - else - { - return EDEADLK; - } - } - else - { - while (0 == (result = ptw32_robust_mutex_inherit(mutex)) - && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) -1) != 0) - { - if (0 != (result = ptw32_timed_eventwait (mx->event, abstime))) - { - return result; - } - } - - if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == - PTW32_INTERLOCKED_EXCHANGE_ADD_LONG( - (PTW32_INTERLOCKED_LONGPTR)statePtr, - (PTW32_INTERLOCKED_LONG)0)) - { - /* Unblock the next thread */ - SetEvent(mx->event); - result = ENOTRECOVERABLE; - } - else if (0 == result || EOWNERDEAD == result) - { - mx->recursive_count = 1; - /* - * Add mutex to the per-thread robust mutex currently-held list. - * If the thread terminates, all mutexes in this list will be unlocked. - */ - ptw32_robust_mutex_add(mutex, self); - } - } - } - } - } - } - - return result; -} diff --git a/pthreads/src/pthread_mutex_trylock.c b/pthreads/src/pthread_mutex_trylock.c deleted file mode 100644 index d6b6872..0000000 --- a/pthreads/src/pthread_mutex_trylock.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * pthread_mutex_trylock.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutex_trylock (pthread_mutex_t * mutex) -{ - pthread_mutex_t mx; - int kind; - int result = 0; - - /* - * Let the system deal with invalid pointers. - */ - - /* - * We do a quick check to see if we need to do more work - * to initialise a static mutex. We check - * again inside the guarded section of ptw32_mutex_check_need_init() - * to avoid race conditions. - */ - if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) - { - if ((result = ptw32_mutex_check_need_init (mutex)) != 0) - { - return (result); - } - } - - mx = *mutex; - kind = mx->kind; - - if (kind >= 0) - { - /* Non-robust */ - if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1, - (PTW32_INTERLOCKED_LONG) 0)) - { - if (kind != PTHREAD_MUTEX_NORMAL) - { - mx->recursive_count = 1; - mx->ownerThread = pthread_self (); - } - } - else - { - if (kind == PTHREAD_MUTEX_RECURSIVE && - pthread_equal (mx->ownerThread, pthread_self ())) - { - mx->recursive_count++; - } - else - { - result = EBUSY; - } - } - } - else - { - /* - * Robust types - * All types record the current owner thread. - * The mutex is added to a per thread list when ownership is acquired. - */ - pthread_t self; - ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent; - - if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == - PTW32_INTERLOCKED_EXCHANGE_ADD_LONG( - (PTW32_INTERLOCKED_LONGPTR)statePtr, - (PTW32_INTERLOCKED_LONG)0)) - { - return ENOTRECOVERABLE; - } - - self = pthread_self(); - kind = -kind - 1; /* Convert to non-robust range */ - - if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ( - (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 1, - (PTW32_INTERLOCKED_LONG) 0)) - { - if (kind != PTHREAD_MUTEX_NORMAL) - { - mx->recursive_count = 1; - } - ptw32_robust_mutex_add(mutex, self); - } - else - { - if (PTHREAD_MUTEX_RECURSIVE == kind && - pthread_equal (mx->ownerThread, pthread_self ())) - { - mx->recursive_count++; - } - else - { - if (EOWNERDEAD == (result = ptw32_robust_mutex_inherit(mutex))) - { - mx->recursive_count = 1; - ptw32_robust_mutex_add(mutex, self); - } - else - { - if (0 == result) - { - result = EBUSY; - } - } - } - } - } - - return (result); -} diff --git a/pthreads/src/pthread_mutex_unlock.c b/pthreads/src/pthread_mutex_unlock.c deleted file mode 100644 index 3d65d1a..0000000 --- a/pthreads/src/pthread_mutex_unlock.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * pthread_mutex_unlock.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutex_unlock (pthread_mutex_t * mutex) -{ - int result = 0; - int kind; - pthread_mutex_t mx; - - /* - * Let the system deal with invalid pointers. - */ - - mx = *mutex; - - /* - * If the thread calling us holds the mutex then there is no - * race condition. If another thread holds the - * lock then we shouldn't be in here. - */ - if (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) - { - kind = mx->kind; - - if (kind >= 0) - { - if (kind == PTHREAD_MUTEX_NORMAL) - { - LONG idx; - - idx = (LONG) PTW32_INTERLOCKED_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR)&mx->lock_idx, - (PTW32_INTERLOCKED_LONG)0); - if (idx != 0) - { - if (idx < 0) - { - /* - * Someone may be waiting on that mutex. - */ - if (SetEvent (mx->event) == 0) - { - result = EINVAL; - } - } - } - } - else - { - if (pthread_equal (mx->ownerThread, pthread_self())) - { - if (kind != PTHREAD_MUTEX_RECURSIVE - || 0 == --mx->recursive_count) - { - mx->ownerThread.p = NULL; - - if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR)&mx->lock_idx, - (PTW32_INTERLOCKED_LONG)0) < 0L) - { - /* Someone may be waiting on that mutex */ - if (SetEvent (mx->event) == 0) - { - result = EINVAL; - } - } - } - } - else - { - result = EPERM; - } - } - } - else - { - /* Robust types */ - pthread_t self = pthread_self(); - kind = -kind - 1; /* Convert to non-robust range */ - - /* - * The thread must own the lock regardless of type if the mutex - * is robust. - */ - if (pthread_equal (mx->ownerThread, self)) - { - PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->robustNode->stateInconsistent, - (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE, - (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT); - if (PTHREAD_MUTEX_NORMAL == kind) - { - ptw32_robust_mutex_remove(mutex, NULL); - - if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 0) < 0) - { - /* - * Someone may be waiting on that mutex. - */ - if (SetEvent (mx->event) == 0) - { - result = EINVAL; - } - } - } - else - { - if (kind != PTHREAD_MUTEX_RECURSIVE - || 0 == --mx->recursive_count) - { - ptw32_robust_mutex_remove(mutex, NULL); - - if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx, - (PTW32_INTERLOCKED_LONG) 0) < 0) - { - /* - * Someone may be waiting on that mutex. - */ - if (SetEvent (mx->event) == 0) - { - result = EINVAL; - } - } - } - } - } - else - { - result = EPERM; - } - } - } - else if (mx != PTHREAD_MUTEX_INITIALIZER) - { - result = EINVAL; - } - - return (result); -} diff --git a/pthreads/src/pthread_mutexattr_destroy.c b/pthreads/src/pthread_mutexattr_destroy.c deleted file mode 100644 index 9d424bf..0000000 --- a/pthreads/src/pthread_mutexattr_destroy.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * pthread_mutexattr_destroy.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutexattr_destroy (pthread_mutexattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Destroys a mutex attributes object. The object can - * no longer be used. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_mutexattr_t - * - * - * DESCRIPTION - * Destroys a mutex attributes object. The object can - * no longer be used. - * - * NOTES: - * 1) Does not affect mutexes created using 'attr' - * - * RESULTS - * 0 successfully released attr, - * EINVAL 'attr' is invalid. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - - if (attr == NULL || *attr == NULL) - { - result = EINVAL; - } - else - { - pthread_mutexattr_t ma = *attr; - - *attr = NULL; - free (ma); - } - - return (result); -} /* pthread_mutexattr_destroy */ diff --git a/pthreads/src/pthread_mutexattr_getkind_np.c b/pthreads/src/pthread_mutexattr_getkind_np.c deleted file mode 100644 index 2d82ec6..0000000 --- a/pthreads/src/pthread_mutexattr_getkind_np.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * pthread_mutexattr_getkind_np.c - * - * Description: - * This translation unit implements non-portable thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -int -pthread_mutexattr_getkind_np (pthread_mutexattr_t * attr, int *kind) -{ - return pthread_mutexattr_gettype (attr, kind); -} diff --git a/pthreads/src/pthread_mutexattr_getpshared.c b/pthreads/src/pthread_mutexattr_getpshared.c deleted file mode 100644 index 42f9589..0000000 --- a/pthreads/src/pthread_mutexattr_getpshared.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * pthread_mutexattr_getpshared.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Determine whether mutexes created with 'attr' can be - * shared between processes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_mutexattr_t - * - * pshared - * will be set to one of: - * - * PTHREAD_PROCESS_SHARED - * May be shared if in shared memory - * - * PTHREAD_PROCESS_PRIVATE - * Cannot be shared. - * - * - * DESCRIPTION - * Mutexes creatd with 'attr' can be shared between - * processes if pthread_mutex_t variable is allocated - * in memory shared by these processes. - * NOTES: - * 1) pshared mutexes MUST be allocated in shared - * memory. - * 2) The following macro is defined if shared mutexes - * are supported: - * _POSIX_THREAD_PROCESS_SHARED - * - * RESULTS - * 0 successfully retrieved attribute, - * EINVAL 'attr' is invalid, - * - * ------------------------------------------------------ - */ -{ - int result; - - if ((attr != NULL && *attr != NULL) && (pshared != NULL)) - { - *pshared = (*attr)->pshared; - result = 0; - } - else - { - result = EINVAL; - } - - return (result); - -} /* pthread_mutexattr_getpshared */ diff --git a/pthreads/src/pthread_mutexattr_getrobust.c b/pthreads/src/pthread_mutexattr_getrobust.c deleted file mode 100644 index be00483..0000000 --- a/pthreads/src/pthread_mutexattr_getrobust.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * pthread_mutexattr_getrobust.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutexattr_getrobust (const pthread_mutexattr_t * attr, int * robust) - /* - * ------------------------------------------------------ - * - * DOCPUBLIC - * The pthread_mutexattr_setrobust() and - * pthread_mutexattr_getrobust() functions respectively set and - * get the mutex robust attribute. This attribute is set in the - * robust parameter to these functions. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_mutexattr_t - * - * robust - * must be one of: - * - * PTHREAD_MUTEX_STALLED - * - * PTHREAD_MUTEX_ROBUST - * - * DESCRIPTION - * The pthread_mutexattr_setrobust() and - * pthread_mutexattr_getrobust() functions respectively set and - * get the mutex robust attribute. This attribute is set in the - * robust parameter to these functions. The default value of the - * robust attribute is PTHREAD_MUTEX_STALLED. - * - * The robustness of mutex is contained in the robustness attribute - * of the mutex attributes. Valid mutex robustness values are: - * - * PTHREAD_MUTEX_STALLED - * No special actions are taken if the owner of the mutex is - * terminated while holding the mutex lock. This can lead to - * deadlocks if no other thread can unlock the mutex. - * This is the default value. - * - * PTHREAD_MUTEX_ROBUST - * If the process containing the owning thread of a robust mutex - * terminates while holding the mutex lock, the next thread that - * acquires the mutex shall be notified about the termination by - * the return value [EOWNERDEAD] from the locking function. If the - * owning thread of a robust mutex terminates while holding the mutex - * lock, the next thread that acquires the mutex may be notified - * about the termination by the return value [EOWNERDEAD]. The - * notified thread can then attempt to mark the state protected by - * the mutex as consistent again by a call to - * pthread_mutex_consistent(). After a subsequent successful call to - * pthread_mutex_unlock(), the mutex lock shall be released and can - * be used normally by other threads. If the mutex is unlocked without - * a call to pthread_mutex_consistent(), it shall be in a permanently - * unusable state and all attempts to lock the mutex shall fail with - * the error [ENOTRECOVERABLE]. The only permissible operation on such - * a mutex is pthread_mutex_destroy(). - * - * RESULTS - * 0 successfully set attribute, - * EINVAL 'attr' or 'robust' is invalid, - * - * ------------------------------------------------------ - */ -{ - int result = EINVAL; - - if ((attr != NULL && *attr != NULL && robust != NULL)) - { - *robust = (*attr)->robustness; - result = 0; - } - - return (result); -} /* pthread_mutexattr_getrobust */ diff --git a/pthreads/src/pthread_mutexattr_gettype.c b/pthreads/src/pthread_mutexattr_gettype.c deleted file mode 100644 index c63fcfa..0000000 --- a/pthreads/src/pthread_mutexattr_gettype.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * pthread_mutexattr_gettype.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind) -{ - int result = 0; - - if (attr != NULL && *attr != NULL && kind != NULL) - { - *kind = (*attr)->kind; - } - else - { - result = EINVAL; - } - - return (result); -} diff --git a/pthreads/src/pthread_mutexattr_init.c b/pthreads/src/pthread_mutexattr_init.c deleted file mode 100644 index d2797ff..0000000 --- a/pthreads/src/pthread_mutexattr_init.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * pthread_mutexattr_init.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutexattr_init (pthread_mutexattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Initializes a mutex attributes object with default - * attributes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_mutexattr_t - * - * - * DESCRIPTION - * Initializes a mutex attributes object with default - * attributes. - * - * NOTES: - * 1) Used to define mutex types - * - * RESULTS - * 0 successfully initialized attr, - * ENOMEM insufficient memory for attr. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - pthread_mutexattr_t ma; - - ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma)); - - if (ma == NULL) - { - result = ENOMEM; - } - else - { - ma->pshared = PTHREAD_PROCESS_PRIVATE; - ma->kind = PTHREAD_MUTEX_DEFAULT; - } - - *attr = ma; - - return (result); -} /* pthread_mutexattr_init */ diff --git a/pthreads/src/pthread_mutexattr_setkind_np.c b/pthreads/src/pthread_mutexattr_setkind_np.c deleted file mode 100644 index faa9366..0000000 --- a/pthreads/src/pthread_mutexattr_setkind_np.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * pthread_mutexattr_setkind_np.c - * - * Description: - * This translation unit implements non-portable thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -int -pthread_mutexattr_setkind_np (pthread_mutexattr_t * attr, int kind) -{ - return pthread_mutexattr_settype (attr, kind); -} diff --git a/pthreads/src/pthread_mutexattr_setpshared.c b/pthreads/src/pthread_mutexattr_setpshared.c deleted file mode 100644 index cfa6f71..0000000 --- a/pthreads/src/pthread_mutexattr_setpshared.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * pthread_mutexattr_setpshared.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Mutexes created with 'attr' can be shared between - * processes if pthread_mutex_t variable is allocated - * in memory shared by these processes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_mutexattr_t - * - * pshared - * must be one of: - * - * PTHREAD_PROCESS_SHARED - * May be shared if in shared memory - * - * PTHREAD_PROCESS_PRIVATE - * Cannot be shared. - * - * DESCRIPTION - * Mutexes creatd with 'attr' can be shared between - * processes if pthread_mutex_t variable is allocated - * in memory shared by these processes. - * - * NOTES: - * 1) pshared mutexes MUST be allocated in shared - * memory. - * - * 2) The following macro is defined if shared mutexes - * are supported: - * _POSIX_THREAD_PROCESS_SHARED - * - * RESULTS - * 0 successfully set attribute, - * EINVAL 'attr' or pshared is invalid, - * ENOSYS PTHREAD_PROCESS_SHARED not supported, - * - * ------------------------------------------------------ - */ -{ - int result; - - if ((attr != NULL && *attr != NULL) && - ((pshared == PTHREAD_PROCESS_SHARED) || - (pshared == PTHREAD_PROCESS_PRIVATE))) - { - if (pshared == PTHREAD_PROCESS_SHARED) - { - -#if !defined( _POSIX_THREAD_PROCESS_SHARED ) - - result = ENOSYS; - pshared = PTHREAD_PROCESS_PRIVATE; - -#else - - result = 0; - -#endif /* _POSIX_THREAD_PROCESS_SHARED */ - - } - else - { - result = 0; - } - - (*attr)->pshared = pshared; - } - else - { - result = EINVAL; - } - - return (result); - -} /* pthread_mutexattr_setpshared */ diff --git a/pthreads/src/pthread_mutexattr_setrobust.c b/pthreads/src/pthread_mutexattr_setrobust.c deleted file mode 100644 index b1acef7..0000000 --- a/pthreads/src/pthread_mutexattr_setrobust.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * pthread_mutexattr_setrobust.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutexattr_setrobust (pthread_mutexattr_t * attr, int robust) - /* - * ------------------------------------------------------ - * - * DOCPUBLIC - * The pthread_mutexattr_setrobust() and - * pthread_mutexattr_getrobust() functions respectively set and - * get the mutex robust attribute. This attribute is set in the - * robust parameter to these functions. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_mutexattr_t - * - * robust - * must be one of: - * - * PTHREAD_MUTEX_STALLED - * - * PTHREAD_MUTEX_ROBUST - * - * DESCRIPTION - * The pthread_mutexattr_setrobust() and - * pthread_mutexattr_getrobust() functions respectively set and - * get the mutex robust attribute. This attribute is set in the - * robust parameter to these functions. The default value of the - * robust attribute is PTHREAD_MUTEX_STALLED. - * - * The robustness of mutex is contained in the robustness attribute - * of the mutex attributes. Valid mutex robustness values are: - * - * PTHREAD_MUTEX_STALLED - * No special actions are taken if the owner of the mutex is - * terminated while holding the mutex lock. This can lead to - * deadlocks if no other thread can unlock the mutex. - * This is the default value. - * - * PTHREAD_MUTEX_ROBUST - * If the process containing the owning thread of a robust mutex - * terminates while holding the mutex lock, the next thread that - * acquires the mutex shall be notified about the termination by - * the return value [EOWNERDEAD] from the locking function. If the - * owning thread of a robust mutex terminates while holding the mutex - * lock, the next thread that acquires the mutex may be notified - * about the termination by the return value [EOWNERDEAD]. The - * notified thread can then attempt to mark the state protected by - * the mutex as consistent again by a call to - * pthread_mutex_consistent(). After a subsequent successful call to - * pthread_mutex_unlock(), the mutex lock shall be released and can - * be used normally by other threads. If the mutex is unlocked without - * a call to pthread_mutex_consistent(), it shall be in a permanently - * unusable state and all attempts to lock the mutex shall fail with - * the error [ENOTRECOVERABLE]. The only permissible operation on such - * a mutex is pthread_mutex_destroy(). - * - * RESULTS - * 0 successfully set attribute, - * EINVAL 'attr' or 'robust' is invalid, - * - * ------------------------------------------------------ - */ -{ - int result = EINVAL; - - if ((attr != NULL && *attr != NULL)) - { - switch (robust) - { - case PTHREAD_MUTEX_STALLED: - case PTHREAD_MUTEX_ROBUST: - (*attr)->robustness = robust; - result = 0; - break; - } - } - - return (result); -} /* pthread_mutexattr_setrobust */ diff --git a/pthreads/src/pthread_mutexattr_settype.c b/pthreads/src/pthread_mutexattr_settype.c deleted file mode 100644 index 8365daf..0000000 --- a/pthreads/src/pthread_mutexattr_settype.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * pthread_mutexattr_settype.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind) - /* - * ------------------------------------------------------ - * - * DOCPUBLIC - * The pthread_mutexattr_settype() and - * pthread_mutexattr_gettype() functions respectively set and - * get the mutex type attribute. This attribute is set in the - * type parameter to these functions. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_mutexattr_t - * - * type - * must be one of: - * - * PTHREAD_MUTEX_DEFAULT - * - * PTHREAD_MUTEX_NORMAL - * - * PTHREAD_MUTEX_ERRORCHECK - * - * PTHREAD_MUTEX_RECURSIVE - * - * DESCRIPTION - * The pthread_mutexattr_settype() and - * pthread_mutexattr_gettype() functions respectively set and - * get the mutex type attribute. This attribute is set in the - * type parameter to these functions. The default value of the - * type attribute is PTHREAD_MUTEX_DEFAULT. - * - * The type of mutex is contained in the type attribute of the - * mutex attributes. Valid mutex types include: - * - * PTHREAD_MUTEX_NORMAL - * This type of mutex does not detect deadlock. A - * thread attempting to relock this mutex without - * first unlocking it will deadlock. Attempting to - * unlock a mutex locked by a different thread - * results in undefined behavior. Attempting to - * unlock an unlocked mutex results in undefined - * behavior. - * - * PTHREAD_MUTEX_ERRORCHECK - * This type of mutex provides error checking. A - * thread attempting to relock this mutex without - * first unlocking it will return with an error. A - * thread attempting to unlock a mutex which another - * thread has locked will return with an error. A - * thread attempting to unlock an unlocked mutex will - * return with an error. - * - * PTHREAD_MUTEX_DEFAULT - * Same as PTHREAD_MUTEX_NORMAL. - * - * PTHREAD_MUTEX_RECURSIVE - * A thread attempting to relock this mutex without - * first unlocking it will succeed in locking the - * mutex. The relocking deadlock which can occur with - * mutexes of type PTHREAD_MUTEX_NORMAL cannot occur - * with this type of mutex. Multiple locks of this - * mutex require the same number of unlocks to - * release the mutex before another thread can - * acquire the mutex. A thread attempting to unlock a - * mutex which another thread has locked will return - * with an error. A thread attempting to unlock an - * unlocked mutex will return with an error. This - * type of mutex is only supported for mutexes whose - * process shared attribute is - * PTHREAD_PROCESS_PRIVATE. - * - * RESULTS - * 0 successfully set attribute, - * EINVAL 'attr' or 'type' is invalid, - * - * ------------------------------------------------------ - */ -{ - int result = 0; - - if ((attr != NULL && *attr != NULL)) - { - switch (kind) - { - case PTHREAD_MUTEX_FAST_NP: - case PTHREAD_MUTEX_RECURSIVE_NP: - case PTHREAD_MUTEX_ERRORCHECK_NP: - (*attr)->kind = kind; - break; - default: - result = EINVAL; - break; - } - } - else - { - result = EINVAL; - } - - return (result); -} /* pthread_mutexattr_settype */ diff --git a/pthreads/src/pthread_num_processors_np.c b/pthreads/src/pthread_num_processors_np.c deleted file mode 100644 index 3067d11..0000000 --- a/pthreads/src/pthread_num_processors_np.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * pthread_num_processors_np.c - * - * Description: - * This translation unit implements non-portable thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * pthread_num_processors_np() - * - * Get the number of CPUs available to the process. - */ -int -pthread_num_processors_np (void) -{ - int count; - - if (ptw32_getprocessors (&count) != 0) - { - count = 1; - } - - return (count); -} diff --git a/pthreads/src/pthread_once.c b/pthreads/src/pthread_once.c deleted file mode 100644 index ef2c1f1..0000000 --- a/pthreads/src/pthread_once.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * pthread_once.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -int -pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) -{ - if (once_control == NULL || init_routine == NULL) - { - return EINVAL; - } - - if ((PTW32_INTERLOCKED_LONG)PTW32_FALSE == - (PTW32_INTERLOCKED_LONG)PTW32_INTERLOCKED_EXCHANGE_ADD_LONG((PTW32_INTERLOCKED_LONGPTR)&once_control->done, - (PTW32_INTERLOCKED_LONG)0)) /* MBR fence */ - { - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire((ptw32_mcs_lock_t *)&once_control->lock, &node); - - if (!once_control->done) - { - -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth(0) -#endif - - pthread_cleanup_push(ptw32_mcs_lock_release, &node); - (*init_routine)(); - pthread_cleanup_pop(0); - -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth() -#endif - - once_control->done = PTW32_TRUE; - } - - ptw32_mcs_lock_release(&node); - } - - return 0; - -} /* pthread_once */ diff --git a/pthreads/src/pthread_rwlock_destroy.c b/pthreads/src/pthread_rwlock_destroy.c deleted file mode 100644 index 245a892..0000000 --- a/pthreads/src/pthread_rwlock_destroy.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * pthread_rwlock_destroy.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_destroy (pthread_rwlock_t * rwlock) -{ - pthread_rwlock_t rwl; - int result = 0, result1 = 0, result2 = 0; - - if (rwlock == NULL || *rwlock == NULL) - { - return EINVAL; - } - - if (*rwlock != PTHREAD_RWLOCK_INITIALIZER) - { - rwl = *rwlock; - - if (rwl->nMagic != PTW32_RWLOCK_MAGIC) - { - return EINVAL; - } - - if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) - { - return result; - } - - if ((result = - pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - - /* - * Check whether any threads own/wait for the lock (wait for ex.access); - * report "BUSY" if so. - */ - if (rwl->nExclusiveAccessCount > 0 - || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount) - { - result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); - result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - result2 = EBUSY; - } - else - { - rwl->nMagic = 0; - - if ((result = - pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - pthread_mutex_unlock (&rwl->mtxExclusiveAccess); - return result; - } - - if ((result = - pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) != 0) - { - return result; - } - - *rwlock = NULL; /* Invalidate rwlock before anything else */ - result = pthread_cond_destroy (&(rwl->cndSharedAccessCompleted)); - result1 = pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted)); - result2 = pthread_mutex_destroy (&(rwl->mtxExclusiveAccess)); - (void) free (rwl); - } - } - else - { - ptw32_mcs_local_node_t node; - /* - * See notes in ptw32_rwlock_check_need_init() above also. - */ - ptw32_mcs_lock_acquire(&ptw32_rwlock_test_init_lock, &node); - - /* - * Check again. - */ - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - /* - * This is all we need to do to destroy a statically - * initialised rwlock that has not yet been used (initialised). - * If we get to here, another thread - * waiting to initialise this rwlock will get an EINVAL. - */ - *rwlock = NULL; - } - else - { - /* - * The rwlock has been initialised while we were waiting - * so assume it's in use. - */ - result = EBUSY; - } - - ptw32_mcs_lock_release(&node); - } - - return ((result != 0) ? result : ((result1 != 0) ? result1 : result2)); -} diff --git a/pthreads/src/pthread_rwlock_init.c b/pthreads/src/pthread_rwlock_init.c deleted file mode 100644 index 597c1ff..0000000 --- a/pthreads/src/pthread_rwlock_init.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * pthread_rwlock_init.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_init (pthread_rwlock_t * rwlock, - const pthread_rwlockattr_t * attr) -{ - int result; - pthread_rwlock_t rwl = 0; - - if (rwlock == NULL) - { - return EINVAL; - } - - if (attr != NULL && *attr != NULL) - { - result = EINVAL; /* Not supported */ - goto DONE; - } - - rwl = (pthread_rwlock_t) calloc (1, sizeof (*rwl)); - - if (rwl == NULL) - { - result = ENOMEM; - goto DONE; - } - - rwl->nSharedAccessCount = 0; - rwl->nExclusiveAccessCount = 0; - rwl->nCompletedSharedAccessCount = 0; - - result = pthread_mutex_init (&rwl->mtxExclusiveAccess, NULL); - if (result != 0) - { - goto FAIL0; - } - - result = pthread_mutex_init (&rwl->mtxSharedAccessCompleted, NULL); - if (result != 0) - { - goto FAIL1; - } - - result = pthread_cond_init (&rwl->cndSharedAccessCompleted, NULL); - if (result != 0) - { - goto FAIL2; - } - - rwl->nMagic = PTW32_RWLOCK_MAGIC; - - result = 0; - goto DONE; - -FAIL2: - (void) pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted)); - -FAIL1: - (void) pthread_mutex_destroy (&(rwl->mtxExclusiveAccess)); - -FAIL0: - (void) free (rwl); - rwl = NULL; - -DONE: - *rwlock = rwl; - - return result; -} diff --git a/pthreads/src/pthread_rwlock_rdlock.c b/pthreads/src/pthread_rwlock_rdlock.c deleted file mode 100644 index 91e1808..0000000 --- a/pthreads/src/pthread_rwlock_rdlock.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * pthread_rwlock_rdlock.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_rdlock (pthread_rwlock_t * rwlock) -{ - int result; - pthread_rwlock_t rwl; - - if (rwlock == NULL || *rwlock == NULL) - { - return EINVAL; - } - - /* - * We do a quick check to see if we need to do more work - * to initialise a static rwlock. We check - * again inside the guarded section of ptw32_rwlock_check_need_init() - * to avoid race conditions. - */ - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - result = ptw32_rwlock_check_need_init (rwlock); - - if (result != 0 && result != EBUSY) - { - return result; - } - } - - rwl = *rwlock; - - if (rwl->nMagic != PTW32_RWLOCK_MAGIC) - { - return EINVAL; - } - - if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) - { - return result; - } - - if (++rwl->nSharedAccessCount == INT_MAX) - { - if ((result = - pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - - rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; - rwl->nCompletedSharedAccessCount = 0; - - if ((result = - pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - } - - return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))); -} diff --git a/pthreads/src/pthread_rwlock_timedrdlock.c b/pthreads/src/pthread_rwlock_timedrdlock.c deleted file mode 100644 index 7133778..0000000 --- a/pthreads/src/pthread_rwlock_timedrdlock.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * pthread_rwlock_timedrdlock.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_timedrdlock (pthread_rwlock_t * rwlock, - const struct timespec *abstime) -{ - int result; - pthread_rwlock_t rwl; - - if (rwlock == NULL || *rwlock == NULL) - { - return EINVAL; - } - - /* - * We do a quick check to see if we need to do more work - * to initialise a static rwlock. We check - * again inside the guarded section of ptw32_rwlock_check_need_init() - * to avoid race conditions. - */ - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - result = ptw32_rwlock_check_need_init (rwlock); - - if (result != 0 && result != EBUSY) - { - return result; - } - } - - rwl = *rwlock; - - if (rwl->nMagic != PTW32_RWLOCK_MAGIC) - { - return EINVAL; - } - - if ((result = - pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0) - { - return result; - } - - if (++rwl->nSharedAccessCount == INT_MAX) - { - if ((result = - pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted), - abstime)) != 0) - { - if (result == ETIMEDOUT) - { - ++rwl->nCompletedSharedAccessCount; - } - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - - rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; - rwl->nCompletedSharedAccessCount = 0; - - if ((result = - pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - } - - return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))); -} diff --git a/pthreads/src/pthread_rwlock_timedwrlock.c b/pthreads/src/pthread_rwlock_timedwrlock.c deleted file mode 100644 index 8c111bb..0000000 --- a/pthreads/src/pthread_rwlock_timedwrlock.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * pthread_rwlock_timedwrlock.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock, - const struct timespec *abstime) -{ - int result; - pthread_rwlock_t rwl; - - if (rwlock == NULL || *rwlock == NULL) - { - return EINVAL; - } - - /* - * We do a quick check to see if we need to do more work - * to initialise a static rwlock. We check - * again inside the guarded section of ptw32_rwlock_check_need_init() - * to avoid race conditions. - */ - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - result = ptw32_rwlock_check_need_init (rwlock); - - if (result != 0 && result != EBUSY) - { - return result; - } - } - - rwl = *rwlock; - - if (rwl->nMagic != PTW32_RWLOCK_MAGIC) - { - return EINVAL; - } - - if ((result = - pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0) - { - return result; - } - - if ((result = - pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted), - abstime)) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - - if (rwl->nExclusiveAccessCount == 0) - { - if (rwl->nCompletedSharedAccessCount > 0) - { - rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; - rwl->nCompletedSharedAccessCount = 0; - } - - if (rwl->nSharedAccessCount > 0) - { - rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount; - - /* - * This routine may be a cancelation point - * according to POSIX 1003.1j section 18.1.2. - */ -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth(0) -#endif - pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl); - - do - { - result = - pthread_cond_timedwait (&(rwl->cndSharedAccessCompleted), - &(rwl->mtxSharedAccessCompleted), - abstime); - } - while (result == 0 && rwl->nCompletedSharedAccessCount < 0); - - pthread_cleanup_pop ((result != 0) ? 1 : 0); -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth() -#endif - - if (result == 0) - { - rwl->nSharedAccessCount = 0; - } - } - } - - if (result == 0) - { - rwl->nExclusiveAccessCount++; - } - - return result; -} diff --git a/pthreads/src/pthread_rwlock_tryrdlock.c b/pthreads/src/pthread_rwlock_tryrdlock.c deleted file mode 100644 index 0fc5458..0000000 --- a/pthreads/src/pthread_rwlock_tryrdlock.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * pthread_rwlock_tryrdlock.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_tryrdlock (pthread_rwlock_t * rwlock) -{ - int result; - pthread_rwlock_t rwl; - - if (rwlock == NULL || *rwlock == NULL) - { - return EINVAL; - } - - /* - * We do a quick check to see if we need to do more work - * to initialise a static rwlock. We check - * again inside the guarded section of ptw32_rwlock_check_need_init() - * to avoid race conditions. - */ - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - result = ptw32_rwlock_check_need_init (rwlock); - - if (result != 0 && result != EBUSY) - { - return result; - } - } - - rwl = *rwlock; - - if (rwl->nMagic != PTW32_RWLOCK_MAGIC) - { - return EINVAL; - } - - if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0) - { - return result; - } - - if (++rwl->nSharedAccessCount == INT_MAX) - { - if ((result = - pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - - rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; - rwl->nCompletedSharedAccessCount = 0; - - if ((result = - pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - } - - return (pthread_mutex_unlock (&rwl->mtxExclusiveAccess)); -} diff --git a/pthreads/src/pthread_rwlock_trywrlock.c b/pthreads/src/pthread_rwlock_trywrlock.c deleted file mode 100644 index 9997c5d..0000000 --- a/pthreads/src/pthread_rwlock_trywrlock.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * pthread_rwlock_trywrlock.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_trywrlock (pthread_rwlock_t * rwlock) -{ - int result, result1; - pthread_rwlock_t rwl; - - if (rwlock == NULL || *rwlock == NULL) - { - return EINVAL; - } - - /* - * We do a quick check to see if we need to do more work - * to initialise a static rwlock. We check - * again inside the guarded section of ptw32_rwlock_check_need_init() - * to avoid race conditions. - */ - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - result = ptw32_rwlock_check_need_init (rwlock); - - if (result != 0 && result != EBUSY) - { - return result; - } - } - - rwl = *rwlock; - - if (rwl->nMagic != PTW32_RWLOCK_MAGIC) - { - return EINVAL; - } - - if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0) - { - return result; - } - - if ((result = - pthread_mutex_trylock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return ((result1 != 0) ? result1 : result); - } - - if (rwl->nExclusiveAccessCount == 0) - { - if (rwl->nCompletedSharedAccessCount > 0) - { - rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; - rwl->nCompletedSharedAccessCount = 0; - } - - if (rwl->nSharedAccessCount > 0) - { - if ((result = - pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - - if ((result = - pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) == 0) - { - result = EBUSY; - } - } - else - { - rwl->nExclusiveAccessCount = 1; - } - } - else - { - result = EBUSY; - } - - return result; -} diff --git a/pthreads/src/pthread_rwlock_unlock.c b/pthreads/src/pthread_rwlock_unlock.c deleted file mode 100644 index d48d187..0000000 --- a/pthreads/src/pthread_rwlock_unlock.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * pthread_rwlock_unlock.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_unlock (pthread_rwlock_t * rwlock) -{ - int result, result1; - pthread_rwlock_t rwl; - - if (rwlock == NULL || *rwlock == NULL) - { - return (EINVAL); - } - - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - /* - * Assume any race condition here is harmless. - */ - return 0; - } - - rwl = *rwlock; - - if (rwl->nMagic != PTW32_RWLOCK_MAGIC) - { - return EINVAL; - } - - if (rwl->nExclusiveAccessCount == 0) - { - if ((result = - pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - return result; - } - - if (++rwl->nCompletedSharedAccessCount == 0) - { - result = pthread_cond_signal (&(rwl->cndSharedAccessCompleted)); - } - - result1 = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); - } - else - { - rwl->nExclusiveAccessCount--; - - result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); - result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - - } - - return ((result != 0) ? result : result1); -} diff --git a/pthreads/src/pthread_rwlock_wrlock.c b/pthreads/src/pthread_rwlock_wrlock.c deleted file mode 100644 index e8b4fbb..0000000 --- a/pthreads/src/pthread_rwlock_wrlock.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * pthread_rwlock_wrlock.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlock_wrlock (pthread_rwlock_t * rwlock) -{ - int result; - pthread_rwlock_t rwl; - - if (rwlock == NULL || *rwlock == NULL) - { - return EINVAL; - } - - /* - * We do a quick check to see if we need to do more work - * to initialise a static rwlock. We check - * again inside the guarded section of ptw32_rwlock_check_need_init() - * to avoid race conditions. - */ - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - result = ptw32_rwlock_check_need_init (rwlock); - - if (result != 0 && result != EBUSY) - { - return result; - } - } - - rwl = *rwlock; - - if (rwl->nMagic != PTW32_RWLOCK_MAGIC) - { - return EINVAL; - } - - if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) - { - return result; - } - - if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) - { - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); - return result; - } - - if (rwl->nExclusiveAccessCount == 0) - { - if (rwl->nCompletedSharedAccessCount > 0) - { - rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; - rwl->nCompletedSharedAccessCount = 0; - } - - if (rwl->nSharedAccessCount > 0) - { - rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount; - - /* - * This routine may be a cancelation point - * according to POSIX 1003.1j section 18.1.2. - */ -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth(0) -#endif - pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl); - - do - { - result = pthread_cond_wait (&(rwl->cndSharedAccessCompleted), - &(rwl->mtxSharedAccessCompleted)); - } - while (result == 0 && rwl->nCompletedSharedAccessCount < 0); - - pthread_cleanup_pop ((result != 0) ? 1 : 0); -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth() -#endif - - if (result == 0) - { - rwl->nSharedAccessCount = 0; - } - } - } - - if (result == 0) - { - rwl->nExclusiveAccessCount++; - } - - return result; -} diff --git a/pthreads/src/pthread_rwlockattr_destroy.c b/pthreads/src/pthread_rwlockattr_destroy.c deleted file mode 100644 index 868e727..0000000 --- a/pthreads/src/pthread_rwlockattr_destroy.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * pthread_rwlockattr_destroy.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Destroys a rwlock attributes object. The object can - * no longer be used. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_rwlockattr_t - * - * - * DESCRIPTION - * Destroys a rwlock attributes object. The object can - * no longer be used. - * - * NOTES: - * 1) Does not affect rwlockss created using 'attr' - * - * RESULTS - * 0 successfully released attr, - * EINVAL 'attr' is invalid. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - - if (attr == NULL || *attr == NULL) - { - result = EINVAL; - } - else - { - pthread_rwlockattr_t rwa = *attr; - - *attr = NULL; - free (rwa); - } - - return (result); -} /* pthread_rwlockattr_destroy */ diff --git a/pthreads/src/pthread_rwlockattr_getpshared.c b/pthreads/src/pthread_rwlockattr_getpshared.c deleted file mode 100644 index eeace20..0000000 --- a/pthreads/src/pthread_rwlockattr_getpshared.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * pthread_rwlockattr_getpshared.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, - int *pshared) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Determine whether rwlocks created with 'attr' can be - * shared between processes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_rwlockattr_t - * - * pshared - * will be set to one of: - * - * PTHREAD_PROCESS_SHARED - * May be shared if in shared memory - * - * PTHREAD_PROCESS_PRIVATE - * Cannot be shared. - * - * - * DESCRIPTION - * Rwlocks creatd with 'attr' can be shared between - * processes if pthread_rwlock_t variable is allocated - * in memory shared by these processes. - * NOTES: - * 1) pshared rwlocks MUST be allocated in shared - * memory. - * 2) The following macro is defined if shared rwlocks - * are supported: - * _POSIX_THREAD_PROCESS_SHARED - * - * RESULTS - * 0 successfully retrieved attribute, - * EINVAL 'attr' is invalid, - * - * ------------------------------------------------------ - */ -{ - int result; - - if ((attr != NULL && *attr != NULL) && (pshared != NULL)) - { - *pshared = (*attr)->pshared; - result = 0; - } - else - { - result = EINVAL; - } - - return (result); - -} /* pthread_rwlockattr_getpshared */ diff --git a/pthreads/src/pthread_rwlockattr_init.c b/pthreads/src/pthread_rwlockattr_init.c deleted file mode 100644 index a2d2b94..0000000 --- a/pthreads/src/pthread_rwlockattr_init.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * pthread_rwlockattr_init.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlockattr_init (pthread_rwlockattr_t * attr) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Initializes a rwlock attributes object with default - * attributes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_rwlockattr_t - * - * - * DESCRIPTION - * Initializes a rwlock attributes object with default - * attributes. - * - * RESULTS - * 0 successfully initialized attr, - * ENOMEM insufficient memory for attr. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - pthread_rwlockattr_t rwa; - - rwa = (pthread_rwlockattr_t) calloc (1, sizeof (*rwa)); - - if (rwa == NULL) - { - result = ENOMEM; - } - else - { - rwa->pshared = PTHREAD_PROCESS_PRIVATE; - } - - *attr = rwa; - - return (result); -} /* pthread_rwlockattr_init */ diff --git a/pthreads/src/pthread_rwlockattr_setpshared.c b/pthreads/src/pthread_rwlockattr_setpshared.c deleted file mode 100644 index a83dd70..0000000 --- a/pthreads/src/pthread_rwlockattr_setpshared.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * pthread_rwlockattr_setpshared.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include - -#include "pthread.h" -#include "implement.h" - -int -pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Rwlocks created with 'attr' can be shared between - * processes if pthread_rwlock_t variable is allocated - * in memory shared by these processes. - * - * PARAMETERS - * attr - * pointer to an instance of pthread_rwlockattr_t - * - * pshared - * must be one of: - * - * PTHREAD_PROCESS_SHARED - * May be shared if in shared memory - * - * PTHREAD_PROCESS_PRIVATE - * Cannot be shared. - * - * DESCRIPTION - * Rwlocks creatd with 'attr' can be shared between - * processes if pthread_rwlock_t variable is allocated - * in memory shared by these processes. - * - * NOTES: - * 1) pshared rwlocks MUST be allocated in shared - * memory. - * - * 2) The following macro is defined if shared rwlocks - * are supported: - * _POSIX_THREAD_PROCESS_SHARED - * - * RESULTS - * 0 successfully set attribute, - * EINVAL 'attr' or pshared is invalid, - * ENOSYS PTHREAD_PROCESS_SHARED not supported, - * - * ------------------------------------------------------ - */ -{ - int result; - - if ((attr != NULL && *attr != NULL) && - ((pshared == PTHREAD_PROCESS_SHARED) || - (pshared == PTHREAD_PROCESS_PRIVATE))) - { - if (pshared == PTHREAD_PROCESS_SHARED) - { - -#if !defined( _POSIX_THREAD_PROCESS_SHARED ) - - result = ENOSYS; - pshared = PTHREAD_PROCESS_PRIVATE; - -#else - - result = 0; - -#endif /* _POSIX_THREAD_PROCESS_SHARED */ - - } - else - { - result = 0; - } - - (*attr)->pshared = pshared; - } - else - { - result = EINVAL; - } - - return (result); - -} /* pthread_rwlockattr_setpshared */ diff --git a/pthreads/src/pthread_self.c b/pthreads/src/pthread_self.c deleted file mode 100644 index 9a1765f..0000000 --- a/pthreads/src/pthread_self.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * pthread_self.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -pthread_t -pthread_self (void) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function returns a reference to the current running - * thread. - * - * PARAMETERS - * N/A - * - * - * DESCRIPTION - * This function returns a reference to the current running - * thread. - * - * RESULTS - * pthread_t reference to the current thread - * - * ------------------------------------------------------ - */ -{ - pthread_t self; - pthread_t nil = {NULL, 0}; - ptw32_thread_t * sp; - -#if defined(_UWIN) - if (!ptw32_selfThreadKey) - return nil; -#endif - - sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); - - if (sp != NULL) - { - self = sp->ptHandle; - } - else - { - /* - * Need to create an implicit 'self' for the currently - * executing thread. - */ - self = ptw32_new (); - sp = (ptw32_thread_t *) self.p; - - if (sp != NULL) - { - /* - * This is a non-POSIX thread which has chosen to call - * a POSIX threads function for some reason. We assume that - * it isn't joinable, but we do assume that it's - * (deferred) cancelable. - */ - sp->implicit = 1; - sp->detachState = PTHREAD_CREATE_DETACHED; - sp->thread = GetCurrentThreadId (); - -#if defined(NEED_DUPLICATEHANDLE) - /* - * DuplicateHandle does not exist on WinCE. - * - * NOTE: - * GetCurrentThread only returns a pseudo-handle - * which is only valid in the current thread context. - * Therefore, you should not pass the handle to - * other threads for whatever purpose. - */ - sp->threadH = GetCurrentThread (); -#else - if (!DuplicateHandle (GetCurrentProcess (), - GetCurrentThread (), - GetCurrentProcess (), - &sp->threadH, - 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - /* - * Should not do this, but we have no alternative if - * we can't get a Win32 thread handle. - * Thread structs are never freed. - */ - ptw32_threadReusePush (self); - /* - * As this is a win32 thread calling us and we have failed, - * return a value that makes sense to win32. - */ - return nil; - } -#endif - - /* - * No need to explicitly serialise access to sched_priority - * because the new handle is not yet public. - */ - sp->sched_priority = GetThreadPriority (sp->threadH); - pthread_setspecific (ptw32_selfThreadKey, (void *) sp); - } - } - - return (self); - -} /* pthread_self */ diff --git a/pthreads/src/pthread_setcancelstate.c b/pthreads/src/pthread_setcancelstate.c deleted file mode 100644 index bbcd624..0000000 --- a/pthreads/src/pthread_setcancelstate.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * pthread_setcancelstate.c - * - * Description: - * POSIX thread functions related to thread cancellation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_setcancelstate (int state, int *oldstate) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function atomically sets the calling thread's - * cancelability state to 'state' and returns the previous - * cancelability state at the location referenced by - * 'oldstate' - * - * PARAMETERS - * state, - * oldstate - * PTHREAD_CANCEL_ENABLE - * cancellation is enabled, - * - * PTHREAD_CANCEL_DISABLE - * cancellation is disabled - * - * - * DESCRIPTION - * This function atomically sets the calling thread's - * cancelability state to 'state' and returns the previous - * cancelability state at the location referenced by - * 'oldstate'. - * - * NOTES: - * 1) Use to disable cancellation around 'atomic' code that - * includes cancellation points - * - * COMPATIBILITY ADDITIONS - * If 'oldstate' is NULL then the previous state is not returned - * but the function still succeeds. (Solaris) - * - * RESULTS - * 0 successfully set cancelability type, - * EINVAL 'state' is invalid - * - * ------------------------------------------------------ - */ -{ - ptw32_mcs_local_node_t stateLock; - int result = 0; - pthread_t self = pthread_self (); - ptw32_thread_t * sp = (ptw32_thread_t *) self.p; - - if (sp == NULL - || (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)) - { - return EINVAL; - } - - /* - * Lock for async-cancel safety. - */ - ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); - - if (oldstate != NULL) - { - *oldstate = sp->cancelState; - } - - sp->cancelState = state; - - /* - * Check if there is a pending asynchronous cancel - */ - if (state == PTHREAD_CANCEL_ENABLE - && sp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS - && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0) - { - sp->state = PThreadStateCanceling; - sp->cancelState = PTHREAD_CANCEL_DISABLE; - ResetEvent (sp->cancelEvent); - ptw32_mcs_lock_release (&stateLock); - ptw32_throw (PTW32_EPS_CANCEL); - - /* Never reached */ - } - - ptw32_mcs_lock_release (&stateLock); - - return (result); - -} /* pthread_setcancelstate */ diff --git a/pthreads/src/pthread_setcanceltype.c b/pthreads/src/pthread_setcanceltype.c deleted file mode 100644 index 72b0af5..0000000 --- a/pthreads/src/pthread_setcanceltype.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * pthread_setcanceltype.c - * - * Description: - * POSIX thread functions related to thread cancellation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_setcanceltype (int type, int *oldtype) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function atomically sets the calling thread's - * cancelability type to 'type' and returns the previous - * cancelability type at the location referenced by - * 'oldtype' - * - * PARAMETERS - * type, - * oldtype - * PTHREAD_CANCEL_DEFERRED - * only deferred cancelation is allowed, - * - * PTHREAD_CANCEL_ASYNCHRONOUS - * Asynchronous cancellation is allowed - * - * - * DESCRIPTION - * This function atomically sets the calling thread's - * cancelability type to 'type' and returns the previous - * cancelability type at the location referenced by - * 'oldtype' - * - * NOTES: - * 1) Use with caution; most code is not safe for use - * with asynchronous cancelability. - * - * COMPATIBILITY ADDITIONS - * If 'oldtype' is NULL then the previous type is not returned - * but the function still succeeds. (Solaris) - * - * RESULTS - * 0 successfully set cancelability type, - * EINVAL 'type' is invalid - * - * ------------------------------------------------------ - */ -{ - ptw32_mcs_local_node_t stateLock; - int result = 0; - pthread_t self = pthread_self (); - ptw32_thread_t * sp = (ptw32_thread_t *) self.p; - - if (sp == NULL - || (type != PTHREAD_CANCEL_DEFERRED - && type != PTHREAD_CANCEL_ASYNCHRONOUS)) - { - return EINVAL; - } - - /* - * Lock for async-cancel safety. - */ - ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); - - if (oldtype != NULL) - { - *oldtype = sp->cancelType; - } - - sp->cancelType = type; - - /* - * Check if there is a pending asynchronous cancel - */ - if (sp->cancelState == PTHREAD_CANCEL_ENABLE - && type == PTHREAD_CANCEL_ASYNCHRONOUS - && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0) - { - sp->state = PThreadStateCanceling; - sp->cancelState = PTHREAD_CANCEL_DISABLE; - ResetEvent (sp->cancelEvent); - ptw32_mcs_lock_release (&stateLock); - ptw32_throw (PTW32_EPS_CANCEL); - - /* Never reached */ - } - - ptw32_mcs_lock_release (&stateLock); - - return (result); - -} /* pthread_setcanceltype */ diff --git a/pthreads/src/pthread_setconcurrency.c b/pthreads/src/pthread_setconcurrency.c deleted file mode 100644 index f62346f..0000000 --- a/pthreads/src/pthread_setconcurrency.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * pthread_setconcurrency.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_setconcurrency (int level) -{ - if (level < 0) - { - return EINVAL; - } - else - { - ptw32_concurrency = level; - return 0; - } -} diff --git a/pthreads/src/pthread_setschedparam.c b/pthreads/src/pthread_setschedparam.c deleted file mode 100644 index b762753..0000000 --- a/pthreads/src/pthread_setschedparam.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * sched_setschedparam.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -pthread_setschedparam (pthread_t thread, int policy, - const struct sched_param *param) -{ - int result; - - /* Validate the thread id. */ - result = pthread_kill (thread, 0); - if (0 != result) - { - return result; - } - - /* Validate the scheduling policy. */ - if (policy < SCHED_MIN || policy > SCHED_MAX) - { - return EINVAL; - } - - /* Ensure the policy is SCHED_OTHER. */ - if (policy != SCHED_OTHER) - { - return ENOTSUP; - } - - return (ptw32_setthreadpriority (thread, policy, param->sched_priority)); -} - - -int -ptw32_setthreadpriority (pthread_t thread, int policy, int priority) -{ - int prio; - ptw32_mcs_local_node_t threadLock; - int result = 0; - ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; - - prio = priority; - - /* Validate priority level. */ - if (prio < sched_get_priority_min (policy) || - prio > sched_get_priority_max (policy)) - { - return EINVAL; - } - -#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) -/* WinCE */ -#else -/* Everything else */ - - if (THREAD_PRIORITY_IDLE < prio && THREAD_PRIORITY_LOWEST > prio) - { - prio = THREAD_PRIORITY_LOWEST; - } - else if (THREAD_PRIORITY_TIME_CRITICAL > prio - && THREAD_PRIORITY_HIGHEST < prio) - { - prio = THREAD_PRIORITY_HIGHEST; - } - -#endif - - ptw32_mcs_lock_acquire (&tp->threadLock, &threadLock); - - /* If this fails, the current priority is unchanged. */ - if (0 == SetThreadPriority (tp->threadH, prio)) - { - result = EINVAL; - } - else - { - /* - * Must record the thread's sched_priority as given, - * not as finally adjusted. - */ - tp->sched_priority = priority; - } - - ptw32_mcs_lock_release (&threadLock); - - return result; -} diff --git a/pthreads/src/pthread_setspecific.c b/pthreads/src/pthread_setspecific.c deleted file mode 100644 index 0f29e70..0000000 --- a/pthreads/src/pthread_setspecific.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * pthread_setspecific.c - * - * Description: - * POSIX thread functions which implement thread-specific data (TSD). - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_setspecific (pthread_key_t key, const void *value) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function sets the value of the thread specific - * key in the calling thread. - * - * PARAMETERS - * key - * an instance of pthread_key_t - * value - * the value to set key to - * - * - * DESCRIPTION - * This function sets the value of the thread specific - * key in the calling thread. - * - * RESULTS - * 0 successfully set value - * EAGAIN could not set value - * ENOENT SERIOUS!! - * - * ------------------------------------------------------ - */ -{ - pthread_t self; - int result = 0; - - if (key != ptw32_selfThreadKey) - { - /* - * Using pthread_self will implicitly create - * an instance of pthread_t for the current - * thread if one wasn't explicitly created - */ - self = pthread_self (); - if (self.p == NULL) - { - return ENOENT; - } - } - else - { - /* - * Resolve catch-22 of registering thread with selfThread - * key - */ - ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); - - if (sp == NULL) - { - if (value == NULL) - { - return ENOENT; - } - self = *((pthread_t *) value); - } - else - { - self = sp->ptHandle; - } - } - - result = 0; - - if (key != NULL) - { - if (self.p != NULL && key->destructor != NULL && value != NULL) - { - ptw32_mcs_local_node_t keyLock; - ptw32_mcs_local_node_t threadLock; - ptw32_thread_t * sp = (ptw32_thread_t *) self.p; - /* - * Only require associations if we have to - * call user destroy routine. - * Don't need to locate an existing association - * when setting data to NULL for WIN32 since the - * data is stored with the operating system; not - * on the association; setting assoc to NULL short - * circuits the search. - */ - ThreadKeyAssoc *assoc; - - ptw32_mcs_lock_acquire(&(key->keyLock), &keyLock); - ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock); - - assoc = (ThreadKeyAssoc *) sp->keys; - /* - * Locate existing association - */ - while (assoc != NULL) - { - if (assoc->key == key) - { - /* - * Association already exists - */ - break; - } - assoc = assoc->nextKey; - } - - /* - * create an association if not found - */ - if (assoc == NULL) - { - result = ptw32_tkAssocCreate (sp, key); - } - - ptw32_mcs_lock_release(&threadLock); - ptw32_mcs_lock_release(&keyLock); - } - - if (result == 0) - { - if (!TlsSetValue (key->key, (LPVOID) value)) - { - result = EAGAIN; - } - } - } - - return (result); -} /* pthread_setspecific */ diff --git a/pthreads/src/pthread_spin_destroy.c b/pthreads/src/pthread_spin_destroy.c deleted file mode 100644 index 786c4e3..0000000 --- a/pthreads/src/pthread_spin_destroy.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * pthread_spin_destroy.c - * - * Description: - * This translation unit implements spin lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_spin_destroy (pthread_spinlock_t * lock) -{ - register pthread_spinlock_t s; - int result = 0; - - if (lock == NULL || *lock == NULL) - { - return EINVAL; - } - - if ((s = *lock) != PTHREAD_SPINLOCK_INITIALIZER) - { - if (s->interlock == PTW32_SPIN_USE_MUTEX) - { - result = pthread_mutex_destroy (&(s->u.mutex)); - } - else if ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED != - PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock, - (PTW32_INTERLOCKED_LONG) PTW32_SPIN_INVALID, - (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED)) - { - result = EINVAL; - } - - if (0 == result) - { - /* - * We are relying on the application to ensure that all other threads - * have finished with the spinlock before destroying it. - */ - *lock = NULL; - (void) free (s); - } - } - else - { - /* - * See notes in ptw32_spinlock_check_need_init() above also. - */ - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_spinlock_test_init_lock, &node); - - /* - * Check again. - */ - if (*lock == PTHREAD_SPINLOCK_INITIALIZER) - { - /* - * This is all we need to do to destroy a statically - * initialised spinlock that has not yet been used (initialised). - * If we get to here, another thread - * waiting to initialise this mutex will get an EINVAL. - */ - *lock = NULL; - } - else - { - /* - * The spinlock has been initialised while we were waiting - * so assume it's in use. - */ - result = EBUSY; - } - - ptw32_mcs_lock_release(&node); - } - - return (result); -} diff --git a/pthreads/src/pthread_spin_init.c b/pthreads/src/pthread_spin_init.c deleted file mode 100644 index 553af7e..0000000 --- a/pthreads/src/pthread_spin_init.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * pthread_spin_init.c - * - * Description: - * This translation unit implements spin lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_spin_init (pthread_spinlock_t * lock, int pshared) -{ - pthread_spinlock_t s; - int cpus = 0; - int result = 0; - - if (lock == NULL) - { - return EINVAL; - } - - if (0 != ptw32_getprocessors (&cpus)) - { - cpus = 1; - } - - if (cpus > 1) - { - if (pshared == PTHREAD_PROCESS_SHARED) - { - /* - * Creating spinlock that can be shared between - * processes. - */ -#if _POSIX_THREAD_PROCESS_SHARED >= 0 - - /* - * Not implemented yet. - */ - -#error ERROR [__FILE__, line __LINE__]: Process shared spin locks are not supported yet. - -#else - - return ENOSYS; - -#endif /* _POSIX_THREAD_PROCESS_SHARED */ - - } - } - - s = (pthread_spinlock_t) calloc (1, sizeof (*s)); - - if (s == NULL) - { - return ENOMEM; - } - - if (cpus > 1) - { - s->u.cpus = cpus; - s->interlock = PTW32_SPIN_UNLOCKED; - } - else - { - pthread_mutexattr_t ma; - result = pthread_mutexattr_init (&ma); - - if (0 == result) - { - ma->pshared = pshared; - result = pthread_mutex_init (&(s->u.mutex), &ma); - if (0 == result) - { - s->interlock = PTW32_SPIN_USE_MUTEX; - } - } - (void) pthread_mutexattr_destroy (&ma); - } - - if (0 == result) - { - *lock = s; - } - else - { - (void) free (s); - *lock = NULL; - } - - return (result); -} diff --git a/pthreads/src/pthread_spin_lock.c b/pthreads/src/pthread_spin_lock.c deleted file mode 100644 index b560e14..0000000 --- a/pthreads/src/pthread_spin_lock.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * pthread_spin_lock.c - * - * Description: - * This translation unit implements spin lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_spin_lock (pthread_spinlock_t * lock) -{ - register pthread_spinlock_t s; - - if (NULL == lock || NULL == *lock) - { - return (EINVAL); - } - - if (*lock == PTHREAD_SPINLOCK_INITIALIZER) - { - int result; - - if ((result = ptw32_spinlock_check_need_init (lock)) != 0) - { - return (result); - } - } - - s = *lock; - - while ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED == - PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock, - (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED, - (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED)) - { - } - - if (s->interlock == PTW32_SPIN_LOCKED) - { - return 0; - } - else if (s->interlock == PTW32_SPIN_USE_MUTEX) - { - return pthread_mutex_lock (&(s->u.mutex)); - } - - return EINVAL; -} diff --git a/pthreads/src/pthread_spin_trylock.c b/pthreads/src/pthread_spin_trylock.c deleted file mode 100644 index a6c65af..0000000 --- a/pthreads/src/pthread_spin_trylock.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * pthread_spin_trylock.c - * - * Description: - * This translation unit implements spin lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_spin_trylock (pthread_spinlock_t * lock) -{ - register pthread_spinlock_t s; - - if (NULL == lock || NULL == *lock) - { - return (EINVAL); - } - - if (*lock == PTHREAD_SPINLOCK_INITIALIZER) - { - int result; - - if ((result = ptw32_spinlock_check_need_init (lock)) != 0) - { - return (result); - } - } - - s = *lock; - - switch ((long) - PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock, - (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED, - (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED)) - { - case PTW32_SPIN_UNLOCKED: - return 0; - case PTW32_SPIN_LOCKED: - return EBUSY; - case PTW32_SPIN_USE_MUTEX: - return pthread_mutex_trylock (&(s->u.mutex)); - } - - return EINVAL; -} diff --git a/pthreads/src/pthread_spin_unlock.c b/pthreads/src/pthread_spin_unlock.c deleted file mode 100644 index 3a6932a..0000000 --- a/pthreads/src/pthread_spin_unlock.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * pthread_spin_unlock.c - * - * Description: - * This translation unit implements spin lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -pthread_spin_unlock (pthread_spinlock_t * lock) -{ - register pthread_spinlock_t s; - - if (NULL == lock || NULL == *lock) - { - return (EINVAL); - } - - s = *lock; - - if (s == PTHREAD_SPINLOCK_INITIALIZER) - { - return EPERM; - } - - switch ((long) - PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock, - (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED, - (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED)) - { - case PTW32_SPIN_LOCKED: - case PTW32_SPIN_UNLOCKED: - return 0; - case PTW32_SPIN_USE_MUTEX: - return pthread_mutex_unlock (&(s->u.mutex)); - } - - return EINVAL; -} diff --git a/pthreads/src/pthread_testcancel.c b/pthreads/src/pthread_testcancel.c deleted file mode 100644 index 6658650..0000000 --- a/pthreads/src/pthread_testcancel.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * pthread_testcancel.c - * - * Description: - * POSIX thread functions related to thread cancellation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -void -pthread_testcancel (void) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function creates a deferred cancellation point - * in the calling thread. The call has no effect if the - * current cancelability state is - * PTHREAD_CANCEL_DISABLE - * - * PARAMETERS - * N/A - * - * - * DESCRIPTION - * This function creates a deferred cancellation point - * in the calling thread. The call has no effect if the - * current cancelability state is - * PTHREAD_CANCEL_DISABLE - * - * NOTES: - * 1) Cancellation is asynchronous. Use pthread_join - * to wait for termination of thread if necessary - * - * RESULTS - * N/A - * - * ------------------------------------------------------ - */ -{ - ptw32_mcs_local_node_t stateLock; - pthread_t self = pthread_self (); - ptw32_thread_t * sp = (ptw32_thread_t *) self.p; - - if (sp == NULL) - { - return; - } - - /* - * Pthread_cancel() will have set sp->state to PThreadStateCancelPending - * and set an event, so no need to enter kernel space if - * sp->state != PThreadStateCancelPending - that only slows us down. - */ - if (sp->state != PThreadStateCancelPending) - { - return; - } - - ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); - - if (sp->cancelState != PTHREAD_CANCEL_DISABLE) - { - ResetEvent(sp->cancelEvent); - sp->state = PThreadStateCanceling; - sp->cancelState = PTHREAD_CANCEL_DISABLE; - ptw32_mcs_lock_release (&stateLock); - ptw32_throw (PTW32_EPS_CANCEL); - /* Never returns here */ - } - - ptw32_mcs_lock_release (&stateLock); -} /* pthread_testcancel */ diff --git a/pthreads/src/pthread_timechange_handler_np.c b/pthreads/src/pthread_timechange_handler_np.c deleted file mode 100644 index 0f97e74..0000000 --- a/pthreads/src/pthread_timechange_handler_np.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * pthread_timechange_handler_np.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * Notes on handling system time adjustments (especially negative ones). - * --------------------------------------------------------------------- - * - * This solution was suggested by Alexander Terekhov, but any errors - * in the implementation are mine - [Ross Johnson] - * - * 1) The problem: threads doing a timedwait on a CV may expect to timeout - * at a specific absolute time according to a system timer. If the - * system clock is adjusted backwards then those threads sleep longer than - * expected. Also, pthreads-win32 converts absolute times to intervals in - * order to make use of the underlying Win32, and so waiting threads may - * awake before their proper abstimes. - * - * 2) We aren't able to distinquish between threads on timed or untimed waits, - * so we wake them all at the time of the adjustment so that they can - * re-evaluate their conditions and re-compute their timeouts. - * - * 3) We rely on correctly written applications for this to work. Specifically, - * they must be able to deal properly with spurious wakeups. That is, - * they must re-test their condition upon wakeup and wait again if - * the condition is not satisfied. - */ - -void * -pthread_timechange_handler_np (void *arg) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * Broadcasts all CVs to force re-evaluation and - * new timeouts if required. - * - * PARAMETERS - * NONE - * - * - * DESCRIPTION - * Broadcasts all CVs to force re-evaluation and - * new timeouts if required. - * - * This routine may be passed directly to pthread_create() - * as a new thread in order to run asynchronously. - * - * - * RESULTS - * 0 successfully broadcast all CVs - * EAGAIN Not all CVs were broadcast - * - * ------------------------------------------------------ - */ -{ - int result = 0; - pthread_cond_t cv; - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node); - - cv = ptw32_cond_list_head; - - while (cv != NULL && 0 == result) - { - result = pthread_cond_broadcast (&cv); - cv = cv->next; - } - - ptw32_mcs_lock_release(&node); - - return (void *) (size_t) (result != 0 ? EAGAIN : 0); -} diff --git a/pthreads/src/pthread_win32_attach_detach_np.c b/pthreads/src/pthread_win32_attach_detach_np.c deleted file mode 100644 index bfad450..0000000 --- a/pthreads/src/pthread_win32_attach_detach_np.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * pthread_win32_attach_detach_np.c - * - * Description: - * This translation unit implements non-portable thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -/* - * Handle to quserex.dll - */ -static HINSTANCE ptw32_h_quserex; - -BOOL -pthread_win32_process_attach_np () -{ - TCHAR QuserExDLLPathBuf[1024]; - BOOL result = TRUE; - - result = ptw32_processInitialize (); - -#if defined(_UWIN) - pthread_count++; -#endif - -#if defined(__GNUC__) - ptw32_features = 0; -#else - /* - * This is obsolete now. - */ - ptw32_features = PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE; -#endif - - /* - * Load QUSEREX.DLL and try to get address of QueueUserAPCEx. - * Because QUSEREX.DLL requires a driver to be installed we will - * assume the DLL is in the system directory. - * - * This should take care of any security issues. - */ -#if defined(__GNUC__) || _MSC_VER < 1400 - if(GetSystemDirectory(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf))) - { - (void) strncat(QuserExDLLPathBuf, - "\\QUSEREX.DLL", - sizeof(QuserExDLLPathBuf) - strlen(QuserExDLLPathBuf) - 1); - ptw32_h_quserex = LoadLibrary(QuserExDLLPathBuf); - } -#else - /* strncat is secure - this is just to avoid a warning */ - if(GetSystemDirectory(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf)) && - 0 == strncat_s(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf), "\\QUSEREX.DLL", 12)) - { - ptw32_h_quserex = LoadLibrary(QuserExDLLPathBuf); - } -#endif - - if (ptw32_h_quserex != NULL) - { - ptw32_register_cancelation = (DWORD (*)(PAPCFUNC, HANDLE, DWORD)) -#if defined(NEED_UNICODE_CONSTS) - GetProcAddress (ptw32_h_quserex, - (const TCHAR *) TEXT ("QueueUserAPCEx")); -#else - GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx"); -#endif - } - - if (NULL == ptw32_register_cancelation) - { - ptw32_register_cancelation = ptw32_RegisterCancelation; - - if (ptw32_h_quserex != NULL) - { - (void) FreeLibrary (ptw32_h_quserex); - } - ptw32_h_quserex = 0; - } - else - { - /* Initialise QueueUserAPCEx */ - BOOL (*queue_user_apc_ex_init) (VOID); - - queue_user_apc_ex_init = (BOOL (*)(VOID)) -#if defined(NEED_UNICODE_CONSTS) - GetProcAddress (ptw32_h_quserex, - (const TCHAR *) TEXT ("QueueUserAPCEx_Init")); -#else - GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Init"); -#endif - - if (queue_user_apc_ex_init == NULL || !queue_user_apc_ex_init ()) - { - ptw32_register_cancelation = ptw32_RegisterCancelation; - - (void) FreeLibrary (ptw32_h_quserex); - ptw32_h_quserex = 0; - } - } - - if (ptw32_h_quserex) - { - ptw32_features |= PTW32_ALERTABLE_ASYNC_CANCEL; - } - - return result; -} - - -BOOL -pthread_win32_process_detach_np () -{ - if (ptw32_processInitialized) - { - ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); - - if (sp != NULL) - { - /* - * Detached threads have their resources automatically - * cleaned up upon exit (others must be 'joined'). - */ - if (sp->detachState == PTHREAD_CREATE_DETACHED) - { - ptw32_threadDestroy (sp->ptHandle); - TlsSetValue (ptw32_selfThreadKey->key, NULL); - } - } - - /* - * The DLL is being unmapped from the process's address space - */ - ptw32_processTerminate (); - - if (ptw32_h_quserex) - { - /* Close QueueUserAPCEx */ - BOOL (*queue_user_apc_ex_fini) (VOID); - - queue_user_apc_ex_fini = (BOOL (*)(VOID)) -#if defined(NEED_UNICODE_CONSTS) - GetProcAddress (ptw32_h_quserex, - (const TCHAR *) TEXT ("QueueUserAPCEx_Fini")); -#else - GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Fini"); -#endif - - if (queue_user_apc_ex_fini != NULL) - { - (void) queue_user_apc_ex_fini (); - } - (void) FreeLibrary (ptw32_h_quserex); - } - } - - return TRUE; -} - -BOOL -pthread_win32_thread_attach_np () -{ - return TRUE; -} - -BOOL -pthread_win32_thread_detach_np () -{ - if (ptw32_processInitialized) - { - /* - * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle - * unnecessarily. - */ - ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); - - if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle. - { - ptw32_mcs_local_node_t stateLock; - ptw32_callUserDestroyRoutines (sp->ptHandle); - - ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); - sp->state = PThreadStateLast; - /* - * If the thread is joinable at this point then it MUST be joined - * or detached explicitly by the application. - */ - ptw32_mcs_lock_release (&stateLock); - - /* - * Robust Mutexes - */ - while (sp->robustMxList != NULL) - { - pthread_mutex_t mx = sp->robustMxList->mx; - ptw32_robust_mutex_remove(&mx, sp); - (void) PTW32_INTERLOCKED_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent, - (PTW32_INTERLOCKED_LONG)-1); - /* - * If there are no waiters then the next thread to block will - * sleep, wakeup immediately and then go back to sleep. - * See pthread_mutex_lock.c. - */ - SetEvent(mx->event); - } - - - if (sp->detachState == PTHREAD_CREATE_DETACHED) - { - ptw32_threadDestroy (sp->ptHandle); - - TlsSetValue (ptw32_selfThreadKey->key, NULL); - } - } - } - - return TRUE; -} - -BOOL -pthread_win32_test_features_np (int feature_mask) -{ - return ((ptw32_features & feature_mask) == feature_mask); -} diff --git a/pthreads/src/ptw32_MCS_lock.c b/pthreads/src/ptw32_MCS_lock.c deleted file mode 100644 index d69cf80..0000000 --- a/pthreads/src/ptw32_MCS_lock.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * ptw32_MCS_lock.c - * - * Description: - * This translation unit implements queue-based locks. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -/* - * About MCS locks: - * - * MCS locks are queue-based locks, where the queue nodes are local to the - * thread. The 'lock' is nothing more than a global pointer that points to - * the last node in the queue, or is NULL if the queue is empty. - * - * Originally designed for use as spin locks requiring no kernel resources - * for synchronisation or blocking, the implementation below has adapted - * the MCS spin lock for use as a general mutex that will suspend threads - * when there is lock contention. - * - * Because the queue nodes are thread-local, most of the memory read/write - * operations required to add or remove nodes from the queue do not trigger - * cache-coherence updates. - * - * Like 'named' mutexes, MCS locks consume system resources transiently - - * they are able to acquire and free resources automatically - but MCS - * locks do not require any unique 'name' to identify the lock to all - * threads using it. - * - * Usage of MCS locks: - * - * - you need a global ptw32_mcs_lock_t instance initialised to 0 or NULL. - * - you need a local thread-scope ptw32_mcs_local_node_t instance, which - * may serve several different locks but you need at least one node for - * every lock held concurrently by a thread. - * - * E.g.: - * - * ptw32_mcs_lock_t lock1 = 0; - * ptw32_mcs_lock_t lock2 = 0; - * - * void *mythread(void *arg) - * { - * ptw32_mcs_local_node_t node; - * - * ptw32_mcs_acquire (&lock1, &node); - * ptw32_mcs_lock_release (&node); - * - * ptw32_mcs_lock_acquire (&lock2, &node); - * ptw32_mcs_lock_release (&node); - * { - * ptw32_mcs_local_node_t nodex; - * - * ptw32_mcs_lock_acquire (&lock1, &node); - * ptw32_mcs_lock_acquire (&lock2, &nodex); - * - * ptw32_mcs_lock_release (&nodex); - * ptw32_mcs_lock_release (&node); - * } - * return (void *)0; - * } - */ - -#include "pthread.h" -#include "sched.h" -#include "implement.h" - -/* - * ptw32_mcs_flag_set -- notify another thread about an event. - * - * Set event if an event handle has been stored in the flag, and - * set flag to -1 otherwise. Note that -1 cannot be a valid handle value. - */ -INLINE void -ptw32_mcs_flag_set (HANDLE * flag) -{ - HANDLE e = (HANDLE)(PTW32_INTERLOCKED_SIZE)PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)flag, - (PTW32_INTERLOCKED_SIZE)-1, - (PTW32_INTERLOCKED_SIZE)0); - if ((HANDLE)0 != e) - { - /* another thread has already stored an event handle in the flag */ - SetEvent(e); - } -} - -/* - * ptw32_mcs_flag_set -- wait for notification from another. - * - * Store an event handle in the flag and wait on it if the flag has not been - * set, and proceed without creating an event otherwise. - */ -INLINE void -ptw32_mcs_flag_wait (HANDLE * flag) -{ - if ((PTW32_INTERLOCKED_LONG)0 == - PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)flag, - (PTW32_INTERLOCKED_SIZE)0)) /* MBR fence */ - { - /* the flag is not set. create event. */ - - HANDLE e = CreateEvent(NULL, PTW32_FALSE, PTW32_FALSE, NULL); - - if ((PTW32_INTERLOCKED_SIZE)0 == PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)flag, - (PTW32_INTERLOCKED_SIZE)e, - (PTW32_INTERLOCKED_SIZE)0)) - { - /* stored handle in the flag. wait on it now. */ - WaitForSingleObject(e, INFINITE); - } - - CloseHandle(e); - } -} - -/* - * ptw32_mcs_lock_acquire -- acquire an MCS lock. - * - * See: - * J. M. Mellor-Crummey and M. L. Scott. - * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors. - * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991. - */ -#if defined(PTW32_BUILD_INLINED) -INLINE -#endif /* PTW32_BUILD_INLINED */ -void -ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node) -{ - ptw32_mcs_local_node_t *pred; - - node->lock = lock; - node->nextFlag = 0; - node->readyFlag = 0; - node->next = 0; /* initially, no successor */ - - /* queue for the lock */ - pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock, - (PTW32_INTERLOCKED_PVOID)node); - - if (0 != pred) - { - /* the lock was not free. link behind predecessor. */ - pred->next = node; - ptw32_mcs_flag_set(&pred->nextFlag); - ptw32_mcs_flag_wait(&node->readyFlag); - } -} - -/* - * ptw32_mcs_lock_release -- release an MCS lock. - * - * See: - * J. M. Mellor-Crummey and M. L. Scott. - * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors. - * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991. - */ -#if defined(PTW32_BUILD_INLINED) -INLINE -#endif /* PTW32_BUILD_INLINED */ -void -ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node) -{ - ptw32_mcs_lock_t *lock = node->lock; - ptw32_mcs_local_node_t *next = - (ptw32_mcs_local_node_t *) - PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); /* MBR fence */ - - if (0 == next) - { - /* no known successor */ - - if (node == (ptw32_mcs_local_node_t *) - PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock, - (PTW32_INTERLOCKED_PVOID)0, - (PTW32_INTERLOCKED_PVOID)node)) - { - /* no successor, lock is free now */ - return; - } - - /* wait for successor */ - ptw32_mcs_flag_wait(&node->nextFlag); - next = (ptw32_mcs_local_node_t *) - PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); /* MBR fence */ - } - - /* pass the lock */ - ptw32_mcs_flag_set(&next->readyFlag); -} - -/* - * ptw32_mcs_lock_try_acquire - */ -#if defined(PTW32_BUILD_INLINED) -INLINE -#endif /* PTW32_BUILD_INLINED */ -int -ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node) -{ - node->lock = lock; - node->nextFlag = 0; - node->readyFlag = 0; - node->next = 0; /* initially, no successor */ - - return ((PTW32_INTERLOCKED_PVOID)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock, - (PTW32_INTERLOCKED_PVOID)node, - (PTW32_INTERLOCKED_PVOID)0) - == (PTW32_INTERLOCKED_PVOID)0) ? 0 : EBUSY; -} - -/* - * ptw32_mcs_node_transfer -- move an MCS lock local node, usually from thread - * space to, for example, global space so that another thread can release - * the lock on behalf of the current lock owner. - * - * Example: used in pthread_barrier_wait where we want the last thread out of - * the barrier to release the lock owned by the last thread to enter the barrier - * (the one that releases all threads but not necessarily the last to leave). - * - * Should only be called by the thread that has the lock. - */ -#if defined(PTW32_BUILD_INLINED) -INLINE -#endif /* PTW32_BUILD_INLINED */ -void -ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node) -{ - new_node->lock = old_node->lock; - new_node->nextFlag = 0; /* Not needed - used only in initial Acquire */ - new_node->readyFlag = 0; /* Not needed - we were waiting on this */ - new_node->next = 0; - - if ((ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)new_node->lock, - (PTW32_INTERLOCKED_PVOID)new_node, - (PTW32_INTERLOCKED_PVOID)old_node) - != old_node) - { - /* - * A successor has queued after us, so wait for them to link to us - */ - while (old_node->next == 0) - { - sched_yield(); - } - new_node->next = old_node->next; - } -} diff --git a/pthreads/src/ptw32_callUserDestroyRoutines.c b/pthreads/src/ptw32_callUserDestroyRoutines.c deleted file mode 100644 index f290f7b..0000000 --- a/pthreads/src/ptw32_callUserDestroyRoutines.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * ptw32_callUserDestroyRoutines.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -#if defined(__CLEANUP_CXX) -# if defined(_MSC_VER) -# include -# elif defined(__WATCOMC__) -# include -# include -# else -# if defined(__GNUC__) && __GNUC__ < 3 -# include -# else -# include - using - std::terminate; -# endif -# endif -#endif - -void -ptw32_callUserDestroyRoutines (pthread_t thread) - /* - * ------------------------------------------------------------------- - * DOCPRIVATE - * - * This the routine runs through all thread keys and calls - * the destroy routines on the user's data for the current thread. - * It simulates the behaviour of POSIX Threads. - * - * PARAMETERS - * thread - * an instance of pthread_t - * - * RETURNS - * N/A - * ------------------------------------------------------------------- - */ -{ - ThreadKeyAssoc * assoc; - - if (thread.p != NULL) - { - ptw32_mcs_local_node_t threadLock; - ptw32_mcs_local_node_t keyLock; - int assocsRemaining; - int iterations = 0; - ptw32_thread_t * sp = (ptw32_thread_t *) thread.p; - - /* - * Run through all Thread<-->Key associations - * for the current thread. - * - * Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times. - */ - do - { - assocsRemaining = 0; - iterations++; - - ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock); - /* - * The pointer to the next assoc is stored in the thread struct so that - * the assoc destructor in pthread_key_delete can adjust it - * if it deletes this assoc. This can happen if we fail to acquire - * both locks below, and are forced to release all of our locks, - * leaving open the opportunity for pthread_key_delete to get in - * before us. - */ - sp->nextAssoc = sp->keys; - ptw32_mcs_lock_release(&threadLock); - - for (;;) - { - void * value; - pthread_key_t k; - void (*destructor) (void *); - - /* - * First we need to serialise with pthread_key_delete by locking - * both assoc guards, but in the reverse order to our convention, - * so we must be careful to avoid deadlock. - */ - ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock); - - if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL) - { - /* Finished */ - ptw32_mcs_lock_release(&threadLock); - break; - } - else - { - /* - * assoc->key must be valid because assoc can't change or be - * removed from our chain while we hold at least one lock. If - * the assoc was on our key chain then the key has not been - * deleted yet. - * - * Now try to acquire the second lock without deadlocking. - * If we fail, we need to relinquish the first lock and the - * processor and then try to acquire them all again. - */ - if (ptw32_mcs_lock_try_acquire(&(assoc->key->keyLock), &keyLock) == EBUSY) - { - ptw32_mcs_lock_release(&threadLock); - Sleep(0); - /* - * Go around again. - * If pthread_key_delete has removed this assoc in the meantime, - * sp->nextAssoc will point to a new assoc. - */ - continue; - } - } - - /* We now hold both locks */ - - sp->nextAssoc = assoc->nextKey; - - /* - * Key still active; pthread_key_delete - * will block on these same mutexes before - * it can release actual key; therefore, - * key is valid and we can call the destroy - * routine; - */ - k = assoc->key; - destructor = k->destructor; - value = TlsGetValue(k->key); - TlsSetValue (k->key, NULL); - - // Every assoc->key exists and has a destructor - if (value != NULL && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS) - { - /* - * Unlock both locks before the destructor runs. - * POSIX says pthread_key_delete can be run from destructors, - * and that probably includes with this key as target. - * pthread_setspecific can also be run from destructors and - * also needs to be able to access the assocs. - */ - ptw32_mcs_lock_release(&threadLock); - ptw32_mcs_lock_release(&keyLock); - - assocsRemaining++; - -#if defined(__cplusplus) - - try - { - /* - * Run the caller's cleanup routine. - */ - destructor (value); - } - catch (...) - { - /* - * A system unexpected exception has occurred - * running the user's destructor. - * We get control back within this block in case - * the application has set up it's own terminate - * handler. Since we are leaving the thread we - * should not get any internal pthreads - * exceptions. - */ - terminate (); - } - -#else /* __cplusplus */ - - /* - * Run the caller's cleanup routine. - */ - destructor (value); - -#endif /* __cplusplus */ - - } - else - { - /* - * Remove association from both the key and thread chains - * and reclaim it's memory resources. - */ - ptw32_tkAssocDestroy (assoc); - ptw32_mcs_lock_release(&threadLock); - ptw32_mcs_lock_release(&keyLock); - } - } - } - while (assocsRemaining); - } -} /* ptw32_callUserDestroyRoutines */ diff --git a/pthreads/src/ptw32_calloc.c b/pthreads/src/ptw32_calloc.c deleted file mode 100644 index e7b9e64..0000000 --- a/pthreads/src/ptw32_calloc.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * ptw32_calloc.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -#if defined(NEED_CALLOC) -void * -ptw32_calloc (size_t n, size_t s) -{ - unsigned int m = n * s; - void *p; - - p = malloc (m); - if (p == NULL) - return NULL; - - memset (p, 0, m); - - return p; -} -#endif diff --git a/pthreads/src/ptw32_cond_check_need_init.c b/pthreads/src/ptw32_cond_check_need_init.c deleted file mode 100644 index ec3e8bb..0000000 --- a/pthreads/src/ptw32_cond_check_need_init.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * ptw32_cond_check_need_init.c - * - * Description: - * This translation unit implements condition variables and their primitives. - * - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -INLINE int -ptw32_cond_check_need_init (pthread_cond_t * cond) -{ - int result = 0; - ptw32_mcs_local_node_t node; - - /* - * The following guarded test is specifically for statically - * initialised condition variables (via PTHREAD_OBJECT_INITIALIZER). - */ - ptw32_mcs_lock_acquire(&ptw32_cond_test_init_lock, &node); - - /* - * We got here possibly under race - * conditions. Check again inside the critical section. - * If a static cv has been destroyed, the application can - * re-initialise it only by calling pthread_cond_init() - * explicitly. - */ - if (*cond == PTHREAD_COND_INITIALIZER) - { - result = pthread_cond_init (cond, NULL); - } - else if (*cond == NULL) - { - /* - * The cv has been destroyed while we were waiting to - * initialise it, so the operation that caused the - * auto-initialisation should fail. - */ - result = EINVAL; - } - - ptw32_mcs_lock_release(&node); - - return result; -} diff --git a/pthreads/src/ptw32_getprocessors.c b/pthreads/src/ptw32_getprocessors.c deleted file mode 100644 index e60c314..0000000 --- a/pthreads/src/ptw32_getprocessors.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * ptw32_getprocessors.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -/* - * ptw32_getprocessors() - * - * Get the number of CPUs available to the process. - * - * If the available number of CPUs is 1 then pthread_spin_lock() - * will block rather than spin if the lock is already owned. - * - * pthread_spin_init() calls this routine when initialising - * a spinlock. If the number of available processors changes - * (after a call to SetProcessAffinityMask()) then only - * newly initialised spinlocks will notice. - */ -int -ptw32_getprocessors (int *count) -{ - DWORD_PTR vProcessCPUs; - DWORD_PTR vSystemCPUs; - int result = 0; - -#if defined(NEED_PROCESS_AFFINITY_MASK) - - *count = 1; - -#else - - if (GetProcessAffinityMask (GetCurrentProcess (), - &vProcessCPUs, &vSystemCPUs)) - { - DWORD_PTR bit; - int CPUs = 0; - - for (bit = 1; bit != 0; bit <<= 1) - { - if (vProcessCPUs & bit) - { - CPUs++; - } - } - *count = CPUs; - } - else - { - result = EAGAIN; - } - -#endif - - return (result); -} diff --git a/pthreads/src/ptw32_is_attr.c b/pthreads/src/ptw32_is_attr.c deleted file mode 100644 index 36395f8..0000000 --- a/pthreads/src/ptw32_is_attr.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ptw32_is_attr.c - * - * Description: - * This translation unit implements operations on thread attribute objects. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -int -ptw32_is_attr (const pthread_attr_t * attr) -{ - /* Return 0 if the attr object is valid, non-zero otherwise. */ - - return (attr == NULL || - *attr == NULL || (*attr)->valid != PTW32_ATTR_VALID); -} diff --git a/pthreads/src/ptw32_mutex_check_need_init.c b/pthreads/src/ptw32_mutex_check_need_init.c deleted file mode 100644 index 897db3c..0000000 --- a/pthreads/src/ptw32_mutex_check_need_init.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ptw32_mutex_check_need_init.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -static struct pthread_mutexattr_t_ ptw32_recursive_mutexattr_s = - {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_RECURSIVE}; -static struct pthread_mutexattr_t_ ptw32_errorcheck_mutexattr_s = - {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_ERRORCHECK}; -static pthread_mutexattr_t ptw32_recursive_mutexattr = &ptw32_recursive_mutexattr_s; -static pthread_mutexattr_t ptw32_errorcheck_mutexattr = &ptw32_errorcheck_mutexattr_s; - - -INLINE int -ptw32_mutex_check_need_init (pthread_mutex_t * mutex) -{ - register int result = 0; - register pthread_mutex_t mtx; - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_mutex_test_init_lock, &node); - - /* - * We got here possibly under race - * conditions. Check again inside the critical section - * and only initialise if the mutex is valid (not been destroyed). - * If a static mutex has been destroyed, the application can - * re-initialise it only by calling pthread_mutex_init() - * explicitly. - */ - mtx = *mutex; - - if (mtx == PTHREAD_MUTEX_INITIALIZER) - { - result = pthread_mutex_init (mutex, NULL); - } - else if (mtx == PTHREAD_RECURSIVE_MUTEX_INITIALIZER) - { - result = pthread_mutex_init (mutex, &ptw32_recursive_mutexattr); - } - else if (mtx == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) - { - result = pthread_mutex_init (mutex, &ptw32_errorcheck_mutexattr); - } - else if (mtx == NULL) - { - /* - * The mutex has been destroyed while we were waiting to - * initialise it, so the operation that caused the - * auto-initialisation should fail. - */ - result = EINVAL; - } - - ptw32_mcs_lock_release(&node); - - return (result); -} diff --git a/pthreads/src/ptw32_new.c b/pthreads/src/ptw32_new.c deleted file mode 100644 index ac836ea..0000000 --- a/pthreads/src/ptw32_new.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * ptw32_new.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -pthread_t -ptw32_new (void) -{ - pthread_t t; - pthread_t nil = {NULL, 0}; - ptw32_thread_t * tp; - - /* - * If there's a reusable pthread_t then use it. - */ - t = ptw32_threadReusePop (); - - if (NULL != t.p) - { - tp = (ptw32_thread_t *) t.p; - } - else - { - /* No reuse threads available */ - tp = (ptw32_thread_t *) calloc (1, sizeof(ptw32_thread_t)); - - if (tp == NULL) - { - return nil; - } - - /* ptHandle.p needs to point to it's parent ptw32_thread_t. */ - t.p = tp->ptHandle.p = tp; - t.x = tp->ptHandle.x = 0; - } - - /* Set default state. */ - tp->seqNumber = ++ptw32_threadSeqNumber; - tp->sched_priority = THREAD_PRIORITY_NORMAL; - tp->detachState = PTHREAD_CREATE_JOINABLE; - tp->cancelState = PTHREAD_CANCEL_ENABLE; - tp->cancelType = PTHREAD_CANCEL_DEFERRED; - tp->stateLock = 0; - tp->threadLock = 0; - tp->robustMxListLock = 0; - tp->robustMxList = NULL; - tp->cancelEvent = CreateEvent (0, (int) PTW32_TRUE, /* manualReset */ - (int) PTW32_FALSE, /* setSignaled */ - NULL); - - if (tp->cancelEvent == NULL) - { - ptw32_threadReusePush (tp->ptHandle); - return nil; - } - - return t; - -} diff --git a/pthreads/src/ptw32_processInitialize.c b/pthreads/src/ptw32_processInitialize.c deleted file mode 100644 index 8da3e41..0000000 --- a/pthreads/src/ptw32_processInitialize.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ptw32_processInitialize.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -ptw32_processInitialize (void) - /* - * ------------------------------------------------------ - * DOCPRIVATE - * This function performs process wide initialization for - * the pthread library. - * - * PARAMETERS - * N/A - * - * DESCRIPTION - * This function performs process wide initialization for - * the pthread library. - * If successful, this routine sets the global variable - * ptw32_processInitialized to TRUE. - * - * RESULTS - * TRUE if successful, - * FALSE otherwise - * - * ------------------------------------------------------ - */ -{ - if (ptw32_processInitialized) - { - /* - * Ignore if already initialized. this is useful for - * programs that uses a non-dll pthread - * library. Such programs must call ptw32_processInitialize() explicitly, - * since this initialization routine is automatically called only when - * the dll is loaded. - */ - return PTW32_TRUE; - } - - ptw32_processInitialized = PTW32_TRUE; - - /* - * Initialize Keys - */ - if ((pthread_key_create (&ptw32_selfThreadKey, NULL) != 0) || - (pthread_key_create (&ptw32_cleanupKey, NULL) != 0)) - { - - ptw32_processTerminate (); - } - - return (ptw32_processInitialized); - -} /* processInitialize */ diff --git a/pthreads/src/ptw32_processTerminate.c b/pthreads/src/ptw32_processTerminate.c deleted file mode 100644 index 83f0f23..0000000 --- a/pthreads/src/ptw32_processTerminate.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ptw32_processTerminate.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -void -ptw32_processTerminate (void) - /* - * ------------------------------------------------------ - * DOCPRIVATE - * This function performs process wide termination for - * the pthread library. - * - * PARAMETERS - * N/A - * - * DESCRIPTION - * This function performs process wide termination for - * the pthread library. - * This routine sets the global variable - * ptw32_processInitialized to FALSE - * - * RESULTS - * N/A - * - * ------------------------------------------------------ - */ -{ - if (ptw32_processInitialized) - { - ptw32_thread_t * tp, * tpNext; - ptw32_mcs_local_node_t node; - - if (ptw32_selfThreadKey != NULL) - { - /* - * Release ptw32_selfThreadKey - */ - pthread_key_delete (ptw32_selfThreadKey); - - ptw32_selfThreadKey = NULL; - } - - if (ptw32_cleanupKey != NULL) - { - /* - * Release ptw32_cleanupKey - */ - pthread_key_delete (ptw32_cleanupKey); - - ptw32_cleanupKey = NULL; - } - - ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); - - tp = ptw32_threadReuseTop; - while (tp != PTW32_THREAD_REUSE_EMPTY) - { - tpNext = tp->prevReuse; - free (tp); - tp = tpNext; - } - - ptw32_mcs_lock_release(&node); - - ptw32_processInitialized = PTW32_FALSE; - } - -} /* processTerminate */ diff --git a/pthreads/src/ptw32_relmillisecs.c b/pthreads/src/ptw32_relmillisecs.c deleted file mode 100644 index 894d5c9..0000000 --- a/pthreads/src/ptw32_relmillisecs.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * ptw32_relmillisecs.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#if !defined(NEED_FTIME) -#include -#endif - - -#if defined(PTW32_BUILD_INLINED) -INLINE -#endif /* PTW32_BUILD_INLINED */ -DWORD -ptw32_relmillisecs (const struct timespec * abstime) -{ - const int64_t NANOSEC_PER_MILLISEC = 1000000; - const int64_t MILLISEC_PER_SEC = 1000; - DWORD milliseconds; - int64_t tmpAbsMilliseconds; - int64_t tmpCurrMilliseconds; -#if defined(NEED_FTIME) - struct timespec currSysTime; - FILETIME ft; - SYSTEMTIME st; -#else /* ! NEED_FTIME */ -#if ( defined(_MSC_VER) && _MSC_VER >= 1300 ) || \ - ( (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601 ) - struct __timeb64 currSysTime; -#else - struct _timeb currSysTime; -#endif -#endif /* NEED_FTIME */ - - - /* - * Calculate timeout as milliseconds from current system time. - */ - - /* - * subtract current system time from abstime in a way that checks - * that abstime is never in the past, or is never equivalent to the - * defined INFINITE value (0xFFFFFFFF). - * - * Assume all integers are unsigned, i.e. cannot test if less than 0. - */ - tmpAbsMilliseconds = (int64_t)abstime->tv_sec * MILLISEC_PER_SEC; - tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC; - - /* get current system time */ - -#if defined(NEED_FTIME) - - GetSystemTime(&st); - SystemTimeToFileTime(&st, &ft); - /* - * GetSystemTimeAsFileTime(&ft); would be faster, - * but it does not exist on WinCE - */ - - ptw32_filetime_to_timespec(&ft, &currSysTime); - - tmpCurrMilliseconds = (int64_t)currSysTime.tv_sec * MILLISEC_PER_SEC; - tmpCurrMilliseconds += ((int64_t)currSysTime.tv_nsec + (NANOSEC_PER_MILLISEC/2)) - / NANOSEC_PER_MILLISEC; - -#else /* ! NEED_FTIME */ - -#if defined(_MSC_VER) && _MSC_VER >= 1400 - _ftime64_s(&currSysTime); -#elif ( defined(_MSC_VER) && _MSC_VER >= 1300 ) || \ - ( (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601 ) - _ftime64(&currSysTime); -#else - _ftime(&currSysTime); -#endif - - tmpCurrMilliseconds = (int64_t) currSysTime.time * MILLISEC_PER_SEC; - tmpCurrMilliseconds += (int64_t) currSysTime.millitm; - -#endif /* NEED_FTIME */ - - if (tmpAbsMilliseconds > tmpCurrMilliseconds) - { - milliseconds = (DWORD) (tmpAbsMilliseconds - tmpCurrMilliseconds); - if (milliseconds == INFINITE) - { - /* Timeouts must be finite */ - milliseconds--; - } - } - else - { - /* The abstime given is in the past */ - milliseconds = 0; - } - - return milliseconds; -} diff --git a/pthreads/src/ptw32_reuse.c b/pthreads/src/ptw32_reuse.c deleted file mode 100644 index 7325857..0000000 --- a/pthreads/src/ptw32_reuse.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * ptw32_threadReuse.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -/* - * How it works: - * A pthread_t is a struct (2x32 bit scalar types on IA-32, 2x64 bit on IA-64) - * which is normally passed/returned by value to/from pthreads routines. - * Applications are therefore storing a copy of the struct as it is at that - * time. - * - * The original pthread_t struct plus all copies of it contain the address of - * the thread state struct ptw32_thread_t_ (p), plus a reuse counter (x). Each - * ptw32_thread_t contains the original copy of it's pthread_t. - * Once malloced, a ptw32_thread_t_ struct is not freed until the process exits. - * - * The thread reuse stack is a simple LILO stack managed through a singly - * linked list element in the ptw32_thread_t. - * - * Each time a thread is destroyed, the ptw32_thread_t address is pushed onto the - * reuse stack after it's ptHandle's reuse counter has been incremented. - * - * The following can now be said from this: - * - two pthread_t's are identical if their ptw32_thread_t reference pointers - * are equal and their reuse counters are equal. That is, - * - * equal = (a.p == b.p && a.x == b.x) - * - * - a pthread_t copy refers to a destroyed thread if the reuse counter in - * the copy is not equal to the reuse counter in the original. - * - * threadDestroyed = (copy.x != ((ptw32_thread_t *)copy.p)->ptHandle.x) - * - */ - -/* - * Pop a clean pthread_t struct off the reuse stack. - */ -pthread_t -ptw32_threadReusePop (void) -{ - pthread_t t = {NULL, 0}; - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); - - if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseTop) - { - ptw32_thread_t * tp; - - tp = ptw32_threadReuseTop; - - ptw32_threadReuseTop = tp->prevReuse; - - if (PTW32_THREAD_REUSE_EMPTY == ptw32_threadReuseTop) - { - ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY; - } - - tp->prevReuse = NULL; - - t = tp->ptHandle; - } - - ptw32_mcs_lock_release(&node); - - return t; - -} - -/* - * Push a clean pthread_t struct onto the reuse stack. - * Must be re-initialised when reused. - * All object elements (mutexes, events etc) must have been either - * detroyed before this, or never initialised. - */ -void -ptw32_threadReusePush (pthread_t thread) -{ - ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; - pthread_t t; - ptw32_mcs_local_node_t node; - - ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); - - t = tp->ptHandle; - memset(tp, 0, sizeof(ptw32_thread_t)); - - /* Must restore the original POSIX handle that we just wiped. */ - tp->ptHandle = t; - - /* Bump the reuse counter now */ -#if defined(PTW32_THREAD_ID_REUSE_INCREMENT) - tp->ptHandle.x += PTW32_THREAD_ID_REUSE_INCREMENT; -#else - tp->ptHandle.x++; -#endif - - tp->state = PThreadStateReuse; - - tp->prevReuse = PTW32_THREAD_REUSE_EMPTY; - - if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseBottom) - { - ptw32_threadReuseBottom->prevReuse = tp; - } - else - { - ptw32_threadReuseTop = tp; - } - - ptw32_threadReuseBottom = tp; - - ptw32_mcs_lock_release(&node); -} diff --git a/pthreads/src/ptw32_rwlock_cancelwrwait.c b/pthreads/src/ptw32_rwlock_cancelwrwait.c deleted file mode 100644 index a057bd1..0000000 --- a/pthreads/src/ptw32_rwlock_cancelwrwait.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ptw32_rwlock_cancelwrwait.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -void -ptw32_rwlock_cancelwrwait (void *arg) -{ - pthread_rwlock_t rwl = (pthread_rwlock_t) arg; - - rwl->nSharedAccessCount = -rwl->nCompletedSharedAccessCount; - rwl->nCompletedSharedAccessCount = 0; - - (void) pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); - (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); -} diff --git a/pthreads/src/ptw32_rwlock_check_need_init.c b/pthreads/src/ptw32_rwlock_check_need_init.c deleted file mode 100644 index 858ee27..0000000 --- a/pthreads/src/ptw32_rwlock_check_need_init.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * pthread_rwlock_check_need_init.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -INLINE int -ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock) -{ - int result = 0; - ptw32_mcs_local_node_t node; - - /* - * The following guarded test is specifically for statically - * initialised rwlocks (via PTHREAD_RWLOCK_INITIALIZER). - */ - ptw32_mcs_lock_acquire(&ptw32_rwlock_test_init_lock, &node); - - /* - * We got here possibly under race - * conditions. Check again inside the critical section - * and only initialise if the rwlock is valid (not been destroyed). - * If a static rwlock has been destroyed, the application can - * re-initialise it only by calling pthread_rwlock_init() - * explicitly. - */ - if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) - { - result = pthread_rwlock_init (rwlock, NULL); - } - else if (*rwlock == NULL) - { - /* - * The rwlock has been destroyed while we were waiting to - * initialise it, so the operation that caused the - * auto-initialisation should fail. - */ - result = EINVAL; - } - - ptw32_mcs_lock_release(&node); - - return result; -} diff --git a/pthreads/src/ptw32_semwait.c b/pthreads/src/ptw32_semwait.c deleted file mode 100644 index c3c4fd0..0000000 --- a/pthreads/src/ptw32_semwait.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * ptw32_semwait.c - * - * Description: - * This translation unit implements mutual exclusion (mutex) primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined(_UWIN) -/*# include */ -#endif -#include "pthread.h" -#include "implement.h" - - -int -ptw32_semwait (sem_t * sem) - /* - * ------------------------------------------------------ - * DESCRIPTION - * This function waits on a POSIX semaphore. If the - * semaphore value is greater than zero, it decreases - * its value by one. If the semaphore value is zero, then - * the calling thread (or process) is blocked until it can - * successfully decrease the value. - * - * Unlike sem_wait(), this routine is non-cancelable. - * - * RESULTS - * 0 successfully decreased semaphore, - * -1 failed, error in errno. - * ERRNO - * EINVAL 'sem' is not a valid semaphore, - * ENOSYS semaphores are not supported, - * EINTR the function was interrupted by a signal, - * EDEADLK a deadlock condition was detected. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - sem_t s = *sem; - - if (s == NULL) - { - result = EINVAL; - } - else - { - if ((result = pthread_mutex_lock (&s->lock)) == 0) - { - int v; - - /* See sem_destroy.c - */ - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - errno = EINVAL; - return -1; - } - - v = --s->value; - (void) pthread_mutex_unlock (&s->lock); - - if (v < 0) - { - /* Must wait */ - if (WaitForSingleObject (s->sem, INFINITE) == WAIT_OBJECT_0) - { -#if defined(NEED_SEM) - if (pthread_mutex_lock (&s->lock) == 0) - { - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - errno = EINVAL; - return -1; - } - - if (s->leftToUnblock > 0) - { - --s->leftToUnblock; - SetEvent(s->sem); - } - (void) pthread_mutex_unlock (&s->lock); - } -#endif - return 0; - } - } - else - { - return 0; - } - } - } - - if (result != 0) - { - errno = result; - return -1; - } - - return 0; - -} /* ptw32_semwait */ diff --git a/pthreads/src/ptw32_spinlock_check_need_init.c b/pthreads/src/ptw32_spinlock_check_need_init.c deleted file mode 100644 index 8808454..0000000 --- a/pthreads/src/ptw32_spinlock_check_need_init.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * ptw32_spinlock_check_need_init.c - * - * Description: - * This translation unit implements spin lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -INLINE int -ptw32_spinlock_check_need_init (pthread_spinlock_t * lock) -{ - int result = 0; - ptw32_mcs_local_node_t node; - - /* - * The following guarded test is specifically for statically - * initialised spinlocks (via PTHREAD_SPINLOCK_INITIALIZER). - */ - ptw32_mcs_lock_acquire(&ptw32_spinlock_test_init_lock, &node); - - /* - * We got here possibly under race - * conditions. Check again inside the critical section - * and only initialise if the spinlock is valid (not been destroyed). - * If a static spinlock has been destroyed, the application can - * re-initialise it only by calling pthread_spin_init() - * explicitly. - */ - if (*lock == PTHREAD_SPINLOCK_INITIALIZER) - { - result = pthread_spin_init (lock, PTHREAD_PROCESS_PRIVATE); - } - else if (*lock == NULL) - { - /* - * The spinlock has been destroyed while we were waiting to - * initialise it, so the operation that caused the - * auto-initialisation should fail. - */ - result = EINVAL; - } - - ptw32_mcs_lock_release(&node); - - return (result); -} diff --git a/pthreads/src/ptw32_threadDestroy.c b/pthreads/src/ptw32_threadDestroy.c deleted file mode 100644 index 41499b1..0000000 --- a/pthreads/src/ptw32_threadDestroy.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * ptw32_threadDestroy.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -void -ptw32_threadDestroy (pthread_t thread) -{ - ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; - ptw32_thread_t threadCopy; - - if (tp != NULL) - { - /* - * Copy thread state so that the thread can be atomically NULLed. - */ - memcpy (&threadCopy, tp, sizeof (threadCopy)); - - /* - * Thread ID structs are never freed. They're NULLed and reused. - * This also sets the thread to PThreadStateInitial (invalid). - */ - ptw32_threadReusePush (thread); - - /* Now work on the copy. */ - if (threadCopy.cancelEvent != NULL) - { - CloseHandle (threadCopy.cancelEvent); - } - -#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__) - /* - * See documentation for endthread vs endthreadex. - */ - if (threadCopy.threadH != 0) - { - CloseHandle (threadCopy.threadH); - } -#endif - - } -} /* ptw32_threadDestroy */ - diff --git a/pthreads/src/ptw32_threadStart.c b/pthreads/src/ptw32_threadStart.c deleted file mode 100644 index cb08403..0000000 --- a/pthreads/src/ptw32_threadStart.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * ptw32_threadStart.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include - -#if defined(__CLEANUP_C) -# include -#endif - -#if defined(__CLEANUP_SEH) - -static DWORD -ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei) -{ - switch (ep->ExceptionRecord->ExceptionCode) - { - case EXCEPTION_PTW32_SERVICES: - { - DWORD param; - DWORD numParams = ep->ExceptionRecord->NumberParameters; - - numParams = (numParams > 3) ? 3 : numParams; - - for (param = 0; param < numParams; param++) - { - ei[param] = ep->ExceptionRecord->ExceptionInformation[param]; - } - - return EXCEPTION_EXECUTE_HANDLER; - break; - } - default: - { - /* - * A system unexpected exception has occurred running the user's - * routine. We need to cleanup before letting the exception - * out of thread scope. - */ - pthread_t self = pthread_self (); - - ptw32_callUserDestroyRoutines (self); - - return EXCEPTION_CONTINUE_SEARCH; - break; - } - } -} - -#elif defined(__CLEANUP_CXX) - -#if defined(_MSC_VER) -# include -#elif defined(__WATCOMC__) -# include -# include -typedef terminate_handler - terminate_function; -#else -# if defined(__GNUC__) && __GNUC__ < 3 -# include -# else -# include -using - std::terminate_handler; -using - std::terminate; -using - std::set_terminate; -# endif -typedef terminate_handler - terminate_function; -#endif - -static terminate_function - ptw32_oldTerminate; - -void -ptw32_terminate () -{ - set_terminate (ptw32_oldTerminate); - (void) pthread_win32_thread_detach_np (); - terminate (); -} - -#endif - -#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || (defined (__MSVCRT__) && ! defined (__DMC__)) -unsigned - __stdcall -#else -void -#endif -ptw32_threadStart (void *vthreadParms) -{ - ThreadParms * threadParms = (ThreadParms *) vthreadParms; - pthread_t self; - ptw32_thread_t * sp; - void *(*start) (void *); - void * arg; - -#if defined(__CLEANUP_SEH) - DWORD - ei[] = { 0, 0, 0 }; -#endif - -#if defined(__CLEANUP_C) - int setjmp_rc; -#endif - - ptw32_mcs_local_node_t stateLock; - void * status = (void *) 0; - - self = threadParms->tid; - sp = (ptw32_thread_t *) self.p; - start = threadParms->start; - arg = threadParms->arg; - - free (threadParms); - -#if (defined(__MINGW64__) || defined(__MINGW32__)) && ! defined (__MSVCRT__) - /* - * beginthread does not return the thread id and is running - * before it returns us the thread handle, and so we do it here. - */ - sp->thread = GetCurrentThreadId (); - /* - * Here we're using stateLock as a general-purpose lock - * to make the new thread wait until the creating thread - * has the new handle. - */ - ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); - pthread_setspecific (ptw32_selfThreadKey, sp); -#else - pthread_setspecific (ptw32_selfThreadKey, sp); - ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); -#endif - - sp->state = PThreadStateRunning; - ptw32_mcs_lock_release (&stateLock); - -#if defined(__CLEANUP_SEH) - - __try - { - /* - * Run the caller's routine; - */ - status = sp->exitStatus = (*start) (arg); - sp->state = PThreadStateExiting; - -#if defined(_UWIN) - if (--pthread_count <= 0) - exit (0); -#endif - - } - __except (ExceptionFilter (GetExceptionInformation (), ei)) - { - switch (ei[0]) - { - case PTW32_EPS_CANCEL: - status = sp->exitStatus = PTHREAD_CANCELED; -#if defined(_UWIN) - if (--pthread_count <= 0) - exit (0); -#endif - break; - case PTW32_EPS_EXIT: - status = sp->exitStatus; - break; - default: - status = sp->exitStatus = PTHREAD_CANCELED; - break; - } - } - -#else /* __CLEANUP_SEH */ - -#if defined(__CLEANUP_C) - - setjmp_rc = setjmp (sp->start_mark); - - if (0 == setjmp_rc) - { - - /* - * Run the caller's routine; - */ - status = sp->exitStatus = (*start) (arg); - sp->state = PThreadStateExiting; - } - else - { - switch (setjmp_rc) - { - case PTW32_EPS_CANCEL: - status = sp->exitStatus = PTHREAD_CANCELED; - break; - case PTW32_EPS_EXIT: - status = sp->exitStatus; - break; - default: - status = sp->exitStatus = PTHREAD_CANCELED; - break; - } - } - -#else /* __CLEANUP_C */ - -#if defined(__CLEANUP_CXX) - - ptw32_oldTerminate = set_terminate (&ptw32_terminate); - - try - { - /* - * Run the caller's routine in a nested try block so that we - * can run the user's terminate function, which may call - * pthread_exit() or be canceled. - */ - try - { - status = sp->exitStatus = (*start) (arg); - sp->state = PThreadStateExiting; - } - catch (ptw32_exception &) - { - /* - * Pass these through to the outer block. - */ - throw; - } - catch (...) - { - /* - * We want to run the user's terminate function if supplied. - * That function may call pthread_exit() or be canceled, which will - * be handled by the outer try block. - * - * ptw32_terminate() will be called if there is no user - * supplied function. - */ - terminate_function - term_func = set_terminate (0); - set_terminate (term_func); - - if (term_func != 0) - { - term_func (); - } - throw; - } - } - catch (ptw32_exception_cancel &) - { - /* - * Thread was canceled. - */ - status = sp->exitStatus = PTHREAD_CANCELED; - } - catch (ptw32_exception_exit &) - { - /* - * Thread was exited via pthread_exit(). - */ - status = sp->exitStatus; - } - catch (...) - { - /* - * A system unexpected exception has occurred running the user's - * terminate routine. We get control back within this block - * and exit with a substitute status. If the thread was not - * cancelled then this indicates the unhandled exception. - */ - status = sp->exitStatus = PTHREAD_CANCELED; - } - - (void) set_terminate (ptw32_oldTerminate); - -#else - -#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. - -#endif /* __CLEANUP_CXX */ -#endif /* __CLEANUP_C */ -#endif /* __CLEANUP_SEH */ - -#if defined(PTW32_STATIC_LIB) - /* - * We need to cleanup the pthread now if we have - * been statically linked, in which case the cleanup - * in dllMain won't get done. Joinable threads will - * only be partially cleaned up and must be fully cleaned - * up by pthread_join() or pthread_detach(). - * - * Note: if this library has been statically linked, - * implicitly created pthreads (those created - * for Win32 threads which have called pthreads routines) - * must be cleaned up explicitly by the application - * (by calling pthread_win32_thread_detach_np()). - * For the dll, dllMain will do the cleanup automatically. - */ - (void) pthread_win32_thread_detach_np (); -#endif - -#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__) - _endthreadex ((unsigned)(size_t) status); -#else - _endthread (); -#endif - - /* - * Never reached. - */ - -#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__) - return (unsigned)(size_t) status; -#endif - -} /* ptw32_threadStart */ diff --git a/pthreads/src/ptw32_throw.c b/pthreads/src/ptw32_throw.c deleted file mode 100644 index 1404e94..0000000 --- a/pthreads/src/ptw32_throw.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * ptw32_throw.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - -#if defined(__CLEANUP_C) -# include -#endif - -/* - * ptw32_throw - * - * All canceled and explicitly exited POSIX threads go through - * here. This routine knows how to exit both POSIX initiated threads and - * 'implicit' POSIX threads for each of the possible language modes (C, - * C++, and SEH). - */ -#if defined(_MSC_VER) -/* - * Ignore the warning: - * "C++ exception specification ignored except to indicate that - * the function is not __declspec(nothrow)." - */ -#pragma warning(disable:4290) -#endif -void -ptw32_throw (DWORD exception) -#if defined(__CLEANUP_CXX) - throw(ptw32_exception_cancel,ptw32_exception_exit) -#endif -{ - /* - * Don't use pthread_self() to avoid creating an implicit POSIX thread handle - * unnecessarily. - */ - ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); - -#if defined(__CLEANUP_SEH) - DWORD exceptionInformation[3]; -#endif - - sp->state = PThreadStateExiting; - - if (exception != PTW32_EPS_CANCEL && exception != PTW32_EPS_EXIT) - { - /* Should never enter here */ - exit (1); - } - - if (NULL == sp || sp->implicit) - { - /* - * We're inside a non-POSIX initialised Win32 thread - * so there is no point to jump or throw back to. Just do an - * explicit thread exit here after cleaning up POSIX - * residue (i.e. cleanup handlers, POSIX thread handle etc). - */ -#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__) - unsigned exitCode = 0; - - switch (exception) - { - case PTW32_EPS_CANCEL: - exitCode = (unsigned)(size_t) PTHREAD_CANCELED; - break; - case PTW32_EPS_EXIT: - if (NULL != sp) - { - exitCode = (unsigned)(size_t) sp->exitStatus; - } - break; - } -#endif - -#if defined(PTW32_STATIC_LIB) - - pthread_win32_thread_detach_np (); - -#endif - -#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__) - _endthreadex (exitCode); -#else - _endthread (); -#endif - - } - -#if defined(__CLEANUP_SEH) - - - exceptionInformation[0] = (DWORD) (exception); - exceptionInformation[1] = (DWORD) (0); - exceptionInformation[2] = (DWORD) (0); - - RaiseException (EXCEPTION_PTW32_SERVICES, 0, 3, exceptionInformation); - -#else /* __CLEANUP_SEH */ - -#if defined(__CLEANUP_C) - - ptw32_pop_cleanup_all (1); - longjmp (sp->start_mark, exception); - -#else /* __CLEANUP_C */ - -#if defined(__CLEANUP_CXX) - - switch (exception) - { - case PTW32_EPS_CANCEL: - throw ptw32_exception_cancel (); - break; - case PTW32_EPS_EXIT: - throw ptw32_exception_exit (); - break; - } - -#else - -#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. - -#endif /* __CLEANUP_CXX */ - -#endif /* __CLEANUP_C */ - -#endif /* __CLEANUP_SEH */ - - /* Never reached */ -} - - -void -ptw32_pop_cleanup_all (int execute) -{ - while (NULL != ptw32_pop_cleanup (execute)) - { - } -} - - -DWORD -ptw32_get_exception_services_code (void) -{ -#if defined(__CLEANUP_SEH) - - return EXCEPTION_PTW32_SERVICES; - -#else - - return (DWORD)0; - -#endif -} diff --git a/pthreads/src/ptw32_timespec.c b/pthreads/src/ptw32_timespec.c deleted file mode 100644 index 6318957..0000000 --- a/pthreads/src/ptw32_timespec.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * ptw32_timespec.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -#if defined(NEED_FTIME) - -/* - * time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds - */ -#define PTW32_TIMESPEC_TO_FILETIME_OFFSET \ - ( ((int64_t) 27111902 << 32) + (int64_t) 3577643008 ) - -INLINE void -ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft) - /* - * ------------------------------------------------------------------- - * converts struct timespec - * where the time is expressed in seconds and nanoseconds from Jan 1, 1970. - * into FILETIME (as set by GetSystemTimeAsFileTime), where the time is - * expressed in 100 nanoseconds from Jan 1, 1601, - * ------------------------------------------------------------------- - */ -{ - *(int64_t *) ft = ts->tv_sec * 10000000 - + (ts->tv_nsec + 50) / 100 + PTW32_TIMESPEC_TO_FILETIME_OFFSET; -} - -INLINE void -ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts) - /* - * ------------------------------------------------------------------- - * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is - * expressed in 100 nanoseconds from Jan 1, 1601, - * into struct timespec - * where the time is expressed in seconds and nanoseconds from Jan 1, 1970. - * ------------------------------------------------------------------- - */ -{ - ts->tv_sec = - (int) ((*(int64_t *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET) / 10000000); - ts->tv_nsec = - (int) ((*(int64_t *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET - - ((int64_t) ts->tv_sec * (int64_t) 10000000)) * 100); -} - -#endif /* NEED_FTIME */ diff --git a/pthreads/src/ptw32_tkAssocCreate.c b/pthreads/src/ptw32_tkAssocCreate.c deleted file mode 100644 index 50d6c50..0000000 --- a/pthreads/src/ptw32_tkAssocCreate.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * ptw32_tkAssocCreate.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -int -ptw32_tkAssocCreate (ptw32_thread_t * sp, pthread_key_t key) - /* - * ------------------------------------------------------------------- - * This routine creates an association that - * is unique for the given (thread,key) combination.The association - * is referenced by both the thread and the key. - * This association allows us to determine what keys the - * current thread references and what threads a given key - * references. - * See the detailed description - * at the beginning of this file for further details. - * - * Notes: - * 1) New associations are pushed to the beginning of the - * chain so that the internal ptw32_selfThreadKey association - * is always last, thus allowing selfThreadExit to - * be implicitly called last by pthread_exit. - * 2) - * - * Parameters: - * thread - * current running thread. - * key - * key on which to create an association. - * Returns: - * 0 - if successful, - * ENOMEM - not enough memory to create assoc or other object - * EINVAL - an internal error occurred - * ENOSYS - an internal error occurred - * ------------------------------------------------------------------- - */ -{ - ThreadKeyAssoc *assoc; - - /* - * Have to create an association and add it - * to both the key and the thread. - * - * Both key->keyLock and thread->threadLock are locked before - * entry to this routine. - */ - assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc)); - - if (assoc == NULL) - { - return ENOMEM; - } - - assoc->thread = sp; - assoc->key = key; - - /* - * Register assoc with key - */ - assoc->prevThread = NULL; - assoc->nextThread = (ThreadKeyAssoc *) key->threads; - if (assoc->nextThread != NULL) - { - assoc->nextThread->prevThread = assoc; - } - key->threads = (void *) assoc; - - /* - * Register assoc with thread - */ - assoc->prevKey = NULL; - assoc->nextKey = (ThreadKeyAssoc *) sp->keys; - if (assoc->nextKey != NULL) - { - assoc->nextKey->prevKey = assoc; - } - sp->keys = (void *) assoc; - - return (0); - -} /* ptw32_tkAssocCreate */ diff --git a/pthreads/src/ptw32_tkAssocDestroy.c b/pthreads/src/ptw32_tkAssocDestroy.c deleted file mode 100644 index fedebf5..0000000 --- a/pthreads/src/ptw32_tkAssocDestroy.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * ptw32_tkAssocDestroy.c - * - * Description: - * This translation unit implements routines which are private to - * the implementation and may be used throughout it. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -void -ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc) - /* - * ------------------------------------------------------------------- - * This routine releases all resources for the given ThreadKeyAssoc - * once it is no longer being referenced - * ie) either the key or thread has stopped referencing it. - * - * Parameters: - * assoc - * an instance of ThreadKeyAssoc. - * Returns: - * N/A - * ------------------------------------------------------------------- - */ -{ - - /* - * Both key->keyLock and thread->threadLock are locked before - * entry to this routine. - */ - if (assoc != NULL) - { - ThreadKeyAssoc * prev, * next; - - /* Remove assoc from thread's keys chain */ - prev = assoc->prevKey; - next = assoc->nextKey; - if (prev != NULL) - { - prev->nextKey = next; - } - if (next != NULL) - { - next->prevKey = prev; - } - - if (assoc->thread->keys == assoc) - { - /* We're at the head of the thread's keys chain */ - assoc->thread->keys = next; - } - if (assoc->thread->nextAssoc == assoc) - { - /* - * Thread is exiting and we're deleting the assoc to be processed next. - * Hand thread the assoc after this one. - */ - assoc->thread->nextAssoc = next; - } - - /* Remove assoc from key's threads chain */ - prev = assoc->prevThread; - next = assoc->nextThread; - if (prev != NULL) - { - prev->nextThread = next; - } - if (next != NULL) - { - next->prevThread = prev; - } - - if (assoc->key->threads == assoc) - { - /* We're at the head of the key's threads chain */ - assoc->key->threads = next; - } - - free (assoc); - } - -} /* ptw32_tkAssocDestroy */ diff --git a/pthreads/src/rwlock.c b/pthreads/src/rwlock.c deleted file mode 100644 index 4a3cd25..0000000 --- a/pthreads/src/rwlock.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * rwlock.c - * - * Description: - * This translation unit implements read/write lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "ptw32_rwlock_check_need_init.c" -#include "ptw32_rwlock_cancelwrwait.c" -#include "pthread_rwlock_init.c" -#include "pthread_rwlock_destroy.c" -#include "pthread_rwlockattr_init.c" -#include "pthread_rwlockattr_destroy.c" -#include "pthread_rwlockattr_getpshared.c" -#include "pthread_rwlockattr_setpshared.c" -#include "pthread_rwlock_rdlock.c" -#include "pthread_rwlock_timedrdlock.c" -#include "pthread_rwlock_wrlock.c" -#include "pthread_rwlock_timedwrlock.c" -#include "pthread_rwlock_unlock.c" -#include "pthread_rwlock_tryrdlock.c" -#include "pthread_rwlock_trywrlock.c" diff --git a/pthreads/src/sched.c b/pthreads/src/sched.c deleted file mode 100644 index ed30ea7..0000000 --- a/pthreads/src/sched.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * sched.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -#include "pthread_attr_setschedpolicy.c" -#include "pthread_attr_getschedpolicy.c" -#include "pthread_attr_setschedparam.c" -#include "pthread_attr_getschedparam.c" -#include "pthread_attr_setinheritsched.c" -#include "pthread_attr_getinheritsched.c" -#include "pthread_setschedparam.c" -#include "pthread_getschedparam.c" -#include "sched_get_priority_max.c" -#include "sched_get_priority_min.c" -#include "sched_setscheduler.c" -#include "sched_getscheduler.c" -#include "sched_yield.c" diff --git a/pthreads/src/sched.h b/pthreads/src/sched.h deleted file mode 100644 index f36a97a..0000000 --- a/pthreads/src/sched.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Module: sched.h - * - * Purpose: - * Provides an implementation of POSIX realtime extensions - * as defined in - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#if !defined(_SCHED_H) -#define _SCHED_H - -#undef PTW32_SCHED_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_SCHED_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_SCHED_LEVEL -#define PTW32_SCHED_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_SCHED_LEVEL -#define PTW32_SCHED_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_SCHED_LEVEL_MAX 3 - -#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL) -#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX -/* Include everything */ -#endif - - -#if defined(__GNUC__) && !defined(__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */ - -#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) -# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX -/* For pid_t */ -# include -/* Required by Unix 98 */ -# include -# else - typedef int pid_t; -# endif -#else - typedef int pid_t; -#endif - -/* Thread scheduling policies */ - -enum { - SCHED_OTHER = 0, - SCHED_FIFO, - SCHED_RR, - SCHED_MIN = SCHED_OTHER, - SCHED_MAX = SCHED_RR -}; - -struct sched_param { - int sched_priority; -}; - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -PTW32_DLLPORT int __cdecl sched_yield (void); - -PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); - -PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); - -PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); - -PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); - -/* - * Note that this macro returns ENOTSUP rather than - * ENOSYS as might be expected. However, returning ENOSYS - * should mean that sched_get_priority_{min,max} are - * not implemented as well as sched_rr_get_interval. - * This is not the case, since we just don't support - * round-robin scheduling. Therefore I have chosen to - * return the same value as sched_setscheduler when - * SCHED_RR is passed to it. - */ -#define sched_rr_get_interval(_pid, _interval) \ - ( errno = ENOTSUP, (int) -1 ) - - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#undef PTW32_SCHED_LEVEL -#undef PTW32_SCHED_LEVEL_MAX - -#endif /* !_SCHED_H */ - diff --git a/pthreads/src/sched_get_priority_max.c b/pthreads/src/sched_get_priority_max.c deleted file mode 100644 index cabf232..0000000 --- a/pthreads/src/sched_get_priority_max.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * sched_get_priority_max.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -/* - * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and - * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine. - * - * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5 - * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny: - * highest priority use smaller numbers) and the following happens: - * - * sched_get_priority_min() returns 5 - * sched_get_priority_max() returns 1 - * - * The following table shows the base priority levels for combinations - * of priority class and priority value in Win32. - * - * Process Priority Class Thread Priority Level - * ----------------------------------------------------------------- - * 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 17 REALTIME_PRIORITY_CLASS -7 - * 18 REALTIME_PRIORITY_CLASS -6 - * 19 REALTIME_PRIORITY_CLASS -5 - * 20 REALTIME_PRIORITY_CLASS -4 - * 21 REALTIME_PRIORITY_CLASS -3 - * 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 27 REALTIME_PRIORITY_CLASS 3 - * 28 REALTIME_PRIORITY_CLASS 4 - * 29 REALTIME_PRIORITY_CLASS 5 - * 30 REALTIME_PRIORITY_CLASS 6 - * 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * - * Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported. - */ - - -int -sched_get_priority_max (int policy) -{ - if (policy < SCHED_MIN || policy > SCHED_MAX) - { - errno = EINVAL; - return -1; - } - -#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) - /* WinCE? */ - return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); -#else - /* This is independent of scheduling policy in Win32. */ - return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); -#endif -} diff --git a/pthreads/src/sched_get_priority_min.c b/pthreads/src/sched_get_priority_min.c deleted file mode 100644 index 9c4f859..0000000 --- a/pthreads/src/sched_get_priority_min.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * sched_get_priority_min.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -/* - * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and - * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine. - * - * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5 - * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny: - * highest priority use smaller numbers) and the following happens: - * - * sched_get_priority_min() returns 5 - * sched_get_priority_max() returns 1 - * - * The following table shows the base priority levels for combinations - * of priority class and priority value in Win32. - * - * Process Priority Class Thread Priority Level - * ----------------------------------------------------------------- - * 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE - * 17 REALTIME_PRIORITY_CLASS -7 - * 18 REALTIME_PRIORITY_CLASS -6 - * 19 REALTIME_PRIORITY_CLASS -5 - * 20 REALTIME_PRIORITY_CLASS -4 - * 21 REALTIME_PRIORITY_CLASS -3 - * 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST - * 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL - * 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL - * 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL - * 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST - * 27 REALTIME_PRIORITY_CLASS 3 - * 28 REALTIME_PRIORITY_CLASS 4 - * 29 REALTIME_PRIORITY_CLASS 5 - * 30 REALTIME_PRIORITY_CLASS 6 - * 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL - * - * Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported. - * - */ - - -int -sched_get_priority_min (int policy) -{ - if (policy < SCHED_MIN || policy > SCHED_MAX) - { - errno = EINVAL; - return -1; - } - -#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) - /* WinCE? */ - return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); -#else - /* This is independent of scheduling policy in Win32. */ - return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); -#endif -} diff --git a/pthreads/src/sched_getscheduler.c b/pthreads/src/sched_getscheduler.c deleted file mode 100644 index 8769c15..0000000 --- a/pthreads/src/sched_getscheduler.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * sched_getscheduler.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -sched_getscheduler (pid_t pid) -{ - /* - * Win32 only has one policy which we call SCHED_OTHER. - * However, we try to provide other valid side-effects - * such as EPERM and ESRCH errors. - */ - if (0 != pid) - { - int selfPid = (int) GetCurrentProcessId (); - - if (pid != selfPid) - { - HANDLE h = - OpenProcess (PROCESS_QUERY_INFORMATION, PTW32_FALSE, (DWORD) pid); - - if (NULL == h) - { - errno = - (GetLastError () == - (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH; - return -1; - } - else - CloseHandle(h); - } - } - - return SCHED_OTHER; -} diff --git a/pthreads/src/sched_setscheduler.c b/pthreads/src/sched_setscheduler.c deleted file mode 100644 index 8691316..0000000 --- a/pthreads/src/sched_setscheduler.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * sched_setscheduler.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -sched_setscheduler (pid_t pid, int policy) -{ - /* - * Win32 only has one policy which we call SCHED_OTHER. - * However, we try to provide other valid side-effects - * such as EPERM and ESRCH errors. Choosing to check - * for a valid policy last allows us to get the most value out - * of this function. - */ - if (0 != pid) - { - int selfPid = (int) GetCurrentProcessId (); - - if (pid != selfPid) - { - HANDLE h = - OpenProcess (PROCESS_SET_INFORMATION, PTW32_FALSE, (DWORD) pid); - - if (NULL == h) - { - errno = - (GetLastError () == - (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH; - return -1; - } - else - CloseHandle(h); - } - } - - if (SCHED_OTHER != policy) - { - errno = ENOSYS; - return -1; - } - - /* - * Don't set anything because there is nothing to set. - * Just return the current (the only possible) value. - */ - return SCHED_OTHER; -} diff --git a/pthreads/src/sched_yield.c b/pthreads/src/sched_yield.c deleted file mode 100644 index 6ac5ed9..0000000 --- a/pthreads/src/sched_yield.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * sched_yield.c - * - * Description: - * POSIX thread functions that deal with thread scheduling. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" -#include "sched.h" - -int -sched_yield (void) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function indicates that the calling thread is - * willing to give up some time slices to other threads. - * - * PARAMETERS - * N/A - * - * - * DESCRIPTION - * This function indicates that the calling thread is - * willing to give up some time slices to other threads. - * NOTE: Since this is part of POSIX 1003.1b - * (realtime extensions), it is defined as returning - * -1 if an error occurs and sets errno to the actual - * error. - * - * RESULTS - * 0 successfully created semaphore, - * ENOSYS sched_yield not supported, - * - * ------------------------------------------------------ - */ -{ - Sleep (0); - - return 0; -} diff --git a/pthreads/src/sem_close.c b/pthreads/src/sem_close.c deleted file mode 100644 index 6d7280f..0000000 --- a/pthreads/src/sem_close.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_close.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - -/* ignore warning "unreferenced formal parameter" */ -#if defined(_MSC_VER) -#pragma warning( disable : 4100 ) -#endif - -int -sem_close (sem_t * sem) -{ - errno = ENOSYS; - return -1; -} /* sem_close */ diff --git a/pthreads/src/sem_destroy.c b/pthreads/src/sem_destroy.c deleted file mode 100644 index 6c98e80..0000000 --- a/pthreads/src/sem_destroy.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_destroy.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - - -int -sem_destroy (sem_t * sem) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function destroys an unnamed semaphore. - * - * PARAMETERS - * sem - * pointer to an instance of sem_t - * - * DESCRIPTION - * This function destroys an unnamed semaphore. - * - * RESULTS - * 0 successfully destroyed semaphore, - * -1 failed, error in errno - * ERRNO - * EINVAL 'sem' is not a valid semaphore, - * ENOSYS semaphores are not supported, - * EBUSY threads (or processes) are currently - * blocked on 'sem' - * - * ------------------------------------------------------ - */ -{ - int result = 0; - sem_t s = NULL; - - if (sem == NULL || *sem == NULL) - { - result = EINVAL; - } - else - { - s = *sem; - - if ((result = pthread_mutex_lock (&s->lock)) == 0) - { - if (s->value < 0) - { - (void) pthread_mutex_unlock (&s->lock); - result = EBUSY; - } - else - { - /* There are no threads currently blocked on this semaphore. */ - - if (!CloseHandle (s->sem)) - { - (void) pthread_mutex_unlock (&s->lock); - result = EINVAL; - } - else - { - /* - * Invalidate the semaphore handle when we have the lock. - * Other sema operations should test this after acquiring the lock - * to check that the sema is still valid, i.e. before performing any - * operations. This may only be necessary before the sema op routine - * returns so that the routine can return EINVAL - e.g. if setting - * s->value to SEM_VALUE_MAX below does force a fall-through. - */ - *sem = NULL; - - /* Prevent anyone else actually waiting on or posting this sema. - */ - s->value = SEM_VALUE_MAX; - - (void) pthread_mutex_unlock (&s->lock); - - do - { - /* Give other threads a chance to run and exit any sema op - * routines. Due to the SEM_VALUE_MAX value, if sem_post or - * sem_wait were blocked by us they should fall through. - */ - Sleep(0); - } - while (pthread_mutex_destroy (&s->lock) == EBUSY); - } - } - } - } - - if (result != 0) - { - errno = result; - return -1; - } - - free (s); - - return 0; - -} /* sem_destroy */ diff --git a/pthreads/src/sem_getvalue.c b/pthreads/src/sem_getvalue.c deleted file mode 100644 index baafb02..0000000 --- a/pthreads/src/sem_getvalue.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_getvalue.c - * - * Purpose: - * Semaphores aren't actually part of PThreads. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1-2001 - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - - -int -sem_getvalue (sem_t * sem, int *sval) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function stores the current count value of the - * semaphore. - * RESULTS - * - * Return value - * - * 0 sval has been set. - * -1 failed, error in errno - * - * in global errno - * - * EINVAL 'sem' is not a valid semaphore, - * ENOSYS this function is not supported, - * - * - * PARAMETERS - * - * sem pointer to an instance of sem_t - * - * sval pointer to int. - * - * DESCRIPTION - * This function stores the current count value of the semaphore - * pointed to by sem in the int pointed to by sval. - */ -{ - if (sem == NULL || *sem == NULL || sval == NULL) - { - errno = EINVAL; - return -1; - } - else - { - long value; - register sem_t s = *sem; - int result = 0; - - if ((result = pthread_mutex_lock(&s->lock)) == 0) - { - /* See sem_destroy.c - */ - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - errno = EINVAL; - return -1; - } - - value = s->value; - (void) pthread_mutex_unlock(&s->lock); - *sval = value; - } - - return result; - } - -} /* sem_getvalue */ diff --git a/pthreads/src/sem_init.c b/pthreads/src/sem_init.c deleted file mode 100644 index f682f4b..0000000 --- a/pthreads/src/sem_init.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_init.c - * - * Purpose: - * Semaphores aren't actually part of PThreads. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1-2001 - * - * ------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - -int -sem_init (sem_t * sem, int pshared, unsigned int value) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function initializes a semaphore. The - * initial value of the semaphore is 'value' - * - * PARAMETERS - * sem - * pointer to an instance of sem_t - * - * pshared - * if zero, this semaphore may only be shared between - * threads in the same process. - * if nonzero, the semaphore can be shared between - * processes - * - * value - * initial value of the semaphore counter - * - * DESCRIPTION - * This function initializes a semaphore. The - * initial value of the semaphore is set to 'value'. - * - * RESULTS - * 0 successfully created semaphore, - * -1 failed, error in errno - * ERRNO - * EINVAL 'sem' is not a valid semaphore, or - * 'value' >= SEM_VALUE_MAX - * ENOMEM out of memory, - * ENOSPC a required resource has been exhausted, - * ENOSYS semaphores are not supported, - * EPERM the process lacks appropriate privilege - * - * ------------------------------------------------------ - */ -{ - int result = 0; - sem_t s = NULL; - - if (pshared != 0) - { - /* - * Creating a semaphore that can be shared between - * processes - */ - result = EPERM; - } - else if (value > (unsigned int)SEM_VALUE_MAX) - { - result = EINVAL; - } - else - { - s = (sem_t) calloc (1, sizeof (*s)); - - if (NULL == s) - { - result = ENOMEM; - } - else - { - - s->value = value; - if (pthread_mutex_init(&s->lock, NULL) == 0) - { - -#if defined(NEED_SEM) - - s->sem = CreateEvent (NULL, - PTW32_FALSE, /* auto (not manual) reset */ - PTW32_FALSE, /* initial state is unset */ - NULL); - - if (0 == s->sem) - { - free (s); - (void) pthread_mutex_destroy(&s->lock); - result = ENOSPC; - } - else - { - s->leftToUnblock = 0; - } - -#else /* NEED_SEM */ - - if ((s->sem = CreateSemaphore (NULL, /* Always NULL */ - (long) 0, /* Force threads to wait */ - (long) SEM_VALUE_MAX, /* Maximum value */ - NULL)) == 0) /* Name */ - { - (void) pthread_mutex_destroy(&s->lock); - result = ENOSPC; - } - -#endif /* NEED_SEM */ - - } - else - { - result = ENOSPC; - } - - if (result != 0) - { - free(s); - } - } - } - - if (result != 0) - { - errno = result; - return -1; - } - - *sem = s; - - return 0; - -} /* sem_init */ diff --git a/pthreads/src/sem_open.c b/pthreads/src/sem_open.c deleted file mode 100644 index fb1cc54..0000000 --- a/pthreads/src/sem_open.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_open.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - -/* ignore warning "unreferenced formal parameter" */ -#if defined(_MSC_VER) -#pragma warning( disable : 4100 ) -#endif - -int -sem_open (const char *name, int oflag, mode_t mode, unsigned int value) -{ - errno = ENOSYS; - return -1; -} /* sem_open */ diff --git a/pthreads/src/sem_post.c b/pthreads/src/sem_post.c deleted file mode 100644 index 3483252..0000000 --- a/pthreads/src/sem_post.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_post.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - - -int -sem_post (sem_t * sem) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function posts a wakeup to a semaphore. - * - * PARAMETERS - * sem - * pointer to an instance of sem_t - * - * DESCRIPTION - * This function posts a wakeup to a semaphore. If there - * are waiting threads (or processes), one is awakened; - * otherwise, the semaphore value is incremented by one. - * - * RESULTS - * 0 successfully posted semaphore, - * -1 failed, error in errno - * ERRNO - * EINVAL 'sem' is not a valid semaphore, - * ENOSYS semaphores are not supported, - * ERANGE semaphore count is too big - * - * ------------------------------------------------------ - */ -{ - int result = 0; - sem_t s = *sem; - - if (s == NULL) - { - result = EINVAL; - } - else if ((result = pthread_mutex_lock (&s->lock)) == 0) - { - /* See sem_destroy.c - */ - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - result = EINVAL; - return -1; - } - - if (s->value < SEM_VALUE_MAX) - { -#if defined(NEED_SEM) - if (++s->value <= 0 - && !SetEvent(s->sem)) - { - s->value--; - result = EINVAL; - } -#else - if (++s->value <= 0 - && !ReleaseSemaphore (s->sem, 1, NULL)) - { - s->value--; - result = EINVAL; - } -#endif /* NEED_SEM */ - } - else - { - result = ERANGE; - } - - (void) pthread_mutex_unlock (&s->lock); - } - - if (result != 0) - { - errno = result; - return -1; - } - - return 0; - -} /* sem_post */ diff --git a/pthreads/src/sem_post_multiple.c b/pthreads/src/sem_post_multiple.c deleted file mode 100644 index 44c168c..0000000 --- a/pthreads/src/sem_post_multiple.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_post_multiple.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - - -int -sem_post_multiple (sem_t * sem, int count) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function posts multiple wakeups to a semaphore. - * - * PARAMETERS - * sem - * pointer to an instance of sem_t - * - * count - * counter, must be greater than zero. - * - * DESCRIPTION - * This function posts multiple wakeups to a semaphore. If there - * are waiting threads (or processes), n <= count are awakened; - * the semaphore value is incremented by count - n. - * - * RESULTS - * 0 successfully posted semaphore, - * -1 failed, error in errno - * ERRNO - * EINVAL 'sem' is not a valid semaphore - * or count is less than or equal to zero. - * ERANGE semaphore count is too big - * - * ------------------------------------------------------ - */ -{ - int result = 0; - long waiters; - sem_t s = *sem; - - if (s == NULL || count <= 0) - { - result = EINVAL; - } - else if ((result = pthread_mutex_lock (&s->lock)) == 0) - { - /* See sem_destroy.c - */ - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - result = EINVAL; - return -1; - } - - if (s->value <= (SEM_VALUE_MAX - count)) - { - waiters = -s->value; - s->value += count; - if (waiters > 0) - { -#if defined(NEED_SEM) - if (SetEvent(s->sem)) - { - waiters--; - s->leftToUnblock += count - 1; - if (s->leftToUnblock > waiters) - { - s->leftToUnblock = waiters; - } - } -#else - if (ReleaseSemaphore (s->sem, (waiters<=count)?waiters:count, 0)) - { - /* No action */ - } -#endif - else - { - s->value -= count; - result = EINVAL; - } - } - } - else - { - result = ERANGE; - } - (void) pthread_mutex_unlock (&s->lock); - } - - if (result != 0) - { - errno = result; - return -1; - } - - return 0; - -} /* sem_post_multiple */ diff --git a/pthreads/src/sem_timedwait.c b/pthreads/src/sem_timedwait.c deleted file mode 100644 index 638431c..0000000 --- a/pthreads/src/sem_timedwait.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_timedwait.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - - -typedef struct { - sem_t sem; - int * resultPtr; -} sem_timedwait_cleanup_args_t; - - -static void PTW32_CDECL -ptw32_sem_timedwait_cleanup (void * args) -{ - sem_timedwait_cleanup_args_t * a = (sem_timedwait_cleanup_args_t *)args; - sem_t s = a->sem; - - if (pthread_mutex_lock (&s->lock) == 0) - { - /* - * We either timed out or were cancelled. - * If someone has posted between then and now we try to take the semaphore. - * Otherwise the semaphore count may be wrong after we - * return. In the case of a cancellation, it is as if we - * were cancelled just before we return (after taking the semaphore) - * which is ok. - */ - if (WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0) - { - /* We got the semaphore on the second attempt */ - *(a->resultPtr) = 0; - } - else - { - /* Indicate we're no longer waiting */ - s->value++; -#if defined(NEED_SEM) - if (s->value > 0) - { - s->leftToUnblock = 0; - } -#else - /* - * Don't release the W32 sema, it doesn't need adjustment - * because it doesn't record the number of waiters. - */ -#endif - } - (void) pthread_mutex_unlock (&s->lock); - } -} - - -int -sem_timedwait (sem_t * sem, const struct timespec *abstime) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function waits on a semaphore possibly until - * 'abstime' time. - * - * PARAMETERS - * sem - * pointer to an instance of sem_t - * - * abstime - * pointer to an instance of struct timespec - * - * DESCRIPTION - * This function waits on a semaphore. If the - * semaphore value is greater than zero, it decreases - * its value by one. If the semaphore value is zero, then - * the calling thread (or process) is blocked until it can - * successfully decrease the value or until interrupted by - * a signal. - * - * If 'abstime' is a NULL pointer then this function will - * block until it can successfully decrease the value or - * until interrupted by a signal. - * - * RESULTS - * 0 successfully decreased semaphore, - * -1 failed, error in errno - * ERRNO - * EINVAL 'sem' is not a valid semaphore, - * ENOSYS semaphores are not supported, - * EINTR the function was interrupted by a signal, - * EDEADLK a deadlock condition was detected. - * ETIMEDOUT abstime elapsed before success. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - sem_t s = *sem; - - pthread_testcancel(); - - if (sem == NULL) - { - result = EINVAL; - } - else - { - DWORD milliseconds; - - if (abstime == NULL) - { - milliseconds = INFINITE; - } - else - { - /* - * Calculate timeout as milliseconds from current system time. - */ - milliseconds = ptw32_relmillisecs (abstime); - } - - if ((result = pthread_mutex_lock (&s->lock)) == 0) - { - int v; - - /* See sem_destroy.c - */ - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - errno = EINVAL; - return -1; - } - - v = --s->value; - (void) pthread_mutex_unlock (&s->lock); - - if (v < 0) - { -#if defined(NEED_SEM) - int timedout; -#endif - sem_timedwait_cleanup_args_t cleanup_args; - - cleanup_args.sem = s; - cleanup_args.resultPtr = &result; - -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth(0) -#endif - /* Must wait */ - pthread_cleanup_push(ptw32_sem_timedwait_cleanup, (void *) &cleanup_args); -#if defined(NEED_SEM) - timedout = -#endif - result = pthreadCancelableTimedWait (s->sem, milliseconds); - pthread_cleanup_pop(result); -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth() -#endif - -#if defined(NEED_SEM) - - if (!timedout && pthread_mutex_lock (&s->lock) == 0) - { - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - errno = EINVAL; - return -1; - } - - if (s->leftToUnblock > 0) - { - --s->leftToUnblock; - SetEvent(s->sem); - } - (void) pthread_mutex_unlock (&s->lock); - } - -#endif /* NEED_SEM */ - - } - } - - } - - if (result != 0) - { - - errno = result; - return -1; - - } - - return 0; - -} /* sem_timedwait */ diff --git a/pthreads/src/sem_trywait.c b/pthreads/src/sem_trywait.c deleted file mode 100644 index 63614ba..0000000 --- a/pthreads/src/sem_trywait.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_trywait.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - - -int -sem_trywait (sem_t * sem) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function tries to wait on a semaphore. - * - * PARAMETERS - * sem - * pointer to an instance of sem_t - * - * DESCRIPTION - * This function tries to wait on a semaphore. If the - * semaphore value is greater than zero, it decreases - * its value by one. If the semaphore value is zero, then - * this function returns immediately with the error EAGAIN - * - * RESULTS - * 0 successfully decreased semaphore, - * -1 failed, error in errno - * ERRNO - * EAGAIN the semaphore was already locked, - * EINVAL 'sem' is not a valid semaphore, - * ENOTSUP sem_trywait is not supported, - * EINTR the function was interrupted by a signal, - * EDEADLK a deadlock condition was detected. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - sem_t s = *sem; - - if (s == NULL) - { - result = EINVAL; - } - else if ((result = pthread_mutex_lock (&s->lock)) == 0) - { - /* See sem_destroy.c - */ - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - errno = EINVAL; - return -1; - } - - if (s->value > 0) - { - s->value--; - } - else - { - result = EAGAIN; - } - - (void) pthread_mutex_unlock (&s->lock); - } - - if (result != 0) - { - errno = result; - return -1; - } - - return 0; - -} /* sem_trywait */ diff --git a/pthreads/src/sem_unlink.c b/pthreads/src/sem_unlink.c deleted file mode 100644 index fb80569..0000000 --- a/pthreads/src/sem_unlink.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_unlink.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - -/* ignore warning "unreferenced formal parameter" */ -#if defined(_MSC_VER) -#pragma warning( disable : 4100 ) -#endif - -int -sem_unlink (const char *name) -{ - errno = ENOSYS; - return -1; -} /* sem_unlink */ diff --git a/pthreads/src/sem_wait.c b/pthreads/src/sem_wait.c deleted file mode 100644 index 50c11d8..0000000 --- a/pthreads/src/sem_wait.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: sem_wait.c - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - - -static void PTW32_CDECL -ptw32_sem_wait_cleanup(void * sem) -{ - sem_t s = (sem_t) sem; - - if (pthread_mutex_lock (&s->lock) == 0) - { - /* - * If sema is destroyed do nothing, otherwise:- - * If the sema is posted between us being cancelled and us locking - * the sema again above then we need to consume that post but cancel - * anyway. If we don't get the semaphore we indicate that we're no - * longer waiting. - */ - if (*((sem_t *)sem) != NULL && !(WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0)) - { - ++s->value; -#if defined(NEED_SEM) - if (s->value > 0) - { - s->leftToUnblock = 0; - } -#else - /* - * Don't release the W32 sema, it doesn't need adjustment - * because it doesn't record the number of waiters. - */ -#endif /* NEED_SEM */ - } - (void) pthread_mutex_unlock (&s->lock); - } -} - -int -sem_wait (sem_t * sem) - /* - * ------------------------------------------------------ - * DOCPUBLIC - * This function waits on a semaphore. - * - * PARAMETERS - * sem - * pointer to an instance of sem_t - * - * DESCRIPTION - * This function waits on a semaphore. If the - * semaphore value is greater than zero, it decreases - * its value by one. If the semaphore value is zero, then - * the calling thread (or process) is blocked until it can - * successfully decrease the value or until interrupted by - * a signal. - * - * RESULTS - * 0 successfully decreased semaphore, - * -1 failed, error in errno - * ERRNO - * EINVAL 'sem' is not a valid semaphore, - * ENOSYS semaphores are not supported, - * EINTR the function was interrupted by a signal, - * EDEADLK a deadlock condition was detected. - * - * ------------------------------------------------------ - */ -{ - int result = 0; - sem_t s = *sem; - - pthread_testcancel(); - - if (s == NULL) - { - result = EINVAL; - } - else - { - if ((result = pthread_mutex_lock (&s->lock)) == 0) - { - int v; - - /* See sem_destroy.c - */ - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - errno = EINVAL; - return -1; - } - - v = --s->value; - (void) pthread_mutex_unlock (&s->lock); - - if (v < 0) - { -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth(0) -#endif - /* Must wait */ - pthread_cleanup_push(ptw32_sem_wait_cleanup, (void *) s); - result = pthreadCancelableWait (s->sem); - /* Cleanup if we're canceled or on any other error */ - pthread_cleanup_pop(result); -#if defined(_MSC_VER) && _MSC_VER < 1400 -#pragma inline_depth() -#endif - } -#if defined(NEED_SEM) - - if (!result && pthread_mutex_lock (&s->lock) == 0) - { - if (*sem == NULL) - { - (void) pthread_mutex_unlock (&s->lock); - errno = EINVAL; - return -1; - } - - if (s->leftToUnblock > 0) - { - --s->leftToUnblock; - SetEvent(s->sem); - } - (void) pthread_mutex_unlock (&s->lock); - } - -#endif /* NEED_SEM */ - - } - - } - - if (result != 0) - { - errno = result; - return -1; - } - - return 0; - -} /* sem_wait */ diff --git a/pthreads/src/semaphore.c b/pthreads/src/semaphore.c deleted file mode 100644 index 64fc0e3..0000000 --- a/pthreads/src/semaphore.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * ------------------------------------------------------------- - * - * Module: semaphore.c - * - * Purpose: - * Concatenated version of separate modules to allow - * inlining optimisation, which it is assumed can only - * be effective within a single module. - * - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * ------------------------------------------------------------- - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined(NEED_FTIME) -# include -#endif - -#include - -#include "pthread.h" -#include "semaphore.h" -#include "implement.h" - - -#include "sem_init.c" -#include "sem_destroy.c" -#include "sem_trywait.c" -#include "sem_wait.c" -#include "sem_timedwait.c" -#include "sem_post.c" -#include "sem_post_multiple.c" -#include "sem_getvalue.c" -#include "sem_open.c" -#include "sem_close.c" -#include "sem_unlink.c" diff --git a/pthreads/src/semaphore.h b/pthreads/src/semaphore.h deleted file mode 100644 index c6e9407..0000000 --- a/pthreads/src/semaphore.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Module: semaphore.h - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#if !defined( SEMAPHORE_H ) -#define SEMAPHORE_H - -#undef PTW32_SEMAPHORE_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_SEMAPHORE_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_SEMAPHORE_LEVEL -#define PTW32_SEMAPHORE_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_SEMAPHORE_LEVEL -#define PTW32_SEMAPHORE_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_SEMAPHORE_LEVEL_MAX 3 - -#if !defined(PTW32_SEMAPHORE_LEVEL) -#define PTW32_SEMAPHORE_LEVEL PTW32_SEMAPHORE_LEVEL_MAX -/* Include everything */ -#endif - -#if defined(__GNUC__) && ! defined (__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */ - -#define _POSIX_SEMAPHORES - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -#if !defined(HAVE_MODE_T) -typedef unsigned int mode_t; -#endif - - -typedef struct sem_t_ * sem_t; - -PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, - int pshared, - unsigned int value); - -PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, - const struct timespec * abstime); - -PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, - int count); - -PTW32_DLLPORT int __cdecl sem_open (const char * name, - int oflag, - mode_t mode, - unsigned int value); - -PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_unlink (const char * name); - -PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, - int * sval); - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#undef PTW32_SEMAPHORE_LEVEL -#undef PTW32_SEMAPHORE_LEVEL_MAX - -#endif /* !SEMAPHORE_H */ diff --git a/pthreads/src/signal.c b/pthreads/src/signal.c deleted file mode 100644 index eef4669..0000000 --- a/pthreads/src/signal.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * signal.c - * - * Description: - * Thread-aware signal functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -/* - * Possible future strategy for implementing pthread_kill() - * ======================================================== - * - * Win32 does not implement signals. - * Signals are simply software interrupts. - * pthread_kill() asks the system to deliver a specified - * signal (interrupt) to a specified thread in the same - * process. - * Signals are always asynchronous (no deferred signals). - * Pthread-win32 has an async cancelation mechanism. - * A similar system can be written to deliver signals - * within the same process (on ix86 processors at least). - * - * Each thread maintains information about which - * signals it will respond to. Handler routines - * are set on a per-process basis - not per-thread. - * When signalled, a thread will check it's sigmask - * and, if the signal is not being ignored, call the - * handler routine associated with the signal. The - * thread must then (except for some signals) return to - * the point where it was interrupted. - * - * Ideally the system itself would check the target thread's - * mask before possibly needlessly bothering the thread - * itself. This could be done by pthread_kill(), that is, - * in the signaling thread since it has access to - * all pthread_t structures. It could also retrieve - * the handler routine address to minimise the target - * threads response overhead. This may also simplify - * serialisation of the access to the per-thread signal - * structures. - * - * pthread_kill() eventually calls a routine similar to - * ptw32_cancel_thread() which manipulates the target - * threads processor context to cause the thread to - * run the handler launcher routine. pthread_kill() must - * save the target threads current context so that the - * handler launcher routine can restore the context after - * the signal handler has returned. Some handlers will not - * return, eg. the default SIGKILL handler may simply - * call pthread_exit(). - * - * The current context is saved in the target threads - * pthread_t structure. - */ - -#include "pthread.h" -#include "implement.h" - -#if defined(HAVE_SIGSET_T) - -static void -ptw32_signal_thread () -{ -} - -static void -ptw32_signal_callhandler () -{ -} - -int -pthread_sigmask (int how, sigset_t const *set, sigset_t * oset) -{ - pthread_t thread = pthread_self (); - - if (thread.p == NULL) - { - return ENOENT; - } - - /* Validate the `how' argument. */ - if (set != NULL) - { - switch (how) - { - case SIG_BLOCK: - break; - case SIG_UNBLOCK: - break; - case SIG_SETMASK: - break; - default: - /* Invalid `how' argument. */ - return EINVAL; - } - } - - /* Copy the old mask before modifying it. */ - if (oset != NULL) - { - memcpy (oset, &(thread.p->sigmask), sizeof (sigset_t)); - } - - if (set != NULL) - { - unsigned int i; - - /* FIXME: this code assumes that sigmask is an even multiple of - the size of a long integer. */ - - unsigned long *src = (unsigned long const *) set; - unsigned long *dest = (unsigned long *) &(thread.p->sigmask); - - switch (how) - { - case SIG_BLOCK: - for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++) - { - /* OR the bit field longword-wise. */ - *dest++ |= *src++; - } - break; - case SIG_UNBLOCK: - for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++) - { - /* XOR the bitfield longword-wise. */ - *dest++ ^= *src++; - } - case SIG_SETMASK: - /* Replace the whole sigmask. */ - memcpy (&(thread.p->sigmask), set, sizeof (sigset_t)); - break; - } - } - - return 0; -} - -int -sigwait (const sigset_t * set, int *sig) -{ - /* This routine is a cancellation point */ - pthread_test_cancel(); -} - -int -sigaction (int signum, const struct sigaction *act, struct sigaction *oldact) -{ -} - -#endif /* HAVE_SIGSET_T */ diff --git a/pthreads/src/spin.c b/pthreads/src/spin.c deleted file mode 100644 index 41b5aa5..0000000 --- a/pthreads/src/spin.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * spin.c - * - * Description: - * This translation unit implements spin lock primitives. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -#include "ptw32_spinlock_check_need_init.c" -#include "pthread_spin_init.c" -#include "pthread_spin_destroy.c" -#include "pthread_spin_lock.c" -#include "pthread_spin_unlock.c" -#include "pthread_spin_trylock.c" diff --git a/pthreads/src/sync.c b/pthreads/src/sync.c deleted file mode 100644 index 5e56fa9..0000000 --- a/pthreads/src/sync.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * sync.c - * - * Description: - * This translation unit implements functions related to thread - * synchronisation. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -#include "pthread_detach.c" -#include "pthread_join.c" diff --git a/pthreads/src/tsd.c b/pthreads/src/tsd.c deleted file mode 100644 index ed44fe6..0000000 --- a/pthreads/src/tsd.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * tsd.c - * - * Description: - * POSIX thread functions which implement thread-specific data (TSD). - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -#include "pthread_key_create.c" -#include "pthread_key_delete.c" -#include "pthread_setspecific.c" -#include "pthread_getspecific.c" diff --git a/pthreads/src/w32_CancelableWait.c b/pthreads/src/w32_CancelableWait.c deleted file mode 100644 index 070633e..0000000 --- a/pthreads/src/w32_CancelableWait.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * w32_CancelableWait.c - * - * Description: - * This translation unit implements miscellaneous thread functions. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "pthread.h" -#include "implement.h" - - -static INLINE int -ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout) - /* - * ------------------------------------------------------------------- - * This provides an extra hook into the pthread_cancel - * mechanism that will allow you to wait on a Windows handle and make it a - * cancellation point. This function blocks until the given WIN32 handle is - * signaled or pthread_cancel has been called. It is implemented using - * WaitForMultipleObjects on 'waitHandle' and a manually reset WIN32 - * event used to implement pthread_cancel. - * - * Given this hook it would be possible to implement more of the cancellation - * points. - * ------------------------------------------------------------------- - */ -{ - int result; - pthread_t self; - ptw32_thread_t * sp; - HANDLE handles[2]; - DWORD nHandles = 1; - DWORD status; - - handles[0] = waitHandle; - - self = pthread_self(); - sp = (ptw32_thread_t *) self.p; - - if (sp != NULL) - { - /* - * Get cancelEvent handle - */ - if (sp->cancelState == PTHREAD_CANCEL_ENABLE) - { - - if ((handles[1] = sp->cancelEvent) != NULL) - { - nHandles++; - } - } - } - else - { - handles[1] = NULL; - } - - status = WaitForMultipleObjects (nHandles, handles, PTW32_FALSE, timeout); - - switch (status - WAIT_OBJECT_0) - { - case 0: - /* - * Got the handle. - * In the event that both handles are signalled, the smallest index - * value (us) is returned. As it has been arranged, this ensures that - * we don't drop a signal that we should act on (i.e. semaphore, - * mutex, or condition variable etc). - */ - result = 0; - break; - - case 1: - /* - * Got cancel request. - * In the event that both handles are signaled, the cancel will - * be ignored (see case 0 comment). - */ - ResetEvent (handles[1]); - - if (sp != NULL) - { - ptw32_mcs_local_node_t stateLock; - /* - * Should handle POSIX and implicit POSIX threads.. - * Make sure we haven't been async-canceled in the meantime. - */ - ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); - if (sp->state < PThreadStateCanceling) - { - sp->state = PThreadStateCanceling; - sp->cancelState = PTHREAD_CANCEL_DISABLE; - ptw32_mcs_lock_release (&stateLock); - ptw32_throw (PTW32_EPS_CANCEL); - - /* Never reached */ - } - ptw32_mcs_lock_release (&stateLock); - } - - /* Should never get to here. */ - result = EINVAL; - break; - - default: - if (status == WAIT_TIMEOUT) - { - result = ETIMEDOUT; - } - else - { - result = EINVAL; - } - break; - } - - return (result); - -} /* CancelableWait */ - -int -pthreadCancelableWait (HANDLE waitHandle) -{ - return (ptw32_cancelable_wait (waitHandle, INFINITE)); -} - -int -pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout) -{ - return (ptw32_cancelable_wait (waitHandle, timeout)); -} diff --git a/vtparse/src/Makefile b/vtparse/src/Makefile new file mode 100644 index 0000000..044a487 --- /dev/null +++ b/vtparse/src/Makefile @@ -0,0 +1,19 @@ + +RUBY_GENERATION_FILES = vtparse_gen_c_tables.rb vtparse_tables.rb + +all: vtparse_table.c vtparse_table.h test + +clean: + rm -f vtparse_table.c vtparse_table.h test + +vtparse_table.c: $(RUBY_GENERATION_FILES) + ruby vtparse_gen_c_tables.rb + +vtparse_table.h: $(RUBY_GENERATION_FILES) + ruby vtparse_gen_c_tables.rb + +test: vtparse.c vtparse.h vtparse_table.c vtparse_table.h vtparse_test.c + gcc -o test vtparse_test.c vtparse.c vtparse_table.c + +.PHONY: all clean + diff --git a/vtparse/src/README b/vtparse/src/README new file mode 100644 index 0000000..9b24113 --- /dev/null +++ b/vtparse/src/README @@ -0,0 +1,67 @@ + +VTParse - an implementation of Paul Williams' DEC compatible state machine parser + + +Author: Joshua Haberman + +This code is in the public domain. + +BUILDING +======== + +Ruby is required at build time to generate the tables in C. To build the library +and test program, just type make: + +$ make +ruby vtparse_gen_c_tables.rb +Wrote vtparse_table.h +Wrote vtparse_table.c +gcc -o test vtparse_test.c vtparse.c vtparse_table.c + +TEST PROGRAM +============ + +The test program shows how to use vtparse. To see what kind of data is returned +by the library, try: + +-------------------------------- + +$ vim > terminaloutput +' to exit vim, even though you won't see it> +$ ./test < terminaloutput | head -14 +Received action ESC_DISPATCH, char=0x37 +Intermediate chars: '' +0 Parameters: + +Received action CSI_DISPATCH, char=0x68 +Intermediate chars: '???' +1 Parameters: + 47 + +Received action CSI_DISPATCH, char=0x68 +Intermediate chars: '???' +1 Parameters: + 1 + +--------------------------------- + +VERIFYING +========= + +You can also verify the validity of the state tables by running: + +$ ruby vtparse_check_tables.rb +Tables had all necessary transitions defined. + +This checks to make sure that state transitions are defined for all states, for all +characters 0-0xA0. + + +TODO +==== + +One possible enhancement is to allow the client to pass a return value from the +callback to say "stop parsing." The vtparse() function could return the number +of bytes consumed from the input buffer. This would be quite simple to do if +someone needed this functionality, but I don't, so I didn't bother. + diff --git a/vtparse/src/vtparse.c b/vtparse/src/vtparse.c new file mode 100644 index 0000000..b24a4a4 --- /dev/null +++ b/vtparse/src/vtparse.c @@ -0,0 +1,152 @@ +/* + * VTParse - an implementation of Paul Williams' DEC compatible state machine parser + * + * Author: Joshua Haberman + * + * This code is in the public domain. + */ + +#include +#include +#include + +#include "vtparse.h" + +void vtparse_init(vtparse_t *parser, vtparse_callback_t cb) +{ + parser->state = VTPARSE_STATE_GROUND; + parser->intermediate_chars[0] = '\0'; + parser->num_params = 0; + parser->ignore_flagged = 0; + parser->cb = cb; +} + +static void do_action(vtparse_t *parser, vtparse_action_t action, char ch) +{ + /* Some actions we handle internally (like parsing parameters), others + * we hand to our client for processing */ + + switch(action) { + case VTPARSE_ACTION_PRINT: + case VTPARSE_ACTION_EXECUTE: + case VTPARSE_ACTION_HOOK: + case VTPARSE_ACTION_PUT: + case VTPARSE_ACTION_OSC_START: + case VTPARSE_ACTION_OSC_PUT: + case VTPARSE_ACTION_OSC_END: + case VTPARSE_ACTION_UNHOOK: + case VTPARSE_ACTION_CSI_DISPATCH: + case VTPARSE_ACTION_ESC_DISPATCH: + parser->cb(parser, action, ch); + break; + + case VTPARSE_ACTION_IGNORE: + /* do nothing */ + break; + + case VTPARSE_ACTION_COLLECT: + { + /* Append the character to the intermediate params */ + int num_intermediate_chars = strlen((char*)parser->intermediate_chars); + + if(num_intermediate_chars + 1 > MAX_INTERMEDIATE_CHARS) + parser->ignore_flagged = 1; + else + parser->intermediate_chars[num_intermediate_chars++] = ch; + + break; + } + + case VTPARSE_ACTION_PARAM: + { + /* process the param character */ + if(ch == ';') + { + parser->num_params += 1; + parser->params[parser->num_params-1] = 0; + } + else + { + /* the character is a digit */ + int current_param; + + if(parser->num_params == 0) + { + parser->num_params = 1; + parser->params[0] = 0; + } + + current_param = parser->num_params - 1; + parser->params[current_param] *= 10; + parser->params[current_param] += (ch - '0'); + } + + break; + } + + case VTPARSE_ACTION_CLEAR: + parser->intermediate_chars[0] = '\0'; + parser->num_params = 0; + parser->ignore_flagged = 0; + break; + + default: + fprintf(stderr, "Internal error, unknown action %d", action); + } +} + +static void do_state_change(vtparse_t *parser, state_change_t change, char ch) +{ + /* A state change is an action and/or a new state to transition to. */ + + vtparse_state_t new_state = STATE(change); + vtparse_action_t action = ACTION(change); + + + if(new_state) + { + /* Perform up to three actions: + * 1. the exit action of the old state + * 2. the action associated with the transition + * 3. the entry actionk of the new action + */ + + vtparse_action_t exit_action = EXIT_ACTIONS[parser->state]; + vtparse_action_t entry_action = ENTRY_ACTIONS[new_state]; + + if(exit_action) + do_action(parser, exit_action, 0); + + if(action) + do_action(parser, action, ch); + + if(entry_action) + do_action(parser, entry_action, 0); + + parser->state = new_state; + } + else + { + do_action(parser, action, ch); + } +} + +void vtparse(vtparse_t *parser, unsigned char *data, int len) +{ + int i; + for(i = 0; i < len; i++) + { + unsigned char ch = data[i]; + + /* If a transition is defined from the "anywhere" state, always + * use that. Otherwise use the transition from the current state. */ + + state_change_t change = STATE_TABLE[VTPARSE_STATE_ANYWHERE][ch]; + + if(!change) + change = STATE_TABLE[parser->state][ch]; + + do_state_change(parser, change, data[i]); + } +} + diff --git a/vtparse/src/vtparse.h b/vtparse/src/vtparse.h new file mode 100644 index 0000000..1d176ad --- /dev/null +++ b/vtparse/src/vtparse.h @@ -0,0 +1,31 @@ +/* + * VTParse - an implementation of Paul Williams' DEC compatible state machine parser + * + * Author: Joshua Haberman + * + * This code is in the public domain. + */ + +#include "vtparse_table.h" + +#define MAX_INTERMEDIATE_CHARS 2 +#define ACTION(state_change) (state_change & 0x0F) +#define STATE(state_change) (state_change >> 4) + +struct vtparse; + +typedef void (*vtparse_callback_t)(struct vtparse*, vtparse_action_t, unsigned char); + +typedef struct vtparse { + vtparse_state_t state; + vtparse_callback_t cb; + unsigned char intermediate_chars[MAX_INTERMEDIATE_CHARS+1]; + char ignore_flagged; + int params[16]; + int num_params; + void* user_data; +} vtparse_t; + +void vtparse_init(vtparse_t *parser, vtparse_callback_t cb); +void vtparse(vtparse_t *parser, unsigned char *data, int len); + diff --git a/vtparse/src/vtparse_check_tables.rb b/vtparse/src/vtparse_check_tables.rb new file mode 100644 index 0000000..2bfa122 --- /dev/null +++ b/vtparse/src/vtparse_check_tables.rb @@ -0,0 +1,24 @@ + +require 'vtparse_tables' + +# +# check that for every state, there is a transition defined +# for every character between 0 and A0. +# + +table = {} + +anywhere_array = expand_ranges($states[:ANYWHERE]) + +$state_tables.each { |state, table| + next if state == :ANYWHERE + + table.each_with_index { |val, i| + if not (val or $state_tables[:ANYWHERE][i]) + raise "No transition defined from state #{state}, char 0x#{i.to_s(16)}!" + end + } +} + +puts "Tables had all necessary transitions defined." + diff --git a/vtparse/src/vtparse_gen_c_tables.rb b/vtparse/src/vtparse_gen_c_tables.rb new file mode 100644 index 0000000..ed5655e --- /dev/null +++ b/vtparse/src/vtparse_gen_c_tables.rb @@ -0,0 +1,95 @@ + +require 'vtparse_tables' + +class String + def pad(len) + self << (" " * (len - self.length)) + end +end + +File.open("vtparse_table.h", "w") { |f| + f.puts "typedef enum {" + $states_in_order.each_with_index { |state, i| + f.puts " VTPARSE_STATE_#{state.to_s.upcase} = #{i}," + } + f.puts "} vtparse_state_t;" + f.puts + f.puts "typedef enum {" + $actions_in_order.each_with_index { |action, i| + f.puts " VTPARSE_ACTION_#{action.to_s.upcase} = #{i+1}," + } + f.puts "} vtparse_action_t;" + f.puts + f.puts "typedef unsigned char state_change_t;" + f.puts "extern state_change_t STATE_TABLE[#{$states_in_order.length}][256];" + f.puts "extern vtparse_action_t ENTRY_ACTIONS[#{$states_in_order.length}];" + f.puts "extern vtparse_action_t EXIT_ACTIONS[#{$states_in_order.length}];" + f.puts "extern char *ACTION_NAMES[#{$actions_in_order.length+1}];" + f.puts "extern char *STATE_NAMES[#{$states_in_order.length}];" + f.puts +} + +puts "Wrote vtparse_table.h" + +File.open("vtparse_table.c", "w") { |f| + f.puts + f.puts '#include "vtparse_table.h"' + f.puts + f.puts "char *ACTION_NAMES[] = {" + f.puts " \"\"," + $actions_in_order.each { |action| + f.puts " \"#{action.to_s.upcase}\"," + } + f.puts "};" + f.puts + f.puts "char *STATE_NAMES[] = {" + $states_in_order.each { |state| + f.puts " \"#{state.to_s}\"," + } + f.puts "};" + f.puts + f.puts "state_change_t STATE_TABLE[#{$states_in_order.length}][256] = {" + $states_in_order.each { |state| + f.puts " { /* VTPARSE_STATE_#{state.to_s.upcase} */" + $state_tables[state].each_with_index { |state_change, i| + if not state_change + f.puts " 0," + else + (action,) = state_change.find_all { |s| s.kind_of?(Symbol) } + (state,) = state_change.find_all { |s| s.kind_of?(StateTransition) } + action_str = action ? "VTPARSE_ACTION_#{action.to_s.upcase}" : "0" + state_str = state ? "VTPARSE_STATE_#{state.to_state.to_s}" : "0" + f.puts "/*#{i.to_s.pad(3)}*/ #{action_str.pad(33)} | (#{state_str.pad(33)} << 4)," + end + } + f.puts " }," + } + + f.puts "};" + f.puts + f.puts "vtparse_action_t ENTRY_ACTIONS[] = {" + $states_in_order.each { |state| + actions = $states[state] + if actions[:on_entry] + f.puts " VTPARSE_ACTION_#{actions[:on_entry].to_s.upcase}, /* #{state} */" + else + f.puts " 0 /* none for #{state} */," + end + } + f.puts "};" + f.puts + f.puts "vtparse_action_t EXIT_ACTIONS[] = {" + $states_in_order.each { |state| + actions = $states[state] + if actions[:on_exit] + f.puts " VTPARSE_ACTION_#{actions[:on_exit].to_s.upcase}, /* #{state} */" + else + f.puts " 0 /* none for #{state} */," + end + } + f.puts "};" + f.puts +} + +puts "Wrote vtparse_table.c" + diff --git a/vtparse/src/vtparse_table.c b/vtparse/src/vtparse_table.c new file mode 100644 index 0000000..f81e770 --- /dev/null +++ b/vtparse/src/vtparse_table.c @@ -0,0 +1,2657 @@ + +#include "vtparse_table.h" + +char *ACTION_NAMES[] = { + "", + "CLEAR", + "COLLECT", + "CSI_DISPATCH", + "ESC_DISPATCH", + "EXECUTE", + "HOOK", + "IGNORE", + "OSC_END", + "OSC_PUT", + "OSC_START", + "PARAM", + "PRINT", + "PUT", + "UNHOOK", +}; + +char *STATE_NAMES[] = { + "ANYWHERE", + "CSI_ENTRY", + "CSI_IGNORE", + "CSI_INTERMEDIATE", + "CSI_PARAM", + "DCS_ENTRY", + "DCS_IGNORE", + "DCS_INTERMEDIATE", + "DCS_PARAM", + "DCS_PASSTHROUGH", + "ESCAPE", + "ESCAPE_INTERMEDIATE", + "GROUND", + "OSC_STRING", + "SOS_PM_APC_STRING", + "UTF8", +}; + +state_change_t STATE_TABLE[16][256] = { + { /* VTPARSE_STATE_ANYWHERE */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +/*24 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), + 0, +/*26 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*27 */ 0 | (VTPARSE_STATE_ESCAPE << 4), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +/*128*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*129*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*130*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*131*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*132*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*133*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*134*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*135*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*136*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*137*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*138*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*139*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*140*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*141*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*142*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*143*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*144*/ 0 | (VTPARSE_STATE_DCS_ENTRY << 4), +/*145*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*146*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*147*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*148*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*149*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*150*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*151*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*152*/ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4), +/*153*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*154*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*155*/ 0 | (VTPARSE_STATE_CSI_ENTRY << 4), +/*156*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*157*/ 0 | (VTPARSE_STATE_OSC_STRING << 4), +/*158*/ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4), +/*159*/ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +/*192*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*193*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*194*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*195*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*196*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*197*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*198*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*199*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*200*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*201*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*202*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*203*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*204*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*205*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*206*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*207*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*208*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*209*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*210*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*211*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*212*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*213*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*214*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*215*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*216*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*217*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*218*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*219*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*220*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*221*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*222*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*223*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*224*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*225*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*226*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*227*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*228*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*229*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*230*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*231*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*232*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*233*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*234*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*235*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*236*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*237*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*238*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*239*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*240*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*241*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*242*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*243*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*244*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*245*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*246*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*247*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*248*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*249*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*250*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*251*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*252*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*253*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), + }, + { /* VTPARSE_STATE_CSI_ENTRY */ +/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*48 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*49 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*50 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*51 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*52 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*53 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*54 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*55 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*56 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*57 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*58 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*59 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4), +/*60 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_PARAM << 4), +/*61 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_PARAM << 4), +/*62 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_PARAM << 4), +/*63 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_PARAM << 4), +/*64 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*65 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*66 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*67 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*68 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*69 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*70 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*71 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*72 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*73 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*74 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*75 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*76 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*77 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*78 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*79 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*80 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*81 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*82 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*83 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*84 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*85 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*86 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*87 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*88 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*89 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*90 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*91 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*92 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*93 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*94 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*95 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*96 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*97 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*98 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*99 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*100*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*101*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*102*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*103*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*104*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*105*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*106*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*107*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*108*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*109*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*110*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*111*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*112*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*113*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*114*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*115*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*116*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*117*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*118*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*119*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*120*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*121*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*122*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*123*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*124*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*125*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*126*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_CSI_IGNORE */ +/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*32 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*33 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*34 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*35 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*36 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*37 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*38 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*39 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*40 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*41 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*42 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*43 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*44 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*45 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*46 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*47 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*48 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*49 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*50 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*51 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*52 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*53 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*54 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*55 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*56 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*57 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*58 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*59 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*60 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*61 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*62 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*63 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*64 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*65 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*66 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*67 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*68 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*69 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*70 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*71 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*72 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*73 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*74 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*75 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*76 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*77 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*78 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*79 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*80 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*81 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*82 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*83 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*84 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*85 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*86 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*87 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*88 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*89 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*90 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*91 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*92 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*93 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*94 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*95 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*96 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*97 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*98 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*99 */ 0 | (VTPARSE_STATE_GROUND << 4), +/*100*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*101*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*102*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*103*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*104*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*105*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*106*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*107*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*108*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*109*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*110*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*111*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*112*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*113*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*114*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*115*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*116*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*117*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*118*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*119*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*120*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*121*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*122*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*123*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*124*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*125*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*126*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_CSI_INTERMEDIATE */ +/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*32 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*33 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*34 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*35 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*36 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*37 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*38 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*39 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*40 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*41 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*42 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*43 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*44 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*45 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*46 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*47 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*48 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*49 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*50 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*51 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*52 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*53 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*54 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*55 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*56 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*57 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*58 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*59 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*60 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*61 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*62 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*63 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*64 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*65 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*66 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*67 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*68 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*69 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*70 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*71 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*72 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*73 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*74 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*75 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*76 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*77 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*78 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*79 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*80 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*81 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*82 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*83 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*84 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*85 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*86 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*87 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*88 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*89 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*90 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*91 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*92 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*93 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*94 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*95 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*96 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*97 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*98 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*99 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*100*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*101*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*102*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*103*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*104*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*105*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*106*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*107*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*108*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*109*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*110*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*111*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*112*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*113*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*114*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*115*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*116*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*117*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*118*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*119*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*120*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*121*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*122*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*123*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*124*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*125*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*126*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_CSI_PARAM */ +/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4), +/*48 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*49 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*50 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*51 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*52 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*53 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*54 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*55 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*56 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*57 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*58 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*59 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*60 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*61 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*62 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*63 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4), +/*64 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*65 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*66 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*67 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*68 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*69 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*70 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*71 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*72 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*73 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*74 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*75 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*76 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*77 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*78 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*79 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*80 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*81 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*82 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*83 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*84 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*85 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*86 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*87 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*88 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*89 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*90 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*91 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*92 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*93 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*94 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*95 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*96 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*97 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*98 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*99 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*100*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*101*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*102*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*103*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*104*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*105*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*106*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*107*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*108*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*109*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*110*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*111*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*112*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*113*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*114*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*115*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*116*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*117*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*118*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*119*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*120*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*121*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*122*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*123*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*124*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*125*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*126*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_DCS_ENTRY */ +/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*48 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*49 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*50 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*51 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*52 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*53 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*54 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*55 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*56 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*57 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*58 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*59 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4), +/*60 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_PARAM << 4), +/*61 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_PARAM << 4), +/*62 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_PARAM << 4), +/*63 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_PARAM << 4), +/*64 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*65 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*66 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*67 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*68 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*69 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*70 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*71 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*72 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*73 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*74 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*75 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*76 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*77 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*78 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*79 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*80 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*81 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*82 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*83 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*84 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*85 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*86 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*87 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*88 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*89 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*90 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*91 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*92 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*93 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*94 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*95 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*96 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*97 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*98 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*99 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*100*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*101*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*102*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*103*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*104*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*105*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*106*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*107*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*108*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*109*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*110*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*111*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*112*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*113*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*114*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*115*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*116*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*117*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*118*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*119*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*120*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*121*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*122*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*123*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*124*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*125*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*126*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_DCS_IGNORE */ +/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*32 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*33 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*34 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*35 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*36 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*37 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*38 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*39 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*40 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*41 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*42 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*43 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*44 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*45 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*46 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*47 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*48 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*49 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*50 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*51 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*52 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*53 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*54 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*55 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*56 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*57 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*58 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*59 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*60 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*61 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*62 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*63 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*64 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*65 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*66 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*67 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*68 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*69 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*70 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*71 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*72 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*73 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*74 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*75 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*76 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*77 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*78 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*79 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*80 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*81 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*82 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*83 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*84 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*85 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*86 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*87 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*88 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*89 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*90 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*91 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*92 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*93 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*94 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*95 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*96 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*97 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*98 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*99 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*100*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*101*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*102*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*103*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*104*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*105*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*106*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*107*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*108*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*109*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*110*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*111*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*112*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*113*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*114*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*115*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*116*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*117*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*118*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*119*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*120*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*121*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*122*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*123*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*124*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*125*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*126*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +/*156*/ 0 | (VTPARSE_STATE_GROUND << 4), + }, + { /* VTPARSE_STATE_DCS_INTERMEDIATE */ +/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*32 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*33 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*34 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*35 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*36 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*37 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*38 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*39 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*40 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*41 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*42 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*43 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*44 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*45 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*46 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*47 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*48 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*49 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*50 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*51 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*52 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*53 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*54 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*55 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*56 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*57 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*58 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*59 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*60 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*61 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*62 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*63 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*64 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*65 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*66 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*67 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*68 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*69 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*70 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*71 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*72 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*73 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*74 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*75 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*76 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*77 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*78 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*79 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*80 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*81 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*82 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*83 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*84 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*85 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*86 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*87 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*88 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*89 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*90 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*91 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*92 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*93 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*94 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*95 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*96 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*97 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*98 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*99 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*100*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*101*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*102*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*103*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*104*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*105*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*106*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*107*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*108*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*109*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*110*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*111*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*112*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*113*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*114*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*115*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*116*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*117*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*118*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*119*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*120*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*121*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*122*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*123*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*124*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*125*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*126*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_DCS_PARAM */ +/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4), +/*48 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*49 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*50 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*51 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*52 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*53 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*54 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*55 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*56 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*57 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*58 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*59 */ VTPARSE_ACTION_PARAM | (0 << 4), +/*60 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*61 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*62 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*63 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4), +/*64 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*65 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*66 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*67 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*68 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*69 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*70 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*71 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*72 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*73 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*74 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*75 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*76 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*77 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*78 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*79 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*80 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*81 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*82 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*83 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*84 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*85 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*86 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*87 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*88 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*89 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*90 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*91 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*92 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*93 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*94 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*95 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*96 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*97 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*98 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*99 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*100*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*101*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*102*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*103*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*104*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*105*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*106*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*107*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*108*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*109*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*110*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*111*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*112*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*113*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*114*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*115*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*116*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*117*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*118*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*119*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*120*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*121*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*122*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*123*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*124*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*125*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*126*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_DCS_PASSTHROUGH */ +/*0 */ VTPARSE_ACTION_PUT | (0 << 4), +/*1 */ VTPARSE_ACTION_PUT | (0 << 4), +/*2 */ VTPARSE_ACTION_PUT | (0 << 4), +/*3 */ VTPARSE_ACTION_PUT | (0 << 4), +/*4 */ VTPARSE_ACTION_PUT | (0 << 4), +/*5 */ VTPARSE_ACTION_PUT | (0 << 4), +/*6 */ VTPARSE_ACTION_PUT | (0 << 4), +/*7 */ VTPARSE_ACTION_PUT | (0 << 4), +/*8 */ VTPARSE_ACTION_PUT | (0 << 4), +/*9 */ VTPARSE_ACTION_PUT | (0 << 4), +/*10 */ VTPARSE_ACTION_PUT | (0 << 4), +/*11 */ VTPARSE_ACTION_PUT | (0 << 4), +/*12 */ VTPARSE_ACTION_PUT | (0 << 4), +/*13 */ VTPARSE_ACTION_PUT | (0 << 4), +/*14 */ VTPARSE_ACTION_PUT | (0 << 4), +/*15 */ VTPARSE_ACTION_PUT | (0 << 4), +/*16 */ VTPARSE_ACTION_PUT | (0 << 4), +/*17 */ VTPARSE_ACTION_PUT | (0 << 4), +/*18 */ VTPARSE_ACTION_PUT | (0 << 4), +/*19 */ VTPARSE_ACTION_PUT | (0 << 4), +/*20 */ VTPARSE_ACTION_PUT | (0 << 4), +/*21 */ VTPARSE_ACTION_PUT | (0 << 4), +/*22 */ VTPARSE_ACTION_PUT | (0 << 4), +/*23 */ VTPARSE_ACTION_PUT | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_PUT | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_PUT | (0 << 4), +/*29 */ VTPARSE_ACTION_PUT | (0 << 4), +/*30 */ VTPARSE_ACTION_PUT | (0 << 4), +/*31 */ VTPARSE_ACTION_PUT | (0 << 4), +/*32 */ VTPARSE_ACTION_PUT | (0 << 4), +/*33 */ VTPARSE_ACTION_PUT | (0 << 4), +/*34 */ VTPARSE_ACTION_PUT | (0 << 4), +/*35 */ VTPARSE_ACTION_PUT | (0 << 4), +/*36 */ VTPARSE_ACTION_PUT | (0 << 4), +/*37 */ VTPARSE_ACTION_PUT | (0 << 4), +/*38 */ VTPARSE_ACTION_PUT | (0 << 4), +/*39 */ VTPARSE_ACTION_PUT | (0 << 4), +/*40 */ VTPARSE_ACTION_PUT | (0 << 4), +/*41 */ VTPARSE_ACTION_PUT | (0 << 4), +/*42 */ VTPARSE_ACTION_PUT | (0 << 4), +/*43 */ VTPARSE_ACTION_PUT | (0 << 4), +/*44 */ VTPARSE_ACTION_PUT | (0 << 4), +/*45 */ VTPARSE_ACTION_PUT | (0 << 4), +/*46 */ VTPARSE_ACTION_PUT | (0 << 4), +/*47 */ VTPARSE_ACTION_PUT | (0 << 4), +/*48 */ VTPARSE_ACTION_PUT | (0 << 4), +/*49 */ VTPARSE_ACTION_PUT | (0 << 4), +/*50 */ VTPARSE_ACTION_PUT | (0 << 4), +/*51 */ VTPARSE_ACTION_PUT | (0 << 4), +/*52 */ VTPARSE_ACTION_PUT | (0 << 4), +/*53 */ VTPARSE_ACTION_PUT | (0 << 4), +/*54 */ VTPARSE_ACTION_PUT | (0 << 4), +/*55 */ VTPARSE_ACTION_PUT | (0 << 4), +/*56 */ VTPARSE_ACTION_PUT | (0 << 4), +/*57 */ VTPARSE_ACTION_PUT | (0 << 4), +/*58 */ VTPARSE_ACTION_PUT | (0 << 4), +/*59 */ VTPARSE_ACTION_PUT | (0 << 4), +/*60 */ VTPARSE_ACTION_PUT | (0 << 4), +/*61 */ VTPARSE_ACTION_PUT | (0 << 4), +/*62 */ VTPARSE_ACTION_PUT | (0 << 4), +/*63 */ VTPARSE_ACTION_PUT | (0 << 4), +/*64 */ VTPARSE_ACTION_PUT | (0 << 4), +/*65 */ VTPARSE_ACTION_PUT | (0 << 4), +/*66 */ VTPARSE_ACTION_PUT | (0 << 4), +/*67 */ VTPARSE_ACTION_PUT | (0 << 4), +/*68 */ VTPARSE_ACTION_PUT | (0 << 4), +/*69 */ VTPARSE_ACTION_PUT | (0 << 4), +/*70 */ VTPARSE_ACTION_PUT | (0 << 4), +/*71 */ VTPARSE_ACTION_PUT | (0 << 4), +/*72 */ VTPARSE_ACTION_PUT | (0 << 4), +/*73 */ VTPARSE_ACTION_PUT | (0 << 4), +/*74 */ VTPARSE_ACTION_PUT | (0 << 4), +/*75 */ VTPARSE_ACTION_PUT | (0 << 4), +/*76 */ VTPARSE_ACTION_PUT | (0 << 4), +/*77 */ VTPARSE_ACTION_PUT | (0 << 4), +/*78 */ VTPARSE_ACTION_PUT | (0 << 4), +/*79 */ VTPARSE_ACTION_PUT | (0 << 4), +/*80 */ VTPARSE_ACTION_PUT | (0 << 4), +/*81 */ VTPARSE_ACTION_PUT | (0 << 4), +/*82 */ VTPARSE_ACTION_PUT | (0 << 4), +/*83 */ VTPARSE_ACTION_PUT | (0 << 4), +/*84 */ VTPARSE_ACTION_PUT | (0 << 4), +/*85 */ VTPARSE_ACTION_PUT | (0 << 4), +/*86 */ VTPARSE_ACTION_PUT | (0 << 4), +/*87 */ VTPARSE_ACTION_PUT | (0 << 4), +/*88 */ VTPARSE_ACTION_PUT | (0 << 4), +/*89 */ VTPARSE_ACTION_PUT | (0 << 4), +/*90 */ VTPARSE_ACTION_PUT | (0 << 4), +/*91 */ VTPARSE_ACTION_PUT | (0 << 4), +/*92 */ VTPARSE_ACTION_PUT | (0 << 4), +/*93 */ VTPARSE_ACTION_PUT | (0 << 4), +/*94 */ VTPARSE_ACTION_PUT | (0 << 4), +/*95 */ VTPARSE_ACTION_PUT | (0 << 4), +/*96 */ VTPARSE_ACTION_PUT | (0 << 4), +/*97 */ VTPARSE_ACTION_PUT | (0 << 4), +/*98 */ VTPARSE_ACTION_PUT | (0 << 4), +/*99 */ VTPARSE_ACTION_PUT | (0 << 4), +/*100*/ VTPARSE_ACTION_PUT | (0 << 4), +/*101*/ VTPARSE_ACTION_PUT | (0 << 4), +/*102*/ VTPARSE_ACTION_PUT | (0 << 4), +/*103*/ VTPARSE_ACTION_PUT | (0 << 4), +/*104*/ VTPARSE_ACTION_PUT | (0 << 4), +/*105*/ VTPARSE_ACTION_PUT | (0 << 4), +/*106*/ VTPARSE_ACTION_PUT | (0 << 4), +/*107*/ VTPARSE_ACTION_PUT | (0 << 4), +/*108*/ VTPARSE_ACTION_PUT | (0 << 4), +/*109*/ VTPARSE_ACTION_PUT | (0 << 4), +/*110*/ VTPARSE_ACTION_PUT | (0 << 4), +/*111*/ VTPARSE_ACTION_PUT | (0 << 4), +/*112*/ VTPARSE_ACTION_PUT | (0 << 4), +/*113*/ VTPARSE_ACTION_PUT | (0 << 4), +/*114*/ VTPARSE_ACTION_PUT | (0 << 4), +/*115*/ VTPARSE_ACTION_PUT | (0 << 4), +/*116*/ VTPARSE_ACTION_PUT | (0 << 4), +/*117*/ VTPARSE_ACTION_PUT | (0 << 4), +/*118*/ VTPARSE_ACTION_PUT | (0 << 4), +/*119*/ VTPARSE_ACTION_PUT | (0 << 4), +/*120*/ VTPARSE_ACTION_PUT | (0 << 4), +/*121*/ VTPARSE_ACTION_PUT | (0 << 4), +/*122*/ VTPARSE_ACTION_PUT | (0 << 4), +/*123*/ VTPARSE_ACTION_PUT | (0 << 4), +/*124*/ VTPARSE_ACTION_PUT | (0 << 4), +/*125*/ VTPARSE_ACTION_PUT | (0 << 4), +/*126*/ VTPARSE_ACTION_PUT | (0 << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +/*156*/ 0 | (VTPARSE_STATE_GROUND << 4), + }, + { /* VTPARSE_STATE_ESCAPE */ +/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4), +/*48 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*49 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*50 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*51 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*52 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*53 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*54 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*55 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*56 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*57 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*58 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*59 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*60 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*61 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*62 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*63 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*64 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*65 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*66 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*67 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*68 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*69 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*70 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*71 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*72 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*73 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*74 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*75 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*76 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*77 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*78 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*79 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*80 */ 0 | (VTPARSE_STATE_DCS_ENTRY << 4), +/*81 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*82 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*83 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*84 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*85 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*86 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*87 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*88 */ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4), +/*89 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*90 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*91 */ 0 | (VTPARSE_STATE_CSI_ENTRY << 4), +/*92 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*93 */ 0 | (VTPARSE_STATE_OSC_STRING << 4), +/*94 */ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4), +/*95 */ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4), +/*96 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*97 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*98 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*99 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*100*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*101*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*102*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*103*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*104*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*105*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*106*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*107*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*108*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*109*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*110*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*111*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*112*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*113*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*114*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*115*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*116*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*117*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*118*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*119*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*120*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*121*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*122*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*123*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*124*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*125*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*126*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_ESCAPE_INTERMEDIATE */ +/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*32 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*33 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*34 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*35 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*36 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*37 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*38 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*39 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*40 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*41 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*42 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*43 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*44 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*45 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*46 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*47 */ VTPARSE_ACTION_COLLECT | (0 << 4), +/*48 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*49 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*50 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*51 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*52 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*53 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*54 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*55 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*56 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*57 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*58 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*59 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*60 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*61 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*62 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*63 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*64 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*65 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*66 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*67 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*68 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*69 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*70 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*71 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*72 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*73 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*74 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*75 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*76 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*77 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*78 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*79 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*80 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*81 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*82 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*83 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*84 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*85 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*86 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*87 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*88 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*89 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*90 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*91 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*92 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*93 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*94 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*95 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*96 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*97 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*98 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*99 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*100*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*101*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*102*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*103*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*104*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*105*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*106*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*107*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*108*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*109*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*110*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*111*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*112*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*113*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*114*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*115*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*116*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*117*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*118*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*119*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*120*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*121*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*122*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*123*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*124*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*125*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*126*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + }, + { /* VTPARSE_STATE_GROUND */ +/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*32 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*33 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*34 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*35 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*36 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*37 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*38 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*39 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*40 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*41 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*42 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*43 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*44 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*45 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*46 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*47 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*48 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*49 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*50 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*51 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*52 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*53 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*54 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*55 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*56 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*57 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*58 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*59 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*60 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*61 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*62 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*63 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*64 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*65 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*66 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*67 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*68 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*69 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*70 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*71 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*72 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*73 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*74 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*75 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*76 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*77 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*78 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*79 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*80 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*81 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*82 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*83 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*84 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*85 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*86 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*87 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*88 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*89 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*90 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*91 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*92 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*93 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*94 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*95 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*96 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*97 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*98 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*99 */ VTPARSE_ACTION_PRINT | (0 << 4), +/*100*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*101*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*102*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*103*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*104*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*105*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*106*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*107*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*108*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*109*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*110*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*111*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*112*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*113*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*114*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*115*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*116*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*117*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*118*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*119*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*120*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*121*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*122*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*123*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*124*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*125*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*126*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*127*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*128*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*129*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*130*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*131*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*132*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*133*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*134*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*135*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*136*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*137*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*138*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*139*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*140*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*141*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*142*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*143*/ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*145*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*146*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*147*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*148*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*149*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*150*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*151*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*152*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*153*/ VTPARSE_ACTION_EXECUTE | (0 << 4), +/*154*/ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, +/*156*/ VTPARSE_ACTION_EXECUTE | (0 << 4), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +/*192*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*193*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*194*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*195*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*196*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*197*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*198*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*199*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*200*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*201*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*202*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*203*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*204*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*205*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*206*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*207*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*208*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*209*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*210*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*211*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*212*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*213*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*214*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*215*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*216*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*217*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*218*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*219*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*220*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*221*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*222*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*223*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*224*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*225*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*226*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*227*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*228*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*229*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*230*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*231*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*232*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*233*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*234*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*235*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*236*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*237*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*238*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*239*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*240*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*241*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*242*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*243*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*244*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*245*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*246*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*247*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*248*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*249*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*250*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*251*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*252*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), +/*253*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4), + }, + { /* VTPARSE_STATE_OSC_STRING */ +/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*32 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*33 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*34 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*35 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*36 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*37 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*38 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*39 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*40 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*41 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*42 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*43 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*44 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*45 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*46 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*47 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*48 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*49 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*50 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*51 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*52 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*53 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*54 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*55 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*56 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*57 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*58 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*59 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*60 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*61 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*62 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*63 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*64 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*65 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*66 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*67 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*68 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*69 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*70 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*71 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*72 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*73 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*74 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*75 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*76 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*77 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*78 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*79 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*80 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*81 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*82 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*83 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*84 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*85 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*86 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*87 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*88 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*89 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*90 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*91 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*92 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*93 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*94 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*95 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*96 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*97 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*98 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*99 */ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*100*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*101*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*102*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*103*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*104*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*105*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*106*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*107*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*108*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*109*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*110*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*111*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*112*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*113*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*114*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*115*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*116*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*117*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*118*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*119*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*120*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*121*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*122*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*123*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*124*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*125*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*126*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), +/*127*/ VTPARSE_ACTION_OSC_PUT | (0 << 4), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +/*156*/ 0 | (VTPARSE_STATE_GROUND << 4), + }, + { /* VTPARSE_STATE_SOS_PM_APC_STRING */ +/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, +/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*32 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*33 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*34 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*35 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*36 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*37 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*38 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*39 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*40 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*41 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*42 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*43 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*44 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*45 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*46 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*47 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*48 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*49 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*50 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*51 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*52 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*53 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*54 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*55 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*56 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*57 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*58 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*59 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*60 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*61 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*62 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*63 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*64 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*65 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*66 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*67 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*68 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*69 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*70 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*71 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*72 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*73 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*74 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*75 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*76 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*77 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*78 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*79 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*80 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*81 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*82 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*83 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*84 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*85 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*86 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*87 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*88 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*89 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*90 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*91 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*92 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*93 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*94 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*95 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*96 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*97 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*98 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*99 */ VTPARSE_ACTION_IGNORE | (0 << 4), +/*100*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*101*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*102*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*103*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*104*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*105*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*106*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*107*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*108*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*109*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*110*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*111*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*112*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*113*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*114*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*115*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*116*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*117*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*118*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*119*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*120*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*121*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*122*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*123*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*124*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*125*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*126*/ VTPARSE_ACTION_IGNORE | (0 << 4), +/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +/*156*/ 0 | (VTPARSE_STATE_GROUND << 4), + }, + { /* VTPARSE_STATE_UTF8 */ +/*0 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*1 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*2 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*3 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*4 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*5 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*6 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*7 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*8 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*9 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*10 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*11 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*12 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*13 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*14 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*15 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*16 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*17 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*18 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*19 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*20 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*21 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*22 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*23 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), + 0, +/*25 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), + 0, + 0, +/*28 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*29 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*30 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*31 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4), +/*32 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*33 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*34 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*35 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*36 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*37 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*38 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*39 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*40 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*41 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*42 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*43 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*44 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*45 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*46 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*47 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*48 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*49 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*50 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*51 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*52 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*53 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*54 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*55 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*56 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*57 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*58 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*59 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*60 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*61 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*62 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*63 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*64 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*65 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*66 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*67 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*68 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*69 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*70 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*71 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*72 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*73 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*74 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*75 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*76 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*77 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*78 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*79 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*80 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*81 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*82 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*83 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*84 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*85 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*86 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*87 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*88 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*89 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*90 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*91 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*92 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*93 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*94 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*95 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*96 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*97 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*98 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*99 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*100*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*101*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*102*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*103*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*104*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*105*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*106*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*107*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*108*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*109*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*110*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*111*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*112*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*113*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*114*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*115*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*116*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*117*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*118*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*119*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*120*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*121*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*122*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*123*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*124*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*125*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*126*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*127*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4), +/*128*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*129*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*130*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*131*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*132*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*133*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*134*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*135*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*136*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*137*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*138*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*139*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*140*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*141*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*142*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*143*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*144*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*145*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*146*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*147*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*148*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*149*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*150*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*151*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*152*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*153*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*154*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*155*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*156*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*157*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*158*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*159*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*160*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*161*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*162*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*163*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*164*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*165*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*166*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*167*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*168*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*169*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*170*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*171*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*172*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*173*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*174*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*175*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*176*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*177*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*178*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*179*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*180*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*181*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*182*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*183*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*184*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*185*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*186*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*187*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*188*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*189*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*190*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*191*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*192*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*193*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*194*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*195*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*196*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*197*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*198*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*199*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*200*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*201*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*202*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*203*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*204*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*205*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*206*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*207*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*208*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*209*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*210*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*211*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*212*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*213*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*214*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*215*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*216*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*217*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*218*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*219*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*220*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*221*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*222*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*223*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*224*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*225*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*226*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*227*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*228*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*229*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*230*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*231*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*232*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*233*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*234*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*235*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*236*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*237*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*238*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*239*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*240*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*241*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*242*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*243*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*244*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*245*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*246*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*247*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*248*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*249*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*250*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*251*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*252*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*253*/ VTPARSE_ACTION_PRINT | (0 << 4), +/*254*/ 0 | (VTPARSE_STATE_GROUND << 4), +/*255*/ 0 | (VTPARSE_STATE_GROUND << 4), + }, +}; + +vtparse_action_t ENTRY_ACTIONS[] = { + 0 /* none for ANYWHERE */, + VTPARSE_ACTION_CLEAR, /* CSI_ENTRY */ + 0 /* none for CSI_IGNORE */, + 0 /* none for CSI_INTERMEDIATE */, + 0 /* none for CSI_PARAM */, + VTPARSE_ACTION_CLEAR, /* DCS_ENTRY */ + 0 /* none for DCS_IGNORE */, + 0 /* none for DCS_INTERMEDIATE */, + 0 /* none for DCS_PARAM */, + VTPARSE_ACTION_HOOK, /* DCS_PASSTHROUGH */ + VTPARSE_ACTION_CLEAR, /* ESCAPE */ + 0 /* none for ESCAPE_INTERMEDIATE */, + 0 /* none for GROUND */, + VTPARSE_ACTION_OSC_START, /* OSC_STRING */ + 0 /* none for SOS_PM_APC_STRING */, + 0 /* none for UTF8 */, +}; + +vtparse_action_t EXIT_ACTIONS[] = { + 0 /* none for ANYWHERE */, + 0 /* none for CSI_ENTRY */, + 0 /* none for CSI_IGNORE */, + 0 /* none for CSI_INTERMEDIATE */, + 0 /* none for CSI_PARAM */, + 0 /* none for DCS_ENTRY */, + 0 /* none for DCS_IGNORE */, + 0 /* none for DCS_INTERMEDIATE */, + 0 /* none for DCS_PARAM */, + VTPARSE_ACTION_UNHOOK, /* DCS_PASSTHROUGH */ + 0 /* none for ESCAPE */, + 0 /* none for ESCAPE_INTERMEDIATE */, + 0 /* none for GROUND */, + VTPARSE_ACTION_OSC_END, /* OSC_STRING */ + 0 /* none for SOS_PM_APC_STRING */, + 0 /* none for UTF8 */, +}; + diff --git a/vtparse/src/vtparse_table.h b/vtparse/src/vtparse_table.h new file mode 100644 index 0000000..1dec0a8 --- /dev/null +++ b/vtparse/src/vtparse_table.h @@ -0,0 +1,43 @@ +typedef enum { + VTPARSE_STATE_ANYWHERE = 0, + VTPARSE_STATE_CSI_ENTRY = 1, + VTPARSE_STATE_CSI_IGNORE = 2, + VTPARSE_STATE_CSI_INTERMEDIATE = 3, + VTPARSE_STATE_CSI_PARAM = 4, + VTPARSE_STATE_DCS_ENTRY = 5, + VTPARSE_STATE_DCS_IGNORE = 6, + VTPARSE_STATE_DCS_INTERMEDIATE = 7, + VTPARSE_STATE_DCS_PARAM = 8, + VTPARSE_STATE_DCS_PASSTHROUGH = 9, + VTPARSE_STATE_ESCAPE = 10, + VTPARSE_STATE_ESCAPE_INTERMEDIATE = 11, + VTPARSE_STATE_GROUND = 12, + VTPARSE_STATE_OSC_STRING = 13, + VTPARSE_STATE_SOS_PM_APC_STRING = 14, + VTPARSE_STATE_UTF8 = 15, +} vtparse_state_t; + +typedef enum { + VTPARSE_ACTION_CLEAR = 1, + VTPARSE_ACTION_COLLECT = 2, + VTPARSE_ACTION_CSI_DISPATCH = 3, + VTPARSE_ACTION_ESC_DISPATCH = 4, + VTPARSE_ACTION_EXECUTE = 5, + VTPARSE_ACTION_HOOK = 6, + VTPARSE_ACTION_IGNORE = 7, + VTPARSE_ACTION_OSC_END = 8, + VTPARSE_ACTION_OSC_PUT = 9, + VTPARSE_ACTION_OSC_START = 10, + VTPARSE_ACTION_PARAM = 11, + VTPARSE_ACTION_PRINT = 12, + VTPARSE_ACTION_PUT = 13, + VTPARSE_ACTION_UNHOOK = 14, +} vtparse_action_t; + +typedef unsigned char state_change_t; +extern state_change_t STATE_TABLE[16][256]; +extern vtparse_action_t ENTRY_ACTIONS[16]; +extern vtparse_action_t EXIT_ACTIONS[16]; +extern char *ACTION_NAMES[15]; +extern char *STATE_NAMES[16]; + diff --git a/vtparse/src/vtparse_tables.rb b/vtparse/src/vtparse_tables.rb new file mode 100644 index 0000000..030be7d --- /dev/null +++ b/vtparse/src/vtparse_tables.rb @@ -0,0 +1,269 @@ + +class StateTransition + attr_accessor :to_state + def initialize(to_state) + @to_state = to_state + end +end + +def transition_to(state) + StateTransition.new(state) +end + +$states = {} + +$states[:ANYWHERE] = { + 0x18 => [:execute, transition_to(:GROUND)], + 0x1a => [:execute, transition_to(:GROUND)], + 0x80..0x8f => [:execute, transition_to(:GROUND)], + 0x91..0x97 => [:execute, transition_to(:GROUND)], + 0x99 => [:execute, transition_to(:GROUND)], + 0x9a => [:execute, transition_to(:GROUND)], + 0x9c => [:execute, transition_to(:GROUND)], + 0x1b => transition_to(:ESCAPE), + 0x98 => transition_to(:SOS_PM_APC_STRING), + 0x9e => transition_to(:SOS_PM_APC_STRING), + 0x9f => transition_to(:SOS_PM_APC_STRING), + 0x90 => transition_to(:DCS_ENTRY), + 0x9d => transition_to(:OSC_STRING), + 0x9b => transition_to(:CSI_ENTRY), + 0xc0..0xdf => [:print, transition_to(:UTF8)], # UTF-8 2 bytes sequence start + 0xe0..0xef => [:print, transition_to(:UTF8)], # UTF-8 3 bytes sequence start + 0xf0..0xf7 => [:print, transition_to(:UTF8)], # UTF-8 4 bytes sequence start + 0xf8..0xfb => [:print, transition_to(:UTF8)], # UTF-8 5 bytes sequence start + 0xfc..0xfd => [:print, transition_to(:UTF8)] # UTF-8 6 bytes sequence start +} + +$states[:GROUND] = { + 0x00..0x17 => :execute, + 0x19 => :execute, + 0x1c..0x1f => :execute, + 0x20..0x7f => :print, + 0x80..0x8f => :execute, + 0x91..0x9a => :execute, + 0x9c => :execute, + 0xc0..0xdf => [:print, transition_to(:UTF8)], # UTF-8 2 bytes sequence start + 0xe0..0xef => [:print, transition_to(:UTF8)], # UTF-8 3 bytes sequence start + 0xf0..0xf7 => [:print, transition_to(:UTF8)], # UTF-8 4 bytes sequence start + 0xf8..0xfb => [:print, transition_to(:UTF8)], # UTF-8 5 bytes sequence start + 0xfc..0xfd => [:print, transition_to(:UTF8)] # UTF-8 6 bytes sequence start +} + +$states[:UTF8] = { + 0x00..0x17 => [:execute, transition_to(:GROUND)], + 0x19 => [:execute, transition_to(:GROUND)], + 0x1c..0x1f => [:execute, transition_to(:GROUND)], + 0x20..0x7f => [:print, transition_to(:GROUND)], + 0x80..0xbf => :print, # UTF-8 sequence + 0xc0..0xdf => :print, # UTF-8 2 bytes sequence start + 0xe0..0xef => :print, # UTF-8 3 bytes sequence start + 0xf0..0xf7 => :print, # UTF-8 4 bytes sequence start + 0xf8..0xfb => :print, # UTF-8 5 bytes sequence start + 0xfc..0xfd => :print, # UTF-8 6 bytes sequence start + 0xfe..0xff => transition_to(:GROUND) +} + +$states[:ESCAPE] = { + :on_entry => :clear, + 0x00..0x17 => :execute, + 0x19 => :execute, + 0x1c..0x1f => :execute, + 0x7f => :ignore, + 0x20..0x2f => [:collect, transition_to(:ESCAPE_INTERMEDIATE)], + 0x30..0x4f => [:esc_dispatch, transition_to(:GROUND)], + 0x51..0x57 => [:esc_dispatch, transition_to(:GROUND)], + 0x59 => [:esc_dispatch, transition_to(:GROUND)], + 0x5a => [:esc_dispatch, transition_to(:GROUND)], + 0x5c => [:esc_dispatch, transition_to(:GROUND)], + 0x60..0x7e => [:esc_dispatch, transition_to(:GROUND)], + 0x5b => transition_to(:CSI_ENTRY), + 0x5d => transition_to(:OSC_STRING), + 0x50 => transition_to(:DCS_ENTRY), + 0x58 => transition_to(:SOS_PM_APC_STRING), + 0x5e => transition_to(:SOS_PM_APC_STRING), + 0x5f => transition_to(:SOS_PM_APC_STRING), +} + +$states[:ESCAPE_INTERMEDIATE] = { + 0x00..0x17 => :execute, + 0x19 => :execute, + 0x1c..0x1f => :execute, + 0x20..0x2f => :collect, + 0x7f => :ignore, + 0x30..0x7e => [:esc_dispatch, transition_to(:GROUND)] +} + +$states[:CSI_ENTRY] = { + :on_entry => :clear, + 0x00..0x17 => :execute, + 0x19 => :execute, + 0x1c..0x1f => :execute, + 0x7f => :ignore, + 0x20..0x2f => [:collect, transition_to(:CSI_INTERMEDIATE)], + 0x3a => transition_to(:CSI_IGNORE), + 0x30..0x39 => [:param, transition_to(:CSI_PARAM)], + 0x3b => [:param, transition_to(:CSI_PARAM)], + 0x3c..0x3f => [:collect, transition_to(:CSI_PARAM)], + 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)] +} + +$states[:CSI_IGNORE] = { + 0x00..0x17 => :execute, + 0x19 => :execute, + 0x1c..0x1f => :execute, + 0x20..0x3f => :ignore, + 0x7f => :ignore, + 0x40..0x7e => transition_to(:GROUND), +} + +$states[:CSI_PARAM] = { + 0x00..0x17 => :execute, + 0x19 => :execute, + 0x1c..0x1f => :execute, + 0x30..0x39 => :param, + 0x3b => :param, + 0x7f => :ignore, + 0x3a => transition_to(:CSI_IGNORE), + 0x3c..0x3f => transition_to(:CSI_IGNORE), + 0x20..0x2f => [:collect, transition_to(:CSI_INTERMEDIATE)], + 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)] +} + +$states[:CSI_INTERMEDIATE] = { + 0x00..0x17 => :execute, + 0x19 => :execute, + 0x1c..0x1f => :execute, + 0x20..0x2f => :collect, + 0x7f => :ignore, + 0x30..0x3f => transition_to(:CSI_IGNORE), + 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)], +} + +$states[:DCS_ENTRY] = { + :on_entry => :clear, + 0x00..0x17 => :ignore, + 0x19 => :ignore, + 0x1c..0x1f => :ignore, + 0x7f => :ignore, + 0x3a => transition_to(:DCS_IGNORE), + 0x20..0x2f => [:collect, transition_to(:DCS_INTERMEDIATE)], + 0x30..0x39 => [:param, transition_to(:DCS_PARAM)], + 0x3b => [:param, transition_to(:DCS_PARAM)], + 0x3c..0x3f => [:collect, transition_to(:DCS_PARAM)], + 0x40..0x7e => [transition_to(:DCS_PASSTHROUGH)] +} + +$states[:DCS_INTERMEDIATE] = { + 0x00..0x17 => :ignore, + 0x19 => :ignore, + 0x1c..0x1f => :ignore, + 0x20..0x2f => :collect, + 0x7f => :ignore, + 0x30..0x3f => transition_to(:DCS_IGNORE), + 0x40..0x7e => transition_to(:DCS_PASSTHROUGH) +} + +$states[:DCS_IGNORE] = { + 0x00..0x17 => :ignore, + 0x19 => :ignore, + 0x1c..0x1f => :ignore, + 0x20..0x7f => :ignore, + 0x9c => transition_to(:GROUND) +} + +$states[:DCS_PARAM] = { + 0x00..0x17 => :ignore, + 0x19 => :ignore, + 0x1c..0x1f => :ignore, + 0x30..0x39 => :param, + 0x3b => :param, + 0x7f => :ignore, + 0x3a => transition_to(:DCS_IGNORE), + 0x3c..0x3f => transition_to(:DCS_IGNORE), + 0x20..0x2f => [:collect, transition_to(:DCS_INTERMEDIATE)], + 0x40..0x7e => transition_to(:DCS_PASSTHROUGH) +} + +$states[:DCS_PASSTHROUGH] = { + :on_entry => :hook, + 0x00..0x17 => :put, + 0x19 => :put, + 0x1c..0x1f => :put, + 0x20..0x7e => :put, + 0x7f => :ignore, + 0x9c => transition_to(:GROUND), + :on_exit => :unhook +} + +$states[:SOS_PM_APC_STRING] = { + 0x00..0x17 => :ignore, + 0x19 => :ignore, + 0x1c..0x1f => :ignore, + 0x20..0x7f => :ignore, + 0x9c => transition_to(:GROUND) +} + +$states[:OSC_STRING] = { + :on_entry => :osc_start, + 0x00..0x17 => :ignore, + 0x19 => :ignore, + 0x1c..0x1f => :ignore, + 0x20..0x7f => :osc_put, + 0x9c => transition_to(:GROUND), + :on_exit => :osc_end +} + +$states.each { |state, transitions| + transitions.each { |keys, actions| + if not actions.kind_of?(Array) + $states[state][keys] = [actions] + end + } +} + + +# get the list of actions implicit in the tables + +action_names = {} +$states.each { |state, transitions| + transitions.each { |keys, actions| + actions.each { |action| + if action.kind_of?(Symbol) + action_names[action] = 1 + end + } + } +} + +# establish an ordering to the states and actions + +$actions_in_order = action_names.keys.sort { |a1, a2| a1.to_s <=> a2.to_s } +$states_in_order = $states.keys.sort { |s1, s2| s1.to_s <=> s2.to_s } + +# +# Expand the above range-based data structures (which are convenient +# to write) into fully expanded tables (which are easier to use). +# + +$state_tables = {} + +def expand_ranges(hash_with_ranges_as_keys) + array = [] + hash_with_ranges_as_keys.each { |range, val| + if range.kind_of?(Range) + range.each { |i| + array[i] = val + } + elsif range.kind_of?(Fixnum) + array[range] = val + end + } + + array +end + +$states.each { |state, transitions| + $state_tables[state] = expand_ranges(transitions) +} + + diff --git a/vtparse/src/vtparse_test.c b/vtparse/src/vtparse_test.c new file mode 100644 index 0000000..4082655 --- /dev/null +++ b/vtparse/src/vtparse_test.c @@ -0,0 +1,37 @@ +/* + * VTParse - an implementation of Paul Williams' DEC compatible state machine parser + * + * Author: Joshua Haberman + * + * This code is in the public domain. + */ + +#include +#include "vtparse.h" + +void parser_callback(vtparse_t *parser, vtparse_action_t action, unsigned char ch) +{ + int i; + + printf("Received action %s, char=0x%02x\n", ACTION_NAMES[action]); + printf("Intermediate chars: '%s'\n", parser->intermediate_chars); + printf("%d Parameters:\n", parser->num_params); + for(i = 0; i < parser->num_params; i++) + printf("\t%d\n", parser->params[i]); + printf("\n"); +} + +int main() +{ + unsigned char buf[1024]; + int bytes; + vtparse_t parser; + + vtparse_init(&parser, parser_callback); + + while(1) { + bytes = read(0, buf, 1024); + vtparse(&parser, buf, bytes); + } +} + diff --git a/vtparse/vtparse.vcxproj b/vtparse/vtparse.vcxproj new file mode 100644 index 0000000..3d1c88b --- /dev/null +++ b/vtparse/vtparse.vcxproj @@ -0,0 +1,118 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + {F0F2B96C-1A36-487F-9A79-9F5BC7D0B829} + vtparse + Win32Proj + + + + StaticLibrary + NotSet + true + v140_xp + + + StaticLibrary + NotSet + v140_xp + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)build\temp\lib\ + $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ + $(SolutionDir)build\temp\lib\ + $(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + $(ProjectName)-mt-debug + $(ProjectName)-mt + + + + Disabled + false + $(SolutionDir)compatibility;%(AdditionalIncludeDirectories) + _WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;_DEBUG;_LIB;HAVE_PTW32_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;%(PreprocessorDefinitions) + false + + + Default + MultiThreadedDebug + + + Level3 + OldStyle + + + + + xcopy "$(ProjectDir)src\vtparse.h" "$(SolutionDir)build\temp\include\vtparse\" /I /Y /D +xcopy "$(ProjectDir)src\vtparse_table.h" "$(SolutionDir)build\temp\include\vtparse\" /I /Y /D + + + + + + MaxSpeed + AnySuitable + false + false + $(SolutionDir)compatibility;%(AdditionalIncludeDirectories) + _WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;NDEBUG;_LIB;HAVE_PTW32_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + + + Level3 + + + + + + + xcopy "$(ProjectDir)src\vtparse.h" "$(SolutionDir)build\temp\include\vtparse\" /I /Y /D +xcopy "$(ProjectDir)src\vtparse_table.h" "$(SolutionDir)build\temp\include\vtparse\" /I /Y /D + + + + + + + \ No newline at end of file diff --git a/vtparse/vtparse.vcxproj.filters b/vtparse/vtparse.vcxproj.filters new file mode 100644 index 0000000..6c4f4a7 --- /dev/null +++ b/vtparse/vtparse.vcxproj.filters @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3