Compare commits
	
		
			660 Commits
		
	
	
		
			curl-7_31_
			...
			curl-7_34_
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 0966b324d9 | ||
|   | c0ef05e675 | ||
|   | 1dc43de0dc | ||
|   | 8a8f9a5d57 | ||
|   | be28223f35 | ||
|   | 8e2d73bbde | ||
|   | dd4d9ea542 | ||
|   | 169fedbdce | ||
|   | 32b9c30e67 | ||
|   | 75cd7fd667 | ||
|   | 7246dffff5 | ||
|   | 41d21e460f | ||
|   | aadca7f418 | ||
|   | 3905bd637d | ||
|   | c4f46e97ca | ||
|   | bd3ca6630a | ||
|   | 92e607abfa | ||
|   | ef118c13ba | ||
|   | 1cf71bd76e | ||
|   | 2c0ecac9d3 | ||
|   | b0b5b51193 | ||
|   | ff9b66a8d4 | ||
|   | e221b55f67 | ||
|   | 865666afca | ||
|   | 7fc9325a52 | ||
|   | 4fb8241add | ||
|   | 30e7e7552b | ||
|   | f58f843f66 | ||
|   | d92de3a7e9 | ||
|   | fe7fc61c6e | ||
|   | ad3836448e | ||
|   | f3ee587775 | ||
|   | c92c30edbd | ||
|   | 4d10f48629 | ||
|   | dc68120e63 | ||
|   | 0db811b69b | ||
|   | d81cbbcc2c | ||
|   | 0dd6522036 | ||
|   | 889cb9c982 | ||
|   | 26ff1ea6c3 | ||
|   | 59f1209fad | ||
|   | 7b9365c65f | ||
|   | a900d45489 | ||
|   | e64f91feb7 | ||
|   | b2a55c8106 | ||
|   | 030a2b8cb8 | ||
|   | edce855943 | ||
|   | 35e476a3f6 | ||
|   | 0434a19431 | ||
|   | 2ff0c6f5f3 | ||
|   | 8a94aedbd6 | ||
|   | 95877cf8ae | ||
|   | d3325ae40a | ||
|   | 23fabf8dea | ||
|   | 7a36b2abc0 | ||
|   | e1c255f388 | ||
|   | 6d3c832a30 | ||
|   | 7935478397 | ||
|   | 5ee64be9c6 | ||
|   | 9f18cf15d5 | ||
|   | bf05da183e | ||
|   | 2c04e8d80c | ||
|   | 925df53580 | ||
|   | 8191800a0c | ||
|   | 2165298fe6 | ||
|   | e885dc85a1 | ||
|   | df58084695 | ||
|   | 3c8c9b2779 | ||
|   | b27dc009cf | ||
|   | 2c7a5578e1 | ||
|   | b56d7cda74 | ||
|   | 8896b56488 | ||
|   | 0d735c29f9 | ||
|   | 3d50e91aee | ||
|   | 0cbfe5a7d5 | ||
|   | eedca5055e | ||
|   | 5d040632ac | ||
|   | 314c3b8480 | ||
|   | d630e1f389 | ||
|   | 0ea4a80bb2 | ||
|   | ed4ce23c23 | ||
|   | 168aa59705 | ||
|   | f71b1ad908 | ||
|   | dac01ff6d7 | ||
|   | 4a9fe26837 | ||
|   | 90ec8763a5 | ||
|   | 796333bc5e | ||
|   | f16c0de4e9 | ||
|   | 786cba1ada | ||
|   | ed1662c374 | ||
|   | 1f0616ea1a | ||
|   | 55250d2d02 | ||
|   | c5d73167a6 | ||
|   | bde901ad89 | ||
|   | 79c77f7c31 | ||
|   | 986c249f2f | ||
|   | 3b8c3eb911 | ||
|   | b29217d0d6 | ||
|   | 534f90f9bf | ||
|   | dbe228353d | ||
|   | bf77101e5c | ||
|   | 2ea9a125a6 | ||
|   | 58a00d6d9f | ||
|   | 57a27528e6 | ||
|   | 632c1edd06 | ||
|   | 434bc09263 | ||
|   | f2584627c8 | ||
|   | 6901861fc9 | ||
|   | d7d8a8f922 | ||
|   | c19cfb79db | ||
|   | 65ce9b6d6c | ||
|   | 5f34a10445 | ||
|   | fa1253aee1 | ||
|   | f833f54979 | ||
|   | e7d77fb3ef | ||
|   | c8e63f247a | ||
|   | 7396ad6e09 | ||
|   | 6d295f8d7d | ||
|   | 5bd999d0c5 | ||
|   | 0f81fbe5da | ||
|   | 9b67960421 | ||
|   | e10a26a9d6 | ||
|   | 7b68b58bc0 | ||
|   | 2d5455feac | ||
|   | ac05c80f19 | ||
|   | 460adfef93 | ||
|   | c876f6ae6d | ||
|   | f49276bfcb | ||
|   | d08ee3c83d | ||
|   | cf7008670b | ||
|   | 558034ab70 | ||
|   | 27b7b1062f | ||
|   | af82661dbd | ||
|   | 76f924131c | ||
|   | 98a5fdaf29 | ||
|   | 1ea05be46d | ||
|   | c9d8c00a41 | ||
|   | 5aa290f0f2 | ||
|   | f0831f7931 | ||
|   | 7fc3b2ce38 | ||
|   | 02fbc26d59 | ||
|   | 0074c9f5d1 | ||
|   | 90acbfd52e | ||
|   | 989b28fe97 | ||
|   | aa61e14dc1 | ||
|   | a84a09ad0b | ||
|   | 66b8557aff | ||
|   | 63cac69c2a | ||
|   | f77d9b6584 | ||
|   | 2736b27df7 | ||
|   | 297644fa70 | ||
|   | 0177f28c51 | ||
|   | 732d10ed6c | ||
|   | 526a1c3b45 | ||
|   | 5b315a273e | ||
|   | 5094bb53f4 | ||
|   | 052f24c9b7 | ||
|   | bce03fe144 | ||
|   | 9a1755264f | ||
|   | 3b59696a93 | ||
|   | cdccb42267 | ||
|   | 753d44fa00 | ||
|   | cfdfdcdd9d | ||
|   | e232f5f3f9 | ||
|   | 43400b4086 | ||
|   | 8179354c2f | ||
|   | f6c335d63f | ||
|   | 2bd72fa61c | ||
|   | e17c1b25bc | ||
|   | 7d1eb66cd7 | ||
|   | 255826c40f | ||
|   | 1d0eead969 | ||
|   | 8005e58983 | ||
|   | 5d415815df | ||
|   | f68559c086 | ||
|   | 08f97f3b1d | ||
|   | b87ba2c942 | ||
|   | e7a2ba41e3 | ||
|   | 6fe619be7a | ||
|   | 1e39b95682 | ||
|   | 8230af0b94 | ||
|   | 1709e5e966 | ||
|   | 7d7df83198 | ||
|   | 7de4cc35f8 | ||
|   | aa0eaef483 | ||
|   | 9f503a254b | ||
|   | d44b014271 | ||
|   | 469b423350 | ||
|   | 0adad07690 | ||
|   | e4670a1029 | ||
|   | 1f0e50f2b9 | ||
|   | 2766262a68 | ||
|   | bdb1f0e53d | ||
|   | 6e3613e6e6 | ||
|   | 1cb5150dba | ||
|   | d24b7953c2 | ||
|   | 13db74ffc3 | ||
|   | 98905aa2c5 | ||
|   | 820ed48a00 | ||
|   | 973cc22529 | ||
|   | 2cc9246477 | ||
|   | 650036633f | ||
|   | 78aee26be6 | ||
|   | 947d431d50 | ||
|   | 58bd0148fb | ||
|   | ca5c5be3e4 | ||
|   | 9bd37a6d27 | ||
|   | 1be69159f3 | ||
|   | a3da0a96e3 | ||
|   | 626f8a85f0 | ||
|   | 867b52a7ac | ||
|   | be31924f8c | ||
|   | f70b2c77f4 | ||
|   | ae495ffcc3 | ||
|   | 0fdfe82c6a | ||
|   | dead10b1b8 | ||
|   | 41d820d2c3 | ||
|   | 5b31b38c27 | ||
|   | 39f4e4fafa | ||
|   | 587811c0a6 | ||
|   | 7f7fbe7fbd | ||
|   | 9b1eb2b421 | ||
|   | 1034aa6680 | ||
|   | 4be0af7f74 | ||
|   | 72f850571d | ||
|   | e179d0eb12 | ||
|   | ce61510127 | ||
|   | 86c64f3daf | ||
|   | 65e556d0ce | ||
|   | 6a1363128f | ||
|   | 75b9b26465 | ||
|   | 2c84ffe154 | ||
|   | e7452415c5 | ||
|   | 87861c9b0e | ||
|   | 4d49ffe165 | ||
|   | f63603dec4 | ||
|   | 0218a737fe | ||
|   | 18ca0aa984 | ||
|   | c4e6c33b13 | ||
|   | d774802eec | ||
|   | 69c0d3fbc8 | ||
|   | 076726f141 | ||
|   | ad34a2d5c8 | ||
|   | 31e106c01c | ||
|   | 1dcc433661 | ||
|   | a106abee62 | ||
|   | f77e89c5d2 | ||
|   | 92cf6141ed | ||
|   | cf12d5b62f | ||
|   | 39beaa5ffb | ||
|   | 5df04bfafd | ||
|   | d015f4ccac | ||
|   | 143d7c13d8 | ||
|   | 9b33ecfd01 | ||
|   | ca1b34b887 | ||
|   | f0f95c97f7 | ||
|   | 4cd444e01a | ||
|   | 8264478490 | ||
|   | b46491900d | ||
|   | 725288bf2f | ||
|   | 173160c0d0 | ||
|   | 3c3622b662 | ||
|   | a22c478ed7 | ||
|   | 3d43a48781 | ||
|   | c8b05b809e | ||
|   | ca995010d0 | ||
|   | 25a0c96a49 | ||
|   | a8b606b1a6 | ||
|   | 20a99a45c0 | ||
|   | 49341628b5 | ||
|   | ab7e6afd44 | ||
|   | 4d7bf73fc3 | ||
|   | 3c34f453fa | ||
|   | d5f687ed8f | ||
|   | a377fab015 | ||
|   | 092f33d6bf | ||
|   | 09a13a1c01 | ||
|   | 30a09783b2 | ||
|   | 733a4419d0 | ||
|   | 77dc4ba877 | ||
|   | 14d8209adc | ||
|   | a942d8ff5b | ||
|   | 1695c67818 | ||
|   | f81d1e1666 | ||
|   | b71ed1fb3d | ||
|   | 86ccfaa3fd | ||
|   | 3b69462fc0 | ||
|   | 22bccb0eda | ||
|   | 4f591b9148 | ||
|   | 52cefc8cd7 | ||
|   | 8880f84e1a | ||
|   | 9d4a8c7936 | ||
|   | fd8dc21fd0 | ||
|   | 8ec6486d05 | ||
|   | 59c1743c78 | ||
|   | 60a2046162 | ||
|   | 6dd8bd8d2f | ||
|   | b07709f741 | ||
|   | 9215cee4c6 | ||
|   | 34df869f99 | ||
|   | 3f04d48495 | ||
|   | 517b8e2290 | ||
|   | af44da38d6 | ||
|   | fcfa26a7ee | ||
|   | 18db743851 | ||
|   | 0e188e2dc3 | ||
|   | eecb0e969f | ||
|   | bd7d56ec71 | ||
|   | 6f78aaad6f | ||
|   | 89d320c2fd | ||
|   | b809bafb0c | ||
|   | 3b6a1681dc | ||
|   | 9300bb826d | ||
|   | dfe7ee1429 | ||
|   | 841103c776 | ||
|   | 8d2335ca23 | ||
|   | 04064e89c1 | ||
|   | c873375123 | ||
|   | 62d232c131 | ||
|   | 98f7ca7e97 | ||
|   | 4cfbb201c4 | ||
|   | dc016567ce | ||
|   | 96b68c57ce | ||
|   | 158dfe2c5c | ||
|   | 8f5336a2fa | ||
|   | f8a9dbd391 | ||
|   | 016879d477 | ||
|   | c03335ec68 | ||
|   | 894585784c | ||
|   | 33c1f2876b | ||
|   | 00ee5c5cf1 | ||
|   | dadc495540 | ||
|   | eae86ba62d | ||
|   | e9cca79dd1 | ||
|   | 4ba3b6c05a | ||
|   | 187ac69374 | ||
|   | 84ad1569e5 | ||
|   | 45e0a661ce | ||
|   | 4d6ef6297a | ||
|   | b68c52704b | ||
|   | 4f4dc5832d | ||
|   | fbcefc0ce0 | ||
|   | 83f6f58834 | ||
|   | 0a691f8935 | ||
|   | c243d45aad | ||
|   | 8a6dba520b | ||
|   | 32352ed6ad | ||
|   | df69440d05 | ||
|   | 345955e87e | ||
|   | 6f5b46855c | ||
|   | 5f93c5d658 | ||
|   | 7fd84b14d2 | ||
|   | f2403140f9 | ||
|   | f3c9749a40 | ||
|   | 3f6991766f | ||
|   | cfe5f7dbf4 | ||
|   | 5840c918d5 | ||
|   | b0afb00000 | ||
|   | 0b5ae7c80e | ||
|   | 0d55f4e1bc | ||
|   | 86d340af27 | ||
|   | 5c14a7f068 | ||
|   | 2879ffacfa | ||
|   | d89eb55906 | ||
|   | 4a85e60cfe | ||
|   | bfefe2400a | ||
|   | 25c6890375 | ||
|   | eb6314260d | ||
|   | 313c38c9de | ||
|   | ae6096471a | ||
|   | 66ea5c415b | ||
|   | 2481ac358c | ||
|   | c639d725a3 | ||
|   | 857f999353 | ||
|   | 6d9cddc513 | ||
|   | e20e48cbf2 | ||
|   | ee5e2cf6cb | ||
|   | e8313697b6 | ||
|   | 28427b4083 | ||
|   | 131649a121 | ||
|   | 632b3d81d6 | ||
|   | 241aeadc50 | ||
|   | 669e4ca366 | ||
|   | c9617d9f93 | ||
|   | f8986a2b34 | ||
|   | 1b96ce04b2 | ||
|   | f851df88fb | ||
|   | 18c595fde2 | ||
|   | 56abdd07e7 | ||
|   | 7e06c336d6 | ||
|   | 8a4069fb17 | ||
|   | 243ad539fe | ||
|   | 3d60590422 | ||
|   | 08fa4fed70 | ||
|   | 4344fa926a | ||
|   | 61672bde44 | ||
|   | 13dbb41c49 | ||
|   | e5c2354fd5 | ||
|   | 09634f46fb | ||
|   | 0119a93b33 | ||
|   | 9fa42beddc | ||
|   | d6cda9e8ab | ||
|   | 2a7f1425d9 | ||
|   | 900ccc26ae | ||
|   | 01d7bbbebe | ||
|   | 3dc6fc42bf | ||
|   | d2fe616e7e | ||
|   | 316ca865e3 | ||
|   | 812d49db90 | ||
|   | 02370fff3a | ||
|   | e9de8e78f0 | ||
|   | 2eabb7d590 | ||
|   | d707a975f6 | ||
|   | ac487842a1 | ||
|   | 06b6e1d0d2 | ||
|   | b77997e6da | ||
|   | 9e8ced9890 | ||
|   | 698e3bdf82 | ||
|   | 9011fb3f0c | ||
|   | 073b03fab7 | ||
|   | f73f052010 | ||
|   | 97ed1ac905 | ||
|   | 322f0bc2f1 | ||
|   | af4bddf20b | ||
|   | f19efd07e7 | ||
|   | 83f5332536 | ||
|   | 497775024c | ||
|   | ea38a70539 | ||
|   | 5eea336d01 | ||
|   | f3849a7b84 | ||
|   | 1ca6ed7b75 | ||
|   | aa51d3a139 | ||
|   | 64c8909071 | ||
|   | e848942505 | ||
|   | 7e489c42f7 | ||
|   | 75b52f9dcc | ||
|   | 221825aebf | ||
|   | 9d35ad9552 | ||
|   | c4a7ca038e | ||
|   | 84f3b3dd44 | ||
|   | 2ef83136d4 | ||
|   | d737aa19c8 | ||
|   | 78e6683bb0 | ||
|   | 2f9b64ac33 | ||
|   | 6a353049ac | ||
|   | 49e3d803ab | ||
|   | b644ae68c8 | ||
|   | 4ae7b7ea69 | ||
|   | 13a2e32548 | ||
|   | c3b513e75c | ||
|   | a74b36af2a | ||
|   | 1b4dc10393 | ||
|   | 45b6e2dd89 | ||
|   | 6dca35c0e5 | ||
|   | a691e04470 | ||
|   | 3d1a453d88 | ||
|   | d7a39f8f97 | ||
|   | 3c929ff9f6 | ||
|   | 9d957294cb | ||
|   | acf59be7f0 | ||
|   | e7dcc454c6 | ||
|   | 84789e12fb | ||
|   | 460fb12097 | ||
|   | 63d8b3a507 | ||
|   | 90ab65c632 | ||
|   | 34122800b8 | ||
|   | 7f41eab395 | ||
|   | 0192ad65bb | ||
|   | 06c1bea72f | ||
|   | 19a05c908f | ||
|   | bb55293313 | ||
|   | 817ceb09e0 | ||
|   | 1a911f7ec4 | ||
|   | ea464d72e9 | ||
|   | 22adb46a32 | ||
|   | fc99eaa5ae | ||
|   | 4bea91fc67 | ||
|   | 06d1b10cbe | ||
|   | 816b639035 | ||
|   | 8804ffd4fa | ||
|   | 19122c0768 | ||
|   | c346c4c8f9 | ||
|   | bc7d806e3a | ||
|   | 6cf8413e31 | ||
|   | 062e5bfd9c | ||
|   | e4a1888bd0 | ||
|   | 2f1a0bc0bf | ||
|   | 09ddb1d61c | ||
|   | 15f76bf7bb | ||
|   | 36585b5395 | ||
|   | 11baffbff6 | ||
|   | 53333a43a1 | ||
|   | c56f9797e7 | ||
|   | 9281be36d5 | ||
|   | f15a88f2b2 | ||
|   | 5ca96cb844 | ||
|   | 10afe7cf10 | ||
|   | 6972335f50 | ||
|   | d5e2d0b6bf | ||
|   | f34b5fb4d8 | ||
|   | f584312e81 | ||
|   | 0b4557f766 | ||
|   | 204126a5f1 | ||
|   | 2ae3d28f3d | ||
|   | 8a42c2ef8d | ||
|   | e79535bc5e | ||
|   | 4ad8e142da | ||
|   | e3ee73b70c | ||
|   | 70812c2f32 | ||
|   | a64bca68c7 | ||
|   | 67633e1308 | ||
|   | 715ca7c5fe | ||
|   | 001758760b | ||
|   | 2f06265e39 | ||
|   | 432431368f | ||
|   | 4b0028f82d | ||
|   | 8c9236bb2c | ||
|   | 2af0b10c95 | ||
|   | 08adecc9a1 | ||
|   | 015556d74c | ||
|   | 4c40fe64b8 | ||
|   | d20def2046 | ||
|   | d2b36e466a | ||
|   | 27f8c93daf | ||
|   | 058b86e6f3 | ||
|   | 0018d6830e | ||
|   | 59224a31fd | ||
|   | 0994d737c8 | ||
|   | 96749554fd | ||
|   | 785749405f | ||
|   | 7cc00d9a83 | ||
|   | 230e16dc03 | ||
|   | 0ce410a629 | ||
|   | 5d3cbde72e | ||
|   | 8fe8fd2b17 | ||
|   | 0ddc678927 | ||
|   | 51f0b798fa | ||
|   | 6b27703b5f | ||
|   | 045ccb59a4 | ||
|   | 784336deec | ||
|   | eb41e8eebe | ||
|   | 3cd43bbfec | ||
|   | 204e340bcd | ||
|   | 37f2ba7e57 | ||
|   | 09b9fc9009 | ||
|   | 7da3caaf95 | ||
|   | 82ab5f1b0c | ||
|   | 7ae64af368 | ||
|   | 2ad688ed7c | ||
|   | ca786233d2 | ||
|   | 14a3139c4d | ||
|   | 5af2bfb955 | ||
|   | 1691a31cab | ||
|   | 9dedcbf9ec | ||
|   | 537ffc4c69 | ||
|   | c3e7210548 | ||
|   | 9a5c2d8373 | ||
|   | 8693bbd8c4 | ||
|   | 251dd03b88 | ||
|   | 55ea83d622 | ||
|   | b5478a0e03 | ||
|   | db2deba6b4 | ||
|   | 41fb6443ce | ||
|   | e5dfe6c282 | ||
|   | e277e20a6d | ||
|   | a23e56d109 | ||
|   | ca89a0a092 | ||
|   | 50a74be125 | ||
|   | 8c1e3bb713 | ||
|   | 4fad1943a2 | ||
|   | 4d346673a2 | ||
|   | de052ca6fc | ||
|   | 1a593191c2 | ||
|   | 2c4ef997b9 | ||
|   | d020e2c381 | ||
|   | 48fe9226a0 | ||
|   | a77ac42e52 | ||
|   | 5880db8abd | ||
|   | 0f4ba89ffd | ||
|   | edeb1ae65f | ||
|   | 82232bbbaf | ||
|   | bb2e0686ab | ||
|   | 513e587c5e | ||
|   | 6ed2bcc5f5 | ||
|   | d529f3882b | ||
|   | e2e92486a7 | ||
|   | 2e5b3168d6 | ||
|   | 6bcacff1a5 | ||
|   | 12d01cb6fa | ||
|   | 90695fb2c5 | ||
|   | dd17069c9e | ||
|   | 26b0cb6ae2 | ||
|   | 6d30f8ebed | ||
|   | 11220678c4 | ||
|   | 448d55ef0a | ||
|   | 7b115cc1e1 | ||
|   | a10d5e3851 | ||
|   | 1016637f5a | ||
|   | 2e00872c04 | ||
|   | 56ece42c81 | ||
|   | 99924f6606 | ||
|   | 0eba02fd41 | ||
|   | 464c8693d2 | ||
|   | 50af17ef24 | ||
|   | 3a24cb7bc4 | ||
|   | e839446c2a | ||
|   | 695931cf8e | ||
|   | 964a7600b9 | ||
|   | d4492f955d | ||
|   | 9c15325d34 | ||
|   | d8c04909fa | ||
|   | c0a7a98aee | ||
|   | f5005dd8d0 | ||
|   | d3aaa68f55 | ||
|   | cfc907e43d | ||
|   | 2af64c6432 | ||
|   | 83f0dae129 | ||
|   | 65d53cf6ef | ||
|   | 0d9e65f79f | ||
|   | c983aa9efc | ||
|   | b16b7f9d3a | ||
|   | 5c6f12b9f2 | ||
|   | 2022b10e50 | ||
|   | 45339625bc | ||
|   | 20ff820ef2 | ||
|   | 39e85d99fe | ||
|   | 3a0e931fc7 | ||
|   | fe7e3229f8 | ||
|   | ecf042ff3c | ||
|   | aff245b360 | ||
|   | e01469907a | ||
|   | b7a933154a | ||
|   | 54f18e5427 | ||
|   | 833fba265d | ||
|   | d633052905 | ||
|   | 009d2336fe | ||
|   | abca89aaa0 | ||
|   | d689376cb0 | ||
|   | 98b0d66eb4 | ||
|   | 9c2853f2ae | ||
|   | aff7562922 | ||
|   | 365c5ba395 | ||
|   | cb1aa8b0e3 | ||
|   | d3d5c4a40e | ||
|   | 6117d4025e | ||
|   | d23745f7c9 | ||
|   | ad47d8e263 | ||
|   | 8a7a277c08 | ||
|   | 0030fbd382 | ||
|   | f3052c8a81 | ||
|   | 7d80ed64e4 | ||
|   | a2e0ce86ba | ||
|   | 6fab0bd9f1 | ||
|   | 02964ed630 | ||
|   | 6f3e7aabdc | ||
|   | 631e3e13a9 | ||
|   | 832c195179 | ||
|   | 7877619f85 | ||
|   | ec248b590d | ||
|   | 4846b5e9fe | 
							
								
								
									
										11
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | language: c | ||||||
|  |  | ||||||
|  | before_script: | ||||||
|  |   - ./buildconf | ||||||
|  |  | ||||||
|  | compiler: | ||||||
|  |   - clang | ||||||
|  |   - gcc | ||||||
|  |  | ||||||
|  | notifications: | ||||||
|  |   email: false | ||||||
| @@ -108,7 +108,11 @@ if(NOT UNIX) | |||||||
|     set(HAVE_IN_ADDR_T 0) |     set(HAVE_IN_ADDR_T 0) | ||||||
|     set(HAVE_INET_NTOA_R_DECL 0) |     set(HAVE_INET_NTOA_R_DECL 0) | ||||||
|     set(HAVE_INET_NTOA_R_DECL_REENTRANT 0) |     set(HAVE_INET_NTOA_R_DECL_REENTRANT 0) | ||||||
|     set(HAVE_GETADDRINFO 0) |     if(ENABLE_IPV6) | ||||||
|  |       set(HAVE_GETADDRINFO 1) | ||||||
|  |     else() | ||||||
|  |       set(HAVE_GETADDRINFO 0) | ||||||
|  |     endif() | ||||||
|     set(STDC_HEADERS 1) |     set(STDC_HEADERS 1) | ||||||
|     set(RETSIGTYPE_TEST 1) |     set(RETSIGTYPE_TEST 1) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -783,6 +783,17 @@ else() | |||||||
|   set(CURL_SIZEOF_CURL_SOCKLEN_T ${SIZEOF_INT}) |   set(CURL_SIZEOF_CURL_SOCKLEN_T ${SIZEOF_INT}) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | # TODO test which of these headers are required for the typedefs used in curlbuild.h | ||||||
|  | if(WIN32) | ||||||
|  |   set(CURL_PULL_WS2TCPIP_H ${HAVE_WS2TCPIP_H}) | ||||||
|  | else() | ||||||
|  |   set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H}) | ||||||
|  |   set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H}) | ||||||
|  |   set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H}) | ||||||
|  | endif() | ||||||
|  | set(CURL_PULL_STDINT_H ${HAVE_STDINT_H}) | ||||||
|  | set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H}) | ||||||
|  |  | ||||||
| include(CMake/OtherTests.cmake) | include(CMake/OtherTests.cmake) | ||||||
|  |  | ||||||
| add_definitions(-DHAVE_CONFIG_H) | add_definitions(-DHAVE_CONFIG_H) | ||||||
|   | |||||||
| @@ -148,12 +148,24 @@ vc-ssl-zlib: $(VC) | |||||||
| 	cd ..\src | 	cd ..\src | ||||||
| 	nmake /f Makefile.$(VC) cfg=release-ssl-zlib | 	nmake /f Makefile.$(VC) cfg=release-ssl-zlib | ||||||
|  |  | ||||||
|  | vc-winssl-zlib: $(VC) | ||||||
|  | 	cd lib | ||||||
|  | 	nmake /f Makefile.$(VC) cfg=release-winssl-zlib | ||||||
|  | 	cd ..\src | ||||||
|  | 	nmake /f Makefile.$(VC) cfg=release-winssl-zlib | ||||||
|  |  | ||||||
| vc-x64-ssl-zlib: $(VC) | vc-x64-ssl-zlib: $(VC) | ||||||
| 	cd lib | 	cd lib | ||||||
| 	nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-ssl-zlib | 	nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-ssl-zlib | ||||||
| 	cd ..\src | 	cd ..\src | ||||||
| 	nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-ssl-zlib | 	nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-ssl-zlib | ||||||
|  |  | ||||||
|  | vc-x64-winssl-zlib: $(VC) | ||||||
|  | 	cd lib | ||||||
|  | 	nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-winssl-zlib | ||||||
|  | 	cd ..\src | ||||||
|  | 	nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-winssl-zlib | ||||||
|  |  | ||||||
| vc-ssl-dll: $(VC) | vc-ssl-dll: $(VC) | ||||||
| 	cd lib | 	cd lib | ||||||
| 	nmake /f Makefile.$(VC) cfg=release-ssl-dll | 	nmake /f Makefile.$(VC) cfg=release-ssl-dll | ||||||
|   | |||||||
							
								
								
									
										185
									
								
								RELEASE-NOTES
									
									
									
									
									
								
							
							
						
						
									
										185
									
								
								RELEASE-NOTES
									
									
									
									
									
								
							| @@ -1,71 +1,71 @@ | |||||||
| Curl and libcurl 7.31.0 | Curl and libcurl 7.34.0 | ||||||
|  |  | ||||||
|  Public curl releases:         133 |  Public curl releases:         136 | ||||||
|  Command line options:         152 |  Command line options:         161 | ||||||
|  curl_easy_setopt() options:   199 |  curl_easy_setopt() options:   206 | ||||||
|  Public functions in libcurl:  58 |  Public functions in libcurl:  58 | ||||||
|  Known libcurl bindings:       42 |  Known libcurl bindings:       42 | ||||||
|  Contributors:                 1005 |  Contributors:                 1104 | ||||||
|  |  | ||||||
| *** | This release includes the following security fix: | ||||||
|   krb4 support is up for removal. If you care about it at all, speak up |  o gtls: respect *VERIFYHOST independently of *VERIFYPEER [26] | ||||||
|   on the curl-library list asap! |  | ||||||
| *** |  | ||||||
|  |  | ||||||
| This release includes the following changes: | This release includes the following changes: | ||||||
|  |  | ||||||
|  o darwinssl: add TLS session resumption |  o SSL: protocol version can be specified more precisely [1] | ||||||
|  o darwinssl: add TLS crypto authentication |  o imap/pop3/smtp: Added graceful cancellation of SASL authentication | ||||||
|  o imap/pop3/smtp: Added support for ;auth=<mech> in the URL |  o Add "Happy Eyeballs" for IPv4/IPv6 dual connect attempts | ||||||
|  o imap/pop3/smtp: Added support for ;auth=<mech> to CURLOPT_USERPWD |  o base64: Added validation of base64 input strings when decoding [8] | ||||||
|  o usercertinmem.c: add example showing user cert in memory |  o curl_easy_setopt: Added the ability to set the login options separately | ||||||
|  o url: Added smtp and pop3 hostnames to the protocol detection list |  o smtp: Added support for additional SMTP commands | ||||||
|  o imap/pop3/smtp: Added support for enabling the SASL initial response [8] |  o curl_easy_getinfo: Added CURLINFO_TLS_SESSION for accessing TLS internals | ||||||
|  o curl -E: allow to use ':' in certificate nicknames [10] |  o nss: allow to use TLS > 1.0 if built against recent NSS [18] | ||||||
|  |  o SECURITY: added this document to describe our security processes [22] | ||||||
|  |  o parseconfig: warn if unquoted white spaces are detected | ||||||
|  |  | ||||||
| This release includes the following bugfixes: | This release includes the following bugfixes: | ||||||
|  |  | ||||||
|  o SECURITY VULNERABILITY: curl_easy_unescape() may parse data beyond the end |  o darwinssl: un-break iOS build after PKCS#12 feature added | ||||||
|    of the input buffer [26] |  o tool: use XFERFUNCTION to save some casts [2] | ||||||
|  |  o usercertinmem: fix memory leaks | ||||||
|  o FTP: access files in root dir correctly [1] |  o ssh: Handle successful SSH_USERAUTH_NONE [3] | ||||||
|  o configure: try pthread_create without -lpthread [2] |  o NSS: acknowledge the --no-sessionid/CURLOPT_SSL_SESSIONID_CACHE option [4] | ||||||
|  o FTP: handle a 230 welcome response [3] |  o test906: Fixed failing test on some platforms [5] | ||||||
|  o curl-config: don't output static libs when they are disabled |  o sasl: initialize NSS before using NTLM crypto | ||||||
|  o CURL_CHECK_CA_BUNDLE: don't check for paths when cross-compiling [4] |  o sasl: Fixed memory leak in OAUTH2 message creation | ||||||
|  o Various documentation updates |  o imap/pop3/smtp: Fixed QUIT / LOGOUT being sent when SSL connect fails | ||||||
|  o getinfo.c: reset timecond when clearing session-info variables [5] |  o cmake: unbreak for non-Windows platforms [6] | ||||||
|  o FILE: prevent an artificial timeout event due to stale speed-check data [6] |  o ssh: initialize per-handle data in ssh_connect() | ||||||
|  o ftp_state_pasv_resp: connect through proxy also when set by env [7] |  o glob: fix broken URLs | ||||||
|  o sshserver: disable StrictHostKeyChecking |  o configure: check for long long when building with cyassl | ||||||
|  o ftpserver: Fixed imap logout confirmation data |  o CURLOPT_RESOLVE: mention they don't time-out [7] | ||||||
|  o curl_easy_init: use less mallocs |  o docs/examples/httpput.c: fix build for MSVC | ||||||
|  o smtp: Fixed unknown percentage complete in progress bar |  o FTP: make the data connection work when going through proxy | ||||||
|  o smtp: Fixed sending of double CRLF caused by first in EOB |  o NSS: support for CERTINFO feature | ||||||
|  o bindlocal: move brace out of #ifdef [9] |  o curl_multi_wait: accept 0 from multi_timeout() as valid timeout | ||||||
|  o winssl: Fixed invalid memory access during SSL shutdown [11] |  o glob_range: pass the closing bracket for a-z ranges | ||||||
|  o OS X framework: fix invalid symbolic link |  o tool_help: Updated --list-only description to include POP3 | ||||||
|  o OpenSSL: allow empty server certificate subject [12] |  o Curl_ssl_push_certinfo_len: don't %.*s non-zero-terminated string [9] | ||||||
|  o axtls: prevent memleaks on SSL handshake failures |  o cmake: fix Windows build with IPv6 support [10] | ||||||
|  o cookies: only consider full path matches |  o ares: Fixed compilation under Visual Studio 2012 [11] | ||||||
|  o Revert win32 MemoryTracking: wcsdup() _wcsdup() and _tcsdup() [13] |  o curl_easy_setopt.3: clarify CURLOPT_SSL_VERIFYHOST documentation [12] | ||||||
|  o Curl_cookie_add: handle IPv6 hosts [14] |  o curl.1: mention that -O does no URL decoding [13] | ||||||
|  o ossl_send: SSL_write() returning 0 is an error too |  o darwinssl: PKCS#12 import feature now requires Lion or later [14] | ||||||
|  o ossl_recv: SSL_read() returning 0 is an error too |  o darwinssl: check for SSLSetSessionOption() presence when toggling BEAST | ||||||
|  o Digest auth: escape user names with \ or " in them [15] |  o configure: Fix test with -Werror=implicit-function-declaration [15] | ||||||
|  o curl_formadd.3: fixed wrong "end-marker" syntax [16] |  o sigpipe: factor out sigpipe_reset from easy.c | ||||||
|  o libcurl-tutorial.3: fix incorrect backslash [17] |  o curl_multi_cleanup: ignore SIGPIPE | ||||||
|  o curl_multi_wait: reduce timeout if the multi handle wants to [18] |  o globbing: curl glob counter mismatch with {} list use [16] | ||||||
|  o tests/Makefile: typo in the perlcheck target [19] |  o parseconfig: dash options can't specified with colon or equals [17] | ||||||
|  o axtls: honor disabled VERIFYHOST |  o digest: fix CURLAUTH_DIGEST_IE [19] | ||||||
|  o OpenSSL: avoid double free in the PKCS12 certificate code [20] |  o curl.h: <sys/select.h> for OpenBSD [20] | ||||||
|  o multi_socket: reduce timeout inaccuracy margin [21] |  o darwinssl: Fix #if 10.6.0 for SecKeychainSearch | ||||||
|  o digest: support auth-int for empty entity body [22] |  o TFTP: fix return codes for connect timeout [21] | ||||||
|  o axtls: now done non-blocking |  o login options: remove the ;[options] support from CURLOPT_USERPWD [23] | ||||||
|  o lib1900: use tutil_tvnow instead of gettimeofday |  o imap: Fixed incorrect fallback to clear text authentication | ||||||
|  o curl_easy_perform: avoid busy-looping [23] |  o parsedate: avoid integer overflow | ||||||
|  o CURLOPT_COOKIELIST: take cookie share lock [24] |  o curl.1: document -J doesn't %-decode [25] | ||||||
|  o multi_socket: react on socket close immediately [25] |  o multi: add timer inaccuracy margin to timeout/connecttimeout [24] | ||||||
|  |  | ||||||
| This release includes the following known bugs: | This release includes the following known bugs: | ||||||
|  |  | ||||||
| @@ -74,43 +74,42 @@ This release includes the following known bugs: | |||||||
| This release would not have looked like this without help, code, reports and | This release would not have looked like this without help, code, reports and | ||||||
| advice from friends like these: | advice from friends like these: | ||||||
|  |  | ||||||
|  David Strauss, Kamil Dudka, Steve Holme, Nick Zitzmann, Sam Deane, Duncan, |  Alessandro Ghedini, Andreas Rieke, Björn Stenberg, Chris Conlon, | ||||||
|  Anders Havn, Dan Fandrich, Paul Howarth, Dave Reisner, Wouter Van Rooy, |  Christian Grothoff, Christian Weisgerber, Dave Reisner, David Walser, | ||||||
|  Linus Nielsen Feltzing, Ishan SinghLevett, Alessandro Ghedini, |  Dima Tisnek, Fabian Keil, Felix Yan, Gergely Nagy, Gisle Vanem, | ||||||
|  Ludovico Cavedon, Zdenek Pavlas, Zekun Ni, Lars Johannesen, Marc Hoersken, |  Ishan SinghLevett, James Dury, Javier Barroso, Jeff King, Kamil Dudka, | ||||||
|  Renaud Guillard, John Gardiner Myers, Jared Jennings, Eric Hu, |  Kim Vandry, Marcin Gryszkalis, Melissa Mears, Michael Osipov, Nick Zitzmann, | ||||||
|  Yamada Yasuharu, Stefan Neis, Mike Giancola, Eric S. Raymond, Andrii Moiseiev, |  Oliver Kuckertz, Patrick Monnerat, Paul Donohue, Paul Marks, Romulo A. Ceccon, | ||||||
|  Christian Weisgerber, Peter Gal, Aleksey Tulinov, Hang Su, Sergei Nikulov, |  Rémy Léone, Sergey Tatarincev, Steve Holme, Tomas Hoger, Tyler Hall, | ||||||
|  Miguel Angel, Nach M. S., Benjamin Gilbert, Erik Johansson, Timo Sirainen, |  Yaakov Selkowitz, Eric Lubin, Petr Bahula, He Qin, Marc Deslauriers | ||||||
|  Guenter Knauf |  | ||||||
|  |  | ||||||
|         Thanks! (and sorry if I forgot to mention someone) |         Thanks! (and sorry if I forgot to mention someone) | ||||||
|  |  | ||||||
| References to bug reports and discussions on issues: | References to bug reports and discussions on issues: | ||||||
|  |  | ||||||
|  [1] = http://curl.haxx.se/mail/lib-2013-04/0142.html |  [1] = https://github.com/bagder/curl/pull/79 | ||||||
|  [2] = http://curl.haxx.se/bug/view.cgi?id=1216 |  [2] = http://curl.haxx.se/mail/lib-2013-10/0089.html | ||||||
|  [3] = http://curl.haxx.se/mail/lib-2013-02/0102.html |  [3] = http://curl.haxx.se/mail/lib-2013-10/0096.html | ||||||
|  [4] = http://curl.haxx.se/mail/lib-2013-04/0294.html |  [4] = http://curl.haxx.se/mail/lib-2013-10/0113.html | ||||||
|  [5] = http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=705783 |  [5] = http://sourceforge.net/p/curl/bugs/1291 | ||||||
|  [6] = https://bugzilla.redhat.com/906031 |  [6] = http://sourceforge.net/p/curl/bugs/1292 | ||||||
|  [7] = http://curl.haxx.se/bug/view.cgi?id=1218 |  [7] = http://curl.haxx.se/mail/lib-2013-10/0062.html | ||||||
|  [8] = http://curl.haxx.se/mail/lib-2012-03/0114.html |  [8] = http://curl.haxx.se/mail/lib-2013-10/0242.html | ||||||
|  [9] = http://curl.haxx.se/mail/lib-2013-05/0000.html |  [9] = http://curl.haxx.se/bug/view.cgi?id=1295 | ||||||
|  [10] = http://curl.haxx.se/bug/view.cgi?id=1196 |  [10] = http://sourceforge.net/p/curl/bugs/1064 | ||||||
|  [11] = http://curl.haxx.se/bug/view.cgi?id=1219 |  [11] = http://curl.haxx.se/mail/lib-2013-11/0057.html | ||||||
|  [12] = http://curl.haxx.se/bug/view.cgi?id=1220 |  [12] = https://github.com/bagder/curl/pull/83 | ||||||
|  [13] = http://curl.haxx.se/mail/lib-2013-05/0070.html |  [13] = http://sourceforge.net/p/curl/bugs/1299 | ||||||
|  [14] = http://curl.haxx.se/bug/view.cgi?id=1221 |  [14] = http://curl.haxx.se/mail/lib-2013-11/0076.html | ||||||
|  [15] = http://curl.haxx.se/bug/view.cgi?id=1230 |  [15] = http://curl.haxx.se/bug/view.cgi?id=1304 | ||||||
|  [16] = http://curl.haxx.se/bug/view.cgi?id=1233 |  [16] = http://curl.haxx.se/bug/view.cgi?id=1305 | ||||||
|  [17] = http://curl.haxx.se/bug/view.cgi?id=1234 |  [17] = http://curl.haxx.se/bug/view.cgi?id=1297 | ||||||
|  [18] = http://curl.haxx.se/bug/view.cgi?id=1224 |  [18] = http://curl.haxx.se/mail/lib-2013-11/0162.html | ||||||
|  [19] = http://curl.haxx.se/bug/view.cgi?id=1239 |  [19] = http://curl.haxx.se/bug/view.cgi?id=1308 | ||||||
|  [20] = http://curl.haxx.se/bug/view.cgi?id=1236 |  [20] = http://curl.haxx.se/mail/lib-2013-12/0017.html | ||||||
|  [21] = http://curl.haxx.se/bug/view.cgi?id=1228 |  [21] = http://curl.haxx.se/bug/view.cgi?id=1310 | ||||||
|  [22] = http://curl.haxx.se/bug/view.cgi?id=1235 |  [22] = http://curl.haxx.se/dev/security.html | ||||||
|  [23] = http://curl.haxx.se/bug/view.cgi?id=1238 |  [23] = http://curl.haxx.se/bug/view.cgi?id=1311 | ||||||
|  [24] = http://curl.haxx.se/bug/view.cgi?id=1215 |  [24] = http://curl.haxx.se/bug/view.cgi?id=1298 | ||||||
|  [25] = http://curl.haxx.se/bug/view.cgi?id=1248 |  [25] = http://curl.haxx.se/bug/view.cgi?id=1294 | ||||||
|  [26] = http://curl.haxx.se/docs/adv_20130622.html |  [26] = http://curl.haxx.se/docs/adv_20131217.html | ||||||
|   | |||||||
							
								
								
									
										73
									
								
								acinclude.m4
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								acinclude.m4
									
									
									
									
									
								
							| @@ -2619,48 +2619,49 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]), | |||||||
|     fi |     fi | ||||||
|     capath="$want_capath" |     capath="$want_capath" | ||||||
|     ca="no" |     ca="no" | ||||||
|   elif test "x$cross_compiling" != "xyes"; then |   else | ||||||
|     dnl NOT cross-compiling and... |  | ||||||
|     dnl neither of the --with-ca-* options are provided |  | ||||||
|  |  | ||||||
|     dnl first try autodetecting a CA bundle , then a CA path |     dnl first try autodetecting a CA bundle , then a CA path | ||||||
|     dnl both autodetections can be skipped by --without-ca-* |     dnl both autodetections can be skipped by --without-ca-* | ||||||
|     ca="no" |     ca="no" | ||||||
|     capath="no" |     capath="no" | ||||||
|     if test "x$want_ca" = "xunset"; then |     if test "x$cross_compiling" != "xyes"; then | ||||||
|       dnl the path we previously would have installed the curl ca bundle |       dnl NOT cross-compiling and... | ||||||
|       dnl to, and thus we now check for an already existing cert in that place |       dnl neither of the --with-ca-* options are provided | ||||||
|       dnl in case we find no other |       if test "x$want_ca" = "xunset"; then | ||||||
|       if test "x$prefix" != xNONE; then |         dnl the path we previously would have installed the curl ca bundle | ||||||
|         cac="${prefix}/share/curl/curl-ca-bundle.crt" |         dnl to, and thus we now check for an already existing cert in that | ||||||
|       else |         dnl place in case we find no other | ||||||
|         cac="$ac_default_prefix/share/curl/curl-ca-bundle.crt" |         if test "x$prefix" != xNONE; then | ||||||
|       fi |           cac="${prefix}/share/curl/curl-ca-bundle.crt" | ||||||
|  |         else | ||||||
|  |           cac="$ac_default_prefix/share/curl/curl-ca-bundle.crt" | ||||||
|  |         fi | ||||||
|  |  | ||||||
|       for a in /etc/ssl/certs/ca-certificates.crt \ |         for a in /etc/ssl/certs/ca-certificates.crt \ | ||||||
|                /etc/pki/tls/certs/ca-bundle.crt \ |                  /etc/pki/tls/certs/ca-bundle.crt \ | ||||||
|                /usr/share/ssl/certs/ca-bundle.crt \ |                  /usr/share/ssl/certs/ca-bundle.crt \ | ||||||
|                /usr/local/share/certs/ca-root.crt \ |                  /usr/local/share/certs/ca-root.crt \ | ||||||
|                /etc/ssl/cert.pem \ |                  /etc/ssl/cert.pem \ | ||||||
|                "$cac"; do |                  "$cac"; do | ||||||
|         if test -f "$a"; then |           if test -f "$a"; then | ||||||
|           ca="$a" |             ca="$a" | ||||||
|           break |             break | ||||||
|         fi |           fi | ||||||
|       done |         done | ||||||
|  |       fi | ||||||
|  |       if test "x$want_capath" = "xunset" -a "x$ca" = "xno" -a \ | ||||||
|  |               "x$OPENSSL_ENABLED" = "x1"; then | ||||||
|  |         for a in /etc/ssl/certs/; do | ||||||
|  |           if test -d "$a" && ls "$a"/[[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]].0 >/dev/null 2>/dev/null; then | ||||||
|  |             capath="$a" | ||||||
|  |             break | ||||||
|  |           fi | ||||||
|  |         done | ||||||
|  |       fi | ||||||
|  |     else | ||||||
|  |       dnl no option given and cross-compiling | ||||||
|  |       AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling]) | ||||||
|     fi |     fi | ||||||
|     if test "x$want_capath" = "xunset" -a "x$ca" = "xno" -a \ |  | ||||||
|             "x$OPENSSL_ENABLED" = "x1"; then |  | ||||||
|       for a in /etc/ssl/certs/; do |  | ||||||
|         if test -d "$a" && ls "$a"/[[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]].0 >/dev/null 2>/dev/null; then |  | ||||||
|           capath="$a" |  | ||||||
|           break |  | ||||||
|         fi |  | ||||||
|       done |  | ||||||
|     fi |  | ||||||
|   else |  | ||||||
|     dnl no option given and cross-compiling |  | ||||||
|     AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling]) |  | ||||||
|   fi |   fi | ||||||
|  |  | ||||||
|   if test "x$ca" != "xno"; then |   if test "x$ca" != "xno"; then | ||||||
|   | |||||||
							
								
								
									
										211
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										211
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -126,7 +126,7 @@ fi | |||||||
| dnl figure out the libcurl version | dnl figure out the libcurl version | ||||||
| CURLVERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curlver.h` | CURLVERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curlver.h` | ||||||
| XC_CHECK_PROG_CC | XC_CHECK_PROG_CC | ||||||
| AM_INIT_AUTOMAKE | XC_AUTOMAKE | ||||||
| AC_MSG_CHECKING([curl version]) | AC_MSG_CHECKING([curl version]) | ||||||
| AC_MSG_RESULT($CURLVERSION) | AC_MSG_RESULT($CURLVERSION) | ||||||
|  |  | ||||||
| @@ -150,7 +150,6 @@ dnl initialize all the info variables | |||||||
|     curl_ssl_msg="no      (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls,winssl,darwinssl} )" |     curl_ssl_msg="no      (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls,winssl,darwinssl} )" | ||||||
|     curl_ssh_msg="no      (--with-libssh2)" |     curl_ssh_msg="no      (--with-libssh2)" | ||||||
|    curl_zlib_msg="no      (--with-zlib)" |    curl_zlib_msg="no      (--with-zlib)" | ||||||
|    curl_krb4_msg="no      (--with-krb4*)" |  | ||||||
|     curl_gss_msg="no      (--with-gssapi)" |     curl_gss_msg="no      (--with-gssapi)" | ||||||
|  curl_spnego_msg="no      (--with-spnego)" |  curl_spnego_msg="no      (--with-spnego)" | ||||||
| curl_tls_srp_msg="no      (--enable-tls-srp)" | curl_tls_srp_msg="no      (--enable-tls-srp)" | ||||||
| @@ -1066,6 +1065,7 @@ AC_HELP_STRING([--disable-ipv6],[Disable ipv6 support]), | |||||||
|   AC_TRY_RUN([ /* is AF_INET6 available? */ |   AC_TRY_RUN([ /* is AF_INET6 available? */ | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <sys/socket.h> | #include <sys/socket.h> | ||||||
|  | #include <stdlib.h> /* for exit() */ | ||||||
| main() | main() | ||||||
| { | { | ||||||
|  if (socket(AF_INET6, SOCK_STREAM, 0) < 0) |  if (socket(AF_INET6, SOCK_STREAM, 0) < 0) | ||||||
| @@ -1134,101 +1134,6 @@ no) | |||||||
|         ;; |         ;; | ||||||
| esac | esac | ||||||
|  |  | ||||||
| dnl ********************************************************************** |  | ||||||
| dnl Check for the presence of Kerberos4 libraries and headers |  | ||||||
| dnl ********************************************************************** |  | ||||||
|  |  | ||||||
| AC_ARG_WITH(krb4-includes, |  | ||||||
| AC_HELP_STRING([--with-krb4-includes=DIR], |  | ||||||
|                [Specify location of kerberos4 headers]),[ |  | ||||||
|  CPPFLAGS="$CPPFLAGS -I$withval" |  | ||||||
|  KRB4INC="$withval" |  | ||||||
|  want_krb4=yes |  | ||||||
|  ]) |  | ||||||
|  |  | ||||||
| AC_ARG_WITH(krb4-libs, |  | ||||||
| AC_HELP_STRING([--with-krb4-libs=DIR],[Specify location of kerberos4 libs]),[ |  | ||||||
|  LDFLAGS="$LDFLAGS -L$withval" |  | ||||||
|  KRB4LIB="$withval" |  | ||||||
|  want_krb4=yes |  | ||||||
|  ]) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| OPT_KRB4=off |  | ||||||
| AC_ARG_WITH(krb4,dnl |  | ||||||
| AC_HELP_STRING([--with-krb4=DIR],[where to look for Kerberos4]),[ |  | ||||||
|   OPT_KRB4="$withval" |  | ||||||
|   if test X"$OPT_KRB4" != Xno; then |  | ||||||
|     want_krb4="yes" |  | ||||||
|     if test X"$OPT_KRB4" != Xyes; then |  | ||||||
|       LDFLAGS="$LDFLAGS -L$OPT_KRB4/lib$libsuff" |  | ||||||
|       KRB4LIB="$OPT_KRB4/lib$libsuff" |  | ||||||
|       CPPFLAGS="$CPPFLAGS -I$OPT_KRB4/include" |  | ||||||
|       KRB4INC="$OPT_KRB4/include" |  | ||||||
|     fi |  | ||||||
|   fi |  | ||||||
|  ]) |  | ||||||
|  |  | ||||||
| AC_MSG_CHECKING([if Kerberos4 support is requested]) |  | ||||||
|  |  | ||||||
| if test "$want_krb4" = yes |  | ||||||
| then |  | ||||||
|   if test "$ipv6" = "yes"; then |  | ||||||
|     echo krb4 is not compatible with IPv6 |  | ||||||
|     exit 1 |  | ||||||
|   fi |  | ||||||
|   AC_MSG_RESULT(yes) |  | ||||||
|  |  | ||||||
|   dnl Check for & handle argument to --with-krb4 |  | ||||||
|  |  | ||||||
|   AC_MSG_CHECKING(where to look for Kerberos4) |  | ||||||
|   if test X"$OPT_KRB4" = Xyes |  | ||||||
|   then |  | ||||||
|     AC_MSG_RESULT([defaults]) |  | ||||||
|   else |  | ||||||
|     AC_MSG_RESULT([libs in $KRB4LIB, headers in $KRB4INC]) |  | ||||||
|   fi |  | ||||||
|  |  | ||||||
|   dnl Check for DES library |  | ||||||
|   AC_CHECK_LIB(des, des_pcbc_encrypt, |  | ||||||
|   [ |  | ||||||
|     AC_CHECK_HEADERS(des.h) |  | ||||||
|  |  | ||||||
|     dnl resolv lib? |  | ||||||
|     AC_CHECK_FUNC(res_search, , [AC_CHECK_LIB(resolv, res_search)]) |  | ||||||
|  |  | ||||||
|     dnl Check for the Kerberos4 library |  | ||||||
|     AC_CHECK_LIB(krb, krb_net_read, |  | ||||||
|     [ |  | ||||||
|       dnl Check for header files |  | ||||||
|       AC_CHECK_HEADERS(krb.h) |  | ||||||
|  |  | ||||||
|       dnl we found the required libraries, add to LIBS |  | ||||||
|       LIBS="-lkrb -lcom_err -ldes $LIBS" |  | ||||||
|  |  | ||||||
|       dnl Check for function krb_get_our_ip_for_realm |  | ||||||
|       dnl this is needed for NAT networks |  | ||||||
|       AC_CHECK_FUNCS(krb_get_our_ip_for_realm) |  | ||||||
|  |  | ||||||
|       dnl add define KRB4 |  | ||||||
|       AC_DEFINE(HAVE_KRB4, 1, |  | ||||||
|       [if you have the Kerberos4 libraries (including -ldes)]) |  | ||||||
|  |  | ||||||
|       dnl substitute it too! |  | ||||||
|       KRB4_ENABLED=1 |  | ||||||
|       AC_SUBST(KRB4_ENABLED) |  | ||||||
|  |  | ||||||
|       curl_krb4_msg="enabled" |  | ||||||
|  |  | ||||||
|       dnl the krb4 stuff needs a strlcpy() |  | ||||||
|       AC_CHECK_FUNCS(strlcpy) |  | ||||||
|  |  | ||||||
|     ]) |  | ||||||
|   ]) |  | ||||||
| else |  | ||||||
|   AC_MSG_RESULT(no) |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
| dnl Check for FBopenssl(SPNEGO) libraries | dnl Check for FBopenssl(SPNEGO) libraries | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
| @@ -2079,6 +1984,9 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then | |||||||
|     if test "x$USE_CYASSL" = "xyes"; then |     if test "x$USE_CYASSL" = "xyes"; then | ||||||
|       AC_MSG_NOTICE([detected CyaSSL]) |       AC_MSG_NOTICE([detected CyaSSL]) | ||||||
|  |  | ||||||
|  |       dnl cyassl/ctaocrypt/types.h needs SIZEOF_LONG_LONG defined! | ||||||
|  |       AC_CHECK_SIZEOF(long long) | ||||||
|  |  | ||||||
|       LIBS="-lcyassl -lm $LIBS" |       LIBS="-lcyassl -lm $LIBS" | ||||||
|  |  | ||||||
|       if test -n "$cyassllib"; then |       if test -n "$cyassllib"; then | ||||||
| @@ -2163,8 +2071,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then | |||||||
|          CPPFLAGS="$CPPFLAGS $addcflags" |          CPPFLAGS="$CPPFLAGS $addcflags" | ||||||
|       fi |       fi | ||||||
|  |  | ||||||
|       dnl The function PK11_CreateGenericObject is needed to load libnsspem.so |       dnl The function SSL_VersionRangeSet() is needed to enable TLS > 1.0 | ||||||
|       AC_CHECK_LIB(nss3, PK11_CreateGenericObject, |       AC_CHECK_LIB(nss3, SSL_VersionRangeSet, | ||||||
|        [ |        [ | ||||||
|        AC_DEFINE(USE_NSS, 1, [if NSS is enabled]) |        AC_DEFINE(USE_NSS, 1, [if NSS is enabled]) | ||||||
|        AC_SUBST(USE_NSS, [1]) |        AC_SUBST(USE_NSS, [1]) | ||||||
| @@ -2180,14 +2088,6 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then | |||||||
|       if test "x$USE_NSS" = "xyes"; then |       if test "x$USE_NSS" = "xyes"; then | ||||||
|         AC_MSG_NOTICE([detected NSS version $version]) |         AC_MSG_NOTICE([detected NSS version $version]) | ||||||
|  |  | ||||||
|         dnl NSS_InitContext() was introduced in NSS 3.12.5 and helps to prevent |  | ||||||
|         dnl collisions on NSS initialization/shutdown with other libraries |  | ||||||
|         AC_CHECK_FUNC(NSS_InitContext, |  | ||||||
|         [ |  | ||||||
|           AC_DEFINE(HAVE_NSS_INITCONTEXT, 1, [if you have the NSS_InitContext function]) |  | ||||||
|           AC_SUBST(HAVE_NSS_INITCONTEXT, [1]) |  | ||||||
|         ]) |  | ||||||
|  |  | ||||||
|         dnl when shared libs were found in a path that the run-time |         dnl when shared libs were found in a path that the run-time | ||||||
|         dnl linker doesn't search through, we need to add it to |         dnl linker doesn't search through, we need to add it to | ||||||
|         dnl LD_LIBRARY_PATH to prevent further configure tests to fail |         dnl LD_LIBRARY_PATH to prevent further configure tests to fail | ||||||
| @@ -2808,6 +2708,92 @@ dnl http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/ \ | |||||||
| dnl genprogc/thread_quick_ref.htm | dnl genprogc/thread_quick_ref.htm | ||||||
|  |  | ||||||
|  |  | ||||||
|  | dnl ********************************************************************** | ||||||
|  | dnl Check for nghttp2 | ||||||
|  | dnl ********************************************************************** | ||||||
|  |  | ||||||
|  | AC_MSG_CHECKING([whether to build with nghttp2]) | ||||||
|  | OPT_H2="no" | ||||||
|  | AC_ARG_WITH(nghttp2, | ||||||
|  | AC_HELP_STRING([--with-nghttp2=PATH],[Enable nghttp2 usage]) | ||||||
|  | AC_HELP_STRING([--without-nghttp2],[Disable nghttp2 usage]), | ||||||
|  |   [OPT_H2=$withval]) | ||||||
|  | case "$OPT_H2" in | ||||||
|  |   no) | ||||||
|  |     dnl --without-nghttp2 option used | ||||||
|  |     want_idn="no" | ||||||
|  |     AC_MSG_RESULT([no]) | ||||||
|  |     ;; | ||||||
|  |   default) | ||||||
|  |     dnl configure option not specified | ||||||
|  |     want_h2="no" | ||||||
|  |     want_h2_path="default" | ||||||
|  |     AC_MSG_RESULT([no]) | ||||||
|  |     ;; | ||||||
|  |   yes) | ||||||
|  |     dnl --with-nghttp2 option used without path | ||||||
|  |     want_h2="yes" | ||||||
|  |     want_h2_path="" | ||||||
|  |     AC_MSG_RESULT([yes]) | ||||||
|  |     ;; | ||||||
|  |   *) | ||||||
|  |     dnl --with-nghttp2 option used with path | ||||||
|  |     want_h2="yes" | ||||||
|  |     want_h2_path="$withval" | ||||||
|  |     AC_MSG_RESULT([yes ($withval)]) | ||||||
|  |     ;; | ||||||
|  | esac | ||||||
|  |  | ||||||
|  | curl_h2_msg="disabled (--with-nghttp2)" | ||||||
|  | if test X"$OPT_H2" != Xno; then | ||||||
|  |   dnl backup the pre-librtmp variables | ||||||
|  |   CLEANLDFLAGS="$LDFLAGS" | ||||||
|  |   CLEANCPPFLAGS="$CPPFLAGS" | ||||||
|  |   CLEANLIBS="$LIBS" | ||||||
|  |  | ||||||
|  |   h2pcdir=${want_h2_path}/lib/pkgconfig | ||||||
|  |   CURL_CHECK_PKGCONFIG(libnghttp2, $h2pcdir) | ||||||
|  |  | ||||||
|  |   if test "$PKGCONFIG" != "no" ; then | ||||||
|  |     LIB_H2=`CURL_EXPORT_PCDIR([$h2pcdir]) | ||||||
|  |       $PKGCONFIG --libs-only-l libnghttp2` | ||||||
|  |     AC_MSG_NOTICE([-l is $LIB_H2]) | ||||||
|  |  | ||||||
|  |     CPP_H2=`CURL_EXPORT_PCDIR([$h2pcdir]) dnl | ||||||
|  |       $PKGCONFIG --cflags-only-I libnghttp2` | ||||||
|  |     AC_MSG_NOTICE([-I is $CPP_H2]) | ||||||
|  |  | ||||||
|  |     LD_H2=`CURL_EXPORT_PCDIR([$h2pcdir]) | ||||||
|  |       $PKGCONFIG --libs-only-L libnghttp2` | ||||||
|  |     AC_MSG_NOTICE([-L is $LD_H2]) | ||||||
|  |  | ||||||
|  |   else | ||||||
|  |     dnl To avoid link errors, we do not allow --libnghttp2 without | ||||||
|  |     dnl a pkgconfig file | ||||||
|  |     AC_MSG_ERROR([--with-nghttp2 was specified but could not find libnghttp2 pkg-config file.]) | ||||||
|  |   fi | ||||||
|  |  | ||||||
|  |   LDFLAGS="$LDFLAGS $LD_H2" | ||||||
|  |   CPPFLAGS="$CPPFLAGS $CPP_H2" | ||||||
|  |   LIBS="$LIB_H2 $LIBS" | ||||||
|  |  | ||||||
|  |   AC_CHECK_LIB(nghttp2, nghttp2_session_client_new, | ||||||
|  |     [ | ||||||
|  |      AC_CHECK_HEADERS(nghttp2/nghttp2.h, | ||||||
|  |         curl_h2_msg="enabled (nghttp2)" | ||||||
|  |         NGHTTP2_ENABLED=1 | ||||||
|  |         AC_DEFINE(USE_NGHTTP2, 1, [if nghttp2 is in use]) | ||||||
|  |         AC_SUBST(USE_NGHTTP2, [1]) | ||||||
|  |      ) | ||||||
|  |     ], | ||||||
|  |       dnl not found, revert back to clean variables | ||||||
|  |       LDFLAGS=$CLEANLDFLAGS | ||||||
|  |       CPPFLAGS=$CLEANCPPFLAGS | ||||||
|  |       LIBS=$CLEANLIBS | ||||||
|  |   ) | ||||||
|  |  | ||||||
|  | fi | ||||||
|  |  | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
| dnl Back to "normal" configuring | dnl Back to "normal" configuring | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
| @@ -3365,9 +3351,6 @@ if test "x$USE_SSLEAY" = "x1"; then | |||||||
| elif test -n "$SSL_ENABLED"; then | elif test -n "$SSL_ENABLED"; then | ||||||
|   SUPPORT_FEATURES="$SUPPORT_FEATURES SSL" |   SUPPORT_FEATURES="$SUPPORT_FEATURES SSL" | ||||||
| fi | fi | ||||||
| if test "@KRB4_ENABLED@" = "x1"; then |  | ||||||
|   SUPPORT_FEATURES="$SUPPORT_FEATURES KRB4" |  | ||||||
| fi |  | ||||||
| if test "x$IPV6_ENABLED" = "x1"; then | if test "x$IPV6_ENABLED" = "x1"; then | ||||||
|   SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6" |   SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6" | ||||||
| fi | fi | ||||||
| @@ -3397,6 +3380,10 @@ if test "x$USE_TLS_SRP" = "x1"; then | |||||||
|   SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP" |   SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP" | ||||||
| fi | fi | ||||||
|  |  | ||||||
|  | if test "x$USE_NGHTTP2" = "x1"; then | ||||||
|  |   SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2" | ||||||
|  | fi | ||||||
|  |  | ||||||
| AC_SUBST(SUPPORT_FEATURES) | AC_SUBST(SUPPORT_FEATURES) | ||||||
|  |  | ||||||
| dnl For supported protocols in pkg-config file | dnl For supported protocols in pkg-config file | ||||||
| @@ -3531,6 +3518,8 @@ AC_OUTPUT | |||||||
|  |  | ||||||
| CURL_GENERATE_CONFIGUREHELP_PM | CURL_GENERATE_CONFIGUREHELP_PM | ||||||
|  |  | ||||||
|  | XC_AMEND_DISTCLEAN([lib src tests/unit tests/server tests/libtest docs/examples]) | ||||||
|  |  | ||||||
| AC_MSG_NOTICE([Configured to build curl/libcurl: | AC_MSG_NOTICE([Configured to build curl/libcurl: | ||||||
|  |  | ||||||
|   curl version:     ${CURLVERSION} |   curl version:     ${CURLVERSION} | ||||||
| @@ -3540,7 +3529,6 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: | |||||||
|   SSL support:      ${curl_ssl_msg} |   SSL support:      ${curl_ssl_msg} | ||||||
|   SSH support:      ${curl_ssh_msg} |   SSH support:      ${curl_ssh_msg} | ||||||
|   zlib support:     ${curl_zlib_msg} |   zlib support:     ${curl_zlib_msg} | ||||||
|   krb4 support:     ${curl_krb4_msg} |  | ||||||
|   GSSAPI support:   ${curl_gss_msg} |   GSSAPI support:   ${curl_gss_msg} | ||||||
|   SPNEGO support:   ${curl_spnego_msg} |   SPNEGO support:   ${curl_spnego_msg} | ||||||
|   TLS-SRP support:  ${curl_tls_srp_msg} |   TLS-SRP support:  ${curl_tls_srp_msg} | ||||||
| @@ -3559,6 +3547,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: | |||||||
|   RTSP support:     ${curl_rtsp_msg} |   RTSP support:     ${curl_rtsp_msg} | ||||||
|   RTMP support:     ${curl_rtmp_msg} |   RTMP support:     ${curl_rtmp_msg} | ||||||
|   metalink support: ${curl_mtlnk_msg} |   metalink support: ${curl_mtlnk_msg} | ||||||
|  |   HTTP2 support:    ${curl_h2_msg} | ||||||
|   Protocols:        ${SUPPORT_PROTOCOLS} |   Protocols:        ${SUPPORT_PROTOCOLS} | ||||||
| ]) | ]) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								contributors.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										46
									
								
								contributors.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | #!/bin/sh | ||||||
|  | #*************************************************************************** | ||||||
|  | #                                  _   _ ____  _ | ||||||
|  | #  Project                     ___| | | |  _ \| | | ||||||
|  | #                             / __| | | | |_) | | | ||||||
|  | #                            | (__| |_| |  _ <| |___ | ||||||
|  | #                             \___|\___/|_| \_\_____| | ||||||
|  | # | ||||||
|  | # Copyright (C) 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  | # | ||||||
|  | # This software is licensed as described in the file COPYING, which | ||||||
|  | # you should have received as part of this distribution. The terms | ||||||
|  | # are also available at http://curl.haxx.se/docs/copyright.html. | ||||||
|  | # | ||||||
|  | # You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  | # copies of the Software, and permit persons to whom the Software is | ||||||
|  | # furnished to do so, under the terms of the COPYING file. | ||||||
|  | # | ||||||
|  | # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  | # KIND, either express or implied. | ||||||
|  | # | ||||||
|  | ########################################################################### | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # This script shows all mentioned contributors from <hash> until HEAD. To aid | ||||||
|  | # when writing RELEASE-NOTES and THANKS. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | start=$1 | ||||||
|  |  | ||||||
|  | if test -z "$start"; then | ||||||
|  |   echo "Usage: $0 <since this tag/hash>" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # filter out Author:, Commit: and *by: lines | ||||||
|  | # cut off the email parts | ||||||
|  | # cut off spaces first and last on the line | ||||||
|  | # only count names with a space (ie more than one word) | ||||||
|  | # sort all unique names | ||||||
|  | git log $start..HEAD | \ | ||||||
|  | egrep '(Author|Commit|by):' | \ | ||||||
|  | cut -d: -f2- | \ | ||||||
|  | cut '-d<' -f1 | \ | ||||||
|  | sed -e 's/^ //' -e 's/ $//g' | \ | ||||||
|  | grep ' ' | \ | ||||||
|  | sort -u | ||||||
| @@ -155,12 +155,12 @@ while test $# -gt 0; do | |||||||
|         ;; |         ;; | ||||||
|  |  | ||||||
|     --static-libs) |     --static-libs) | ||||||
| 	if test "X@ENABLE_STATIC@" != "Xno" ; then |         if test "X@ENABLE_STATIC@" != "Xno" ; then | ||||||
| 		echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@ |           echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@ | ||||||
| 	else |         else | ||||||
| 		echo "curl was built with static libraries disabled" >&2 |           echo "curl was built with static libraries disabled" >&2 | ||||||
| 		exit 1 |           exit 1 | ||||||
| 	fi |         fi | ||||||
|         ;; |         ;; | ||||||
|  |  | ||||||
|     --configure) |     --configure) | ||||||
|   | |||||||
| @@ -79,9 +79,9 @@ | |||||||
| 1.3 What To Read | 1.3 What To Read | ||||||
|  |  | ||||||
|  Source code, the man pages, the INTERNALS document, TODO, KNOWN_BUGS, the |  Source code, the man pages, the INTERNALS document, TODO, KNOWN_BUGS, the | ||||||
|  most recent CHANGES. Just lurking on the libcurl mailing list is gonna give |  most recent CHANGES. Just lurking on the curl-library mailing list is gonna | ||||||
|  you a lot of insights on what's going on right now. Asking there is a good |  give you a lot of insights on what's going on right now. Asking there is a | ||||||
|  idea too. |  good idea too. | ||||||
|  |  | ||||||
| 2. cURL Coding Standards | 2. cURL Coding Standards | ||||||
|  |  | ||||||
| @@ -98,12 +98,12 @@ | |||||||
|  |  | ||||||
| 2.2 Indenting | 2.2 Indenting | ||||||
|  |  | ||||||
|  Please try using the same indenting levels and bracing method as all the |  Use the same indenting levels and bracing method as all the other code | ||||||
|  other code already does. It makes the source code a lot easier to follow if |  already does. It makes the source code easier to follow if all of it is | ||||||
|  all of it is written using the same style. We don't ask you to like it, we |  written using the same style. We don't ask you to like it, we just ask you to | ||||||
|  just ask you to follow the tradition! ;-) This mainly means: 2-level indents, |  follow the tradition! ;-) This mainly means: 2-level indents, using spaces | ||||||
|  using spaces only (no tabs) and having the opening brace ({) on the same line |  only (no tabs) and having the opening brace ({) on the same line as the if() | ||||||
|  as the if() or while(). |  or while(). | ||||||
|  |  | ||||||
|  Also note that we use if() and while() with no space before the parenthesis. |  Also note that we use if() and while() with no space before the parenthesis. | ||||||
|  |  | ||||||
| @@ -151,6 +151,9 @@ | |||||||
|  description exactly what they correct so that all patches can be selectively |  description exactly what they correct so that all patches can be selectively | ||||||
|  applied by the maintainer or other interested parties. |  applied by the maintainer or other interested parties. | ||||||
|  |  | ||||||
|  |  Also, separate patches enable bisecting much better when we track problems in | ||||||
|  |  the future. | ||||||
|  |  | ||||||
| 2.9 Patch Against Recent Sources | 2.9 Patch Against Recent Sources | ||||||
|  |  | ||||||
|  Please try to get the latest available sources to make your patches |  Please try to get the latest available sources to make your patches | ||||||
| @@ -178,6 +181,10 @@ | |||||||
|  test case that verifies that it works as documented. If every submitter also |  test case that verifies that it works as documented. If every submitter also | ||||||
|  posts a few test cases, it won't end up as a heavy burden on a single person! |  posts a few test cases, it won't end up as a heavy burden on a single person! | ||||||
|  |  | ||||||
|  |  If you don't have test cases or perhaps you have done something that is very | ||||||
|  |  hard to write tests for, do explain exactly how you have otherwise tested and | ||||||
|  |  verified your changes. | ||||||
|  |  | ||||||
| 3. Pushing Out Your Changes | 3. Pushing Out Your Changes | ||||||
|  |  | ||||||
| 3.1 Write Access to git Repository | 3.1 Write Access to git Repository | ||||||
|   | |||||||
							
								
								
									
										130
									
								
								docs/FAQ
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								docs/FAQ
									
									
									
									
									
								
							| @@ -202,27 +202,25 @@ FAQ | |||||||
|   better. We do however believe in a few rules when it comes to the future of |   better. We do however believe in a few rules when it comes to the future of | ||||||
|   curl: |   curl: | ||||||
|  |  | ||||||
|   * Curl -- the command line tool -- is to remain a non-graphical command line |   Curl -- the command line tool -- is to remain a non-graphical command line | ||||||
|     tool. If you want GUIs or fancy scripting capabilities, you should look |   tool. If you want GUIs or fancy scripting capabilities, you should look for | ||||||
|     for another tool that uses libcurl. |   another tool that uses libcurl. | ||||||
|  |  | ||||||
|   * We do not add things to curl that other small and available tools already |   We do not add things to curl that other small and available tools already do | ||||||
|     do very fine at the side. Curl's output is fine to pipe into another |   very fine at the side. Curl's output is fine to pipe into another program or | ||||||
|     program or redirect to another file for the next program to interpret. |   redirect to another file for the next program to interpret. | ||||||
|  |  | ||||||
|   * We focus on protocol related issues and improvements. If you wanna do more |   We focus on protocol related issues and improvements. If you wanna do more | ||||||
|     magic with the supported protocols than curl currently does, chances are |   magic with the supported protocols than curl currently does, chances are big | ||||||
|     big we will agree. If you wanna add more protocols, we may very well |   we will agree. If you wanna add more protocols, we may very well agree. | ||||||
|     agree. |  | ||||||
|  |  | ||||||
|   * If you want someone else to make all the work while you wait for us to |   If you want someone else to make all the work while you wait for us to | ||||||
|     implement it for you, that is not a very friendly attitude. We spend a |   implement it for you, that is not a very friendly attitude. We spend a | ||||||
|     considerable time already on maintaining and developing curl. In order to |   considerable time already on maintaining and developing curl. In order to | ||||||
|     get more out of us, you should consider trading in some of your time and |   get more out of us, you should consider trading in some of your time and | ||||||
|     efforts in return. |   efforts in return. | ||||||
|  |  | ||||||
|   * If you write the code, chances are bigger that it will get into curl |   If you write the code, chances are bigger that it will get into curl faster. | ||||||
|     faster. |  | ||||||
|  |  | ||||||
|   1.5 Who makes curl? |   1.5 Who makes curl? | ||||||
|  |  | ||||||
| @@ -263,7 +261,7 @@ FAQ | |||||||
|  |  | ||||||
|   Our project name curl has been in effective use since 1998. We were not the |   Our project name curl has been in effective use since 1998. We were not the | ||||||
|   first computer related project to use the name "curl" and do not claim any |   first computer related project to use the name "curl" and do not claim any | ||||||
|   first-hand rights to the name. |   rights to the name. | ||||||
|  |  | ||||||
|   We recognize that we will be living in parallel with curl.com and wish them |   We recognize that we will be living in parallel with curl.com and wish them | ||||||
|   every success. |   every success. | ||||||
| @@ -620,15 +618,15 @@ FAQ | |||||||
|  |  | ||||||
|   Some workarounds usually suggested to overcome this Javascript dependency: |   Some workarounds usually suggested to overcome this Javascript dependency: | ||||||
|  |  | ||||||
|   - Depending on the Javascript complexity, write up a script that |   Depending on the Javascript complexity, write up a script that translates it | ||||||
|     translates it to another language and execute that. |   to another language and execute that. | ||||||
|  |  | ||||||
|   - Read the Javascript code and rewrite the same logic in another language. |   Read the Javascript code and rewrite the same logic in another language. | ||||||
|  |  | ||||||
|   - Implement a Javascript interpreter, people have successfully used the |   Implement a Javascript interpreter, people have successfully used the | ||||||
|     Mozilla Javascript engine in the past. |   Mozilla Javascript engine in the past. | ||||||
|  |  | ||||||
|   - Ask your admins to stop this, for a static proxy setup or similar. |   Ask your admins to stop this, for a static proxy setup or similar. | ||||||
|  |  | ||||||
|   3.15 Can I do recursive fetches with curl? |   3.15 Can I do recursive fetches with curl? | ||||||
|  |  | ||||||
| @@ -644,34 +642,38 @@ FAQ | |||||||
|   There are three different kinds of "certificates" to keep track of when we |   There are three different kinds of "certificates" to keep track of when we | ||||||
|   talk about using SSL-based protocols (HTTPS or FTPS) using curl or libcurl. |   talk about using SSL-based protocols (HTTPS or FTPS) using curl or libcurl. | ||||||
|  |  | ||||||
|   - Client certificate. The server you communicate may require that you can |   CLIENT CERTIFICATE | ||||||
|     provide this in order to prove that you actually are who you claim to be. |  | ||||||
|     If the server doesn't require this, you don't need a client certificate. |  | ||||||
|  |  | ||||||
|     A client certificate is always used together with a private key, and the |   The server you communicate may require that you can provide this in order to | ||||||
|     private key has a pass phrase that protects it. |   prove that you actually are who you claim to be.  If the server doesn't | ||||||
|  |   require this, you don't need a client certificate. | ||||||
|  |  | ||||||
|   - Server certificate. The server you communicate with has a server |   A client certificate is always used together with a private key, and the | ||||||
|     certificate. You can and should verify this certificate to make sure that |   private key has a pass phrase that protects it. | ||||||
|     you are truly talking to the real server and not a server impersonating |  | ||||||
|     it. |  | ||||||
|  |  | ||||||
|   - Certificate Authority certificate ("CA cert"). You often have several CA |   SERVER CERTIFICATE | ||||||
|     certs in a CA cert bundle that can be used to verify a server certificate |  | ||||||
|     that was signed by one of the authorities in the bundle. curl does not |  | ||||||
|     come with a CA cert bundle but most curl installs provide one. You can |  | ||||||
|     also override the default. |  | ||||||
|  |  | ||||||
|     The server certificate verification process is made by using a Certificate |   The server you communicate with has a server certificate. You can and should | ||||||
|     Authority certificate ("CA cert") that was used to sign the server |   verify this certificate to make sure that you are truly talking to the real | ||||||
|     certificate. Server certificate verification is enabled by default in curl |   server and not a server impersonating it. | ||||||
|     and libcurl and is often the reason for problems as explained in FAQ entry |  | ||||||
|     4.12 and the SSLCERTS document |   CERTIFICATE AUTHORITY CERTIFICATE ("CA cert") | ||||||
|     (http://curl.haxx.se/docs/sslcerts.html). Server certificates that are |  | ||||||
|     "self-signed" or otherwise signed by a CA that you do not have a CA cert |   You often have several CA certs in a CA cert bundle that can be used to | ||||||
|     for, cannot be verified. If the verification during a connect fails, you |   verify a server certificate that was signed by one of the authorities in the | ||||||
|     are refused access. You then need to explicitly disable the verification |   bundle. curl does not come with a CA cert bundle but most curl installs | ||||||
|     to connect to the server. |   provide one. You can also override the default. | ||||||
|  |  | ||||||
|  |   The server certificate verification process is made by using a Certificate | ||||||
|  |   Authority certificate ("CA cert") that was used to sign the server | ||||||
|  |   certificate. Server certificate verification is enabled by default in curl | ||||||
|  |   and libcurl and is often the reason for problems as explained in FAQ entry | ||||||
|  |   4.12 and the SSLCERTS document | ||||||
|  |   (http://curl.haxx.se/docs/sslcerts.html). Server certificates that are | ||||||
|  |   "self-signed" or otherwise signed by a CA that you do not have a CA cert | ||||||
|  |   for, cannot be verified. If the verification during a connect fails, you are | ||||||
|  |   refused access. You then need to explicitly disable the verification to | ||||||
|  |   connect to the server. | ||||||
|  |  | ||||||
|   3.17 How do I list the root dir of an FTP server? |   3.17 How do I list the root dir of an FTP server? | ||||||
|  |  | ||||||
| @@ -794,12 +796,13 @@ FAQ | |||||||
|  |  | ||||||
|      curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl' |      curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl' | ||||||
|  |  | ||||||
|   In Windows, the standard DOS shell treats the %-symbol specially and you |   In Windows, the standard DOS shell treats the percent sign specially and you | ||||||
|   need to use TWO %-symbols for each single one you want to use in the URL. |   need to use TWO percent signs for each single one you want to use in the | ||||||
|  |   URL. | ||||||
|  |  | ||||||
|   Also note that if you want the literal %-symbol to be part of the data you |   If you want a literal percent sign to be part of the data you pass in a POST | ||||||
|   pass in a POST using -d/--data you must encode it as '%25' (which then also |   using -d/--data you must encode it as '%25' (which then also needs the | ||||||
|   needs the %-symbol doubled on Windows machines). |   percent sign doubled on Windows machines). | ||||||
|  |  | ||||||
|   4.3 How can I use {, }, [ or ] to specify multiple URLs? |   4.3 How can I use {, }, [ or ] to specify multiple URLs? | ||||||
|  |  | ||||||
| @@ -968,13 +971,13 @@ FAQ | |||||||
|   4.14 Redirects work in browser but not with curl! |   4.14 Redirects work in browser but not with curl! | ||||||
|  |  | ||||||
|   curl supports HTTP redirects fine (see item 3.8). Browsers generally support |   curl supports HTTP redirects fine (see item 3.8). Browsers generally support | ||||||
|   at least two other ways to perform directs that curl does not: |   at least two other ways to perform redirects that curl does not: | ||||||
|  |  | ||||||
|   - Meta tags. You can write a HTML tag that will cause the browser to |   Meta tags. You can write a HTML tag that will cause the browser to redirect | ||||||
|     redirect to another given URL after a certain time. |   to another given URL after a certain time. | ||||||
|  |  | ||||||
|   - Javascript. You can write a Javascript program embedded in a HTML page |   Javascript. You can write a Javascript program embedded in a HTML page that | ||||||
|     that redirects the browser to another given URL. |   redirects the browser to another given URL. | ||||||
|  |  | ||||||
|   There is no way to make curl follow these redirects. You must either |   There is no way to make curl follow these redirects. You must either | ||||||
|   manually figure out what the page is set to do, or you write a script that |   manually figure out what the page is set to do, or you write a script that | ||||||
| @@ -1270,17 +1273,18 @@ FAQ | |||||||
|  |  | ||||||
|   5.12 Can I make libcurl fake or hide my real IP address? |   5.12 Can I make libcurl fake or hide my real IP address? | ||||||
|  |  | ||||||
|   No. libcurl operates on a higher level than so. Besides, faking IP address |   No. libcurl operates on a higher level. Besides, faking IP address would | ||||||
|   would imply sending IP packages with a made-up source address, and then you |   imply sending IP packet with a made-up source address, and then you normally | ||||||
|   normally get a problem with intercepting the packages sent back as they |   get a problem with receiving the packet sent back as they would then not be | ||||||
|   would then not be routed to you! |   routed to you! | ||||||
|  |  | ||||||
|   If you use a proxy to access remote sites, the sites will not see your local |   If you use a proxy to access remote sites, the sites will not see your local | ||||||
|   IP address but instead the address of the proxy. |   IP address but instead the address of the proxy. | ||||||
|  |  | ||||||
|   Also note that on many networks NATs or other IP-munging techniques are used |   Also note that on many networks NATs or other IP-munging techniques are used | ||||||
|   that makes you see and use a different IP address locally than what the |   that makes you see and use a different IP address locally than what the | ||||||
|   remote server will see you coming from. |   remote server will see you coming from. You may also consider using | ||||||
|  |   http://www.torproject.org . | ||||||
|  |  | ||||||
|   5.13 How do I stop an ongoing transfer? |   5.13 How do I stop an ongoing transfer? | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1045,7 +1045,7 @@ PORTS | |||||||
|         - Alpha OpenVMS V7.1-1H2 |         - Alpha OpenVMS V7.1-1H2 | ||||||
|         - Alpha Tru64 v5.0 5.1 |         - Alpha Tru64 v5.0 5.1 | ||||||
|         - AVR32 Linux |         - AVR32 Linux | ||||||
|         - ARM Android 1.5, 2.1 |         - ARM Android 1.5, 2.1, 2.3, 3.2, 4.x | ||||||
|         - ARM INTEGRITY |         - ARM INTEGRITY | ||||||
|         - ARM iOS |         - ARM iOS | ||||||
|         - Cell Linux |         - Cell Linux | ||||||
| @@ -1116,6 +1116,7 @@ GNU GSS      http://www.gnu.org/software/gss/ | |||||||
| GnuTLS       http://www.gnu.org/software/gnutls/ | GnuTLS       http://www.gnu.org/software/gnutls/ | ||||||
| Heimdal      http://www.pdc.kth.se/heimdal/ | Heimdal      http://www.pdc.kth.se/heimdal/ | ||||||
| libidn       http://www.gnu.org/software/libidn/ | libidn       http://www.gnu.org/software/libidn/ | ||||||
|  | libmetalink  https://launchpad.net/libmetalink/ | ||||||
| libssh2      http://www.libssh2.org/ | libssh2      http://www.libssh2.org/ | ||||||
| MIT Kerberos http://web.mit.edu/kerberos/www/dist/ | MIT Kerberos http://web.mit.edu/kerberos/www/dist/ | ||||||
| NSS          http://www.mozilla.org/projects/security/pki/nss/ | NSS          http://www.mozilla.org/projects/security/pki/nss/ | ||||||
|   | |||||||
							
								
								
									
										115
									
								
								docs/INTERNALS
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								docs/INTERNALS
									
									
									
									
									
								
							| @@ -43,7 +43,7 @@ Portability | |||||||
|  openldap     2.0 |  openldap     2.0 | ||||||
|  MIT krb5 lib 1.2.4 |  MIT krb5 lib 1.2.4 | ||||||
|  qsossl       V5R3M0 |  qsossl       V5R3M0 | ||||||
|  NSS          3.12.x |  NSS          3.14.x | ||||||
|  axTLS        1.2.7 |  axTLS        1.2.7 | ||||||
|  Heimdal      ? |  Heimdal      ? | ||||||
|  |  | ||||||
| @@ -111,6 +111,9 @@ Windows vs Unix | |||||||
| Library | Library | ||||||
| ======= | ======= | ||||||
|  |  | ||||||
|  |  (See LIBCURL-STRUCTS for a separate document describing all major internal | ||||||
|  |  structs and their purposes.) | ||||||
|  |  | ||||||
|  There are plenty of entry points to the library, namely each publicly defined |  There are plenty of entry points to the library, namely each publicly defined | ||||||
|  function that libcurl offers to applications. All of those functions are |  function that libcurl offers to applications. All of those functions are | ||||||
|  rather small and easy-to-follow. All the ones prefixed with 'curl_easy' are |  rather small and easy-to-follow. All the ones prefixed with 'curl_easy' are | ||||||
| @@ -135,16 +138,18 @@ Library | |||||||
|  options is documented in the man page. This function mainly sets things in |  options is documented in the man page. This function mainly sets things in | ||||||
|  the 'SessionHandle' struct. |  the 'SessionHandle' struct. | ||||||
|  |  | ||||||
|  curl_easy_perform() does a whole lot of things: |  curl_easy_perform() is just a wrapper function that makes use of the multi | ||||||
|  |  API.  It basically curl_multi_init(), curl_multi_add_handle(), | ||||||
|  |  curl_multi_wait(), and curl_multi_perform() until the transfer is done and | ||||||
|  |  then returns. | ||||||
|  |  | ||||||
|  It starts off in the lib/easy.c file by calling Curl_perform() and the main |  Some of the most important key functions in url.c are called from multi.c | ||||||
|  work then continues in lib/url.c. The flow continues with a call to |  when certain key steps are to be made in the transfer operation. | ||||||
|  Curl_connect() to connect to the remote site. |  | ||||||
|  |  | ||||||
|  o Curl_connect() |  o Curl_connect() | ||||||
|  |  | ||||||
|    ... analyzes the URL, it separates the different components and connects to |    Analyzes the URL, it separates the different components and connects to the | ||||||
|    the remote host. This may involve using a proxy and/or using SSL. The |    remote host. This may involve using a proxy and/or using SSL. The | ||||||
|    Curl_resolv() function in lib/hostip.c is used for looking up host names |    Curl_resolv() function in lib/hostip.c is used for looking up host names | ||||||
|    (it does then use the proper underlying method, which may vary between |    (it does then use the proper underlying method, which may vary between | ||||||
|    platforms and builds). |    platforms and builds). | ||||||
| @@ -160,10 +165,7 @@ Library | |||||||
|  o Curl_do() |  o Curl_do() | ||||||
|  |  | ||||||
|    Curl_do() makes sure the proper protocol-specific function is called. The |    Curl_do() makes sure the proper protocol-specific function is called. The | ||||||
|    functions are named after the protocols they handle. Curl_ftp(), |    functions are named after the protocols they handle. | ||||||
|    Curl_http(), Curl_dict(), etc. They all reside in their respective files |  | ||||||
|    (ftp.c, http.c and dict.c). HTTPS is handled by Curl_http() and FTPS by |  | ||||||
|    Curl_ftp(). |  | ||||||
|  |  | ||||||
|    The protocol-specific functions of course deal with protocol-specific |    The protocol-specific functions of course deal with protocol-specific | ||||||
|    negotiations and setup. They have access to the Curl_sendf() (from |    negotiations and setup. They have access to the Curl_sendf() (from | ||||||
| @@ -182,10 +184,9 @@ Library | |||||||
|    be called with some basic info about the upcoming transfer: what socket(s) |    be called with some basic info about the upcoming transfer: what socket(s) | ||||||
|    to read/write and the expected file transfer sizes (if known). |    to read/write and the expected file transfer sizes (if known). | ||||||
|  |  | ||||||
|  o Transfer() |  o Curl_readwrite() | ||||||
|  |  | ||||||
|    Curl_perform() then calls Transfer() in lib/transfer.c that performs the |    Called during the transfer of the actual protocol payload. | ||||||
|    entire file transfer. |  | ||||||
|  |  | ||||||
|    During transfer, the progress functions in lib/progress.c are called at a |    During transfer, the progress functions in lib/progress.c are called at a | ||||||
|    frequent interval (or at the user's choice, a specified callback might get |    frequent interval (or at the user's choice, a specified callback might get | ||||||
| @@ -207,33 +208,11 @@ Library | |||||||
|    used. This function is only used when we are certain that no more transfers |    used. This function is only used when we are certain that no more transfers | ||||||
|    is going to be made on the connection. It can be also closed by force, or |    is going to be made on the connection. It can be also closed by force, or | ||||||
|    it can be called to make sure that libcurl doesn't keep too many |    it can be called to make sure that libcurl doesn't keep too many | ||||||
|    connections alive at the same time (there's a default amount of 5 but that |    connections alive at the same time. | ||||||
|    can be changed with the CURLOPT_MAXCONNECTS option). |  | ||||||
|  |  | ||||||
|    This function cleans up all resources that are associated with a single |    This function cleans up all resources that are associated with a single | ||||||
|    connection. |    connection. | ||||||
|  |  | ||||||
|  Curl_perform() is the function that does the main "connect - do - transfer - |  | ||||||
|  done" loop. It loops if there's a Location: to follow. |  | ||||||
|  |  | ||||||
|  When completed, the curl_easy_cleanup() should be called to free up used |  | ||||||
|  resources. It runs Curl_disconnect() on all open connections. |  | ||||||
|  |  | ||||||
|  A quick roundup on internal function sequences (many of these call |  | ||||||
|  protocol-specific function-pointers): |  | ||||||
|  |  | ||||||
|   Curl_connect - connects to a remote site and does initial connect fluff |  | ||||||
|    This also checks for an existing connection to the requested site and uses |  | ||||||
|    that one if it is possible. |  | ||||||
|  |  | ||||||
|    Curl_do - starts a transfer |  | ||||||
|     Curl_handler::do_it() - transfers data |  | ||||||
|    Curl_done - ends a transfer |  | ||||||
|  |  | ||||||
|   Curl_disconnect - disconnects from a remote site. This is called when the |  | ||||||
|    disconnect is really requested, which doesn't necessarily have to be |  | ||||||
|    exactly after curl_done in case we want to keep the connection open for |  | ||||||
|    a while. |  | ||||||
|  |  | ||||||
|  HTTP(S) |  HTTP(S) | ||||||
|  |  | ||||||
| @@ -316,48 +295,38 @@ Persistent Connections | |||||||
|    hold connection-oriented data. It is meant to hold the root data as well as |    hold connection-oriented data. It is meant to hold the root data as well as | ||||||
|    all the options etc that the library-user may choose. |    all the options etc that the library-user may choose. | ||||||
|  o The 'SessionHandle' struct holds the "connection cache" (an array of |  o The 'SessionHandle' struct holds the "connection cache" (an array of | ||||||
|    pointers to 'connectdata' structs). There's one connectdata struct |    pointers to 'connectdata' structs). | ||||||
|    allocated for each connection that libcurl knows about. Note that when you |  | ||||||
|    use the multi interface, the multi handle will hold the connection cache |  | ||||||
|    and not the particular easy handle. This of course to allow all easy handles |  | ||||||
|    in a multi stack to be able to share and re-use connections. |  | ||||||
|  o This enables the 'curl handle' to be reused on subsequent transfers. |  o This enables the 'curl handle' to be reused on subsequent transfers. | ||||||
|  o When we are about to perform a transfer with curl_easy_perform(), we first |  o When libcurl is told to perform a transfer, it first checks for an already | ||||||
|    check for an already existing connection in the cache that we can use, |    existing connection in the cache that we can use. Otherwise it creates a | ||||||
|    otherwise we create a new one and add to the cache. If the cache is full |    new one and adds that the cache. If the cache is full already when a new | ||||||
|    already when we add a new connection, we close one of the present ones. We |    conncetion is added added, it will first close the oldest unused one. | ||||||
|    select which one to close dependent on the close policy that may have been |  o When the transfer operation is complete, the connection is left | ||||||
|    previously set. |    open. Particular options may tell libcurl not to, and protocols may signal | ||||||
|  o When the transfer operation is complete, we try to leave the connection |    closure on connections and then they won't be kept open of course. | ||||||
|    open. Particular options may tell us not to, and protocols may signal |  | ||||||
|    closure on connections and then we don't keep it open of course. |  | ||||||
|  o When curl_easy_cleanup() is called, we close all still opened connections, |  o When curl_easy_cleanup() is called, we close all still opened connections, | ||||||
|    unless of course the multi interface "owns" the connections. |    unless of course the multi interface "owns" the connections. | ||||||
|  |  | ||||||
|  You do realize that the curl handle must be re-used in order for the |  The curl handle must be re-used in order for the persistent connections to | ||||||
|  persistent connections to work. |  work. | ||||||
|  |  | ||||||
| multi interface/non-blocking | multi interface/non-blocking | ||||||
| ============================ | ============================ | ||||||
|  |  | ||||||
|  We make an effort to provide a non-blocking interface to the library, the |  The multi interface is a non-blocking interface to the library. To make that | ||||||
|  multi interface. To make that interface work as good as possible, no |  interface work as good as possible, no low-level functions within libcurl | ||||||
|  low-level functions within libcurl must be written to work in a blocking |  must be written to work in a blocking manner. (There are still a few spots | ||||||
|  manner. |  violating this rule.) | ||||||
|  |  | ||||||
|  One of the primary reasons we introduced c-ares support was to allow the name |  One of the primary reasons we introduced c-ares support was to allow the name | ||||||
|  resolve phase to be perfectly non-blocking as well. |  resolve phase to be perfectly non-blocking as well. | ||||||
|  |  | ||||||
|  The ultimate goal is to provide the easy interface simply by wrapping the |  The FTP and the SFTP/SCP protocols are examples of how we adapt and adjust | ||||||
|  multi interface functions and thus treat everything internally as the multi |  the code to allow non-blocking operations even on multi-stage command- | ||||||
|  interface is the single interface we have. |  response protocols. They are built around state machines that return when | ||||||
|  |  they would otherwise block waiting for data.  The DICT, LDAP and TELNET | ||||||
|  The FTP and the SFTP/SCP protocols are thus perfect examples of how we adapt |  protocols are crappy examples and they are subject for rewrite in the future | ||||||
|  and adjust the code to allow non-blocking operations even on multi-stage |  to better fit the libcurl protocol family. | ||||||
|  protocols. They are built around state machines that return when they could |  | ||||||
|  block waiting for data.  The DICT, LDAP and TELNET protocols are crappy |  | ||||||
|  examples and they are subject for rewrite in the future to better fit the |  | ||||||
|  libcurl protocol family. |  | ||||||
|  |  | ||||||
| SSL libraries | SSL libraries | ||||||
| ============= | ============= | ||||||
| @@ -408,12 +377,12 @@ API/ABI | |||||||
| Client | Client | ||||||
| ====== | ====== | ||||||
|  |  | ||||||
|  main() resides in src/main.c together with most of the client code. |  main() resides in src/tool_main.c. | ||||||
|  |  | ||||||
|  src/tool_hugehelp.c is automatically generated by the mkhelp.pl perl script |  src/tool_hugehelp.c is automatically generated by the mkhelp.pl perl script | ||||||
|  to display the complete "manual" and the src/urlglob.c file holds the |  to display the complete "manual" and the src/tool_urlglob.c file holds the | ||||||
|  functions used for the URL-"globbing" support. Globbing in the sense that |  functions used for the URL-"globbing" support. Globbing in the sense that the | ||||||
|  the {} and [] expansion stuff is there. |  {} and [] expansion stuff is there. | ||||||
|  |  | ||||||
|  The client mostly messes around to setup its 'config' struct properly, then |  The client mostly messes around to setup its 'config' struct properly, then | ||||||
|  it calls the curl_easy_*() functions of the library and when it gets back |  it calls the curl_easy_*() functions of the library and when it gets back | ||||||
| @@ -425,8 +394,8 @@ Client | |||||||
|  curl_easy_getinfo() function to extract useful information from the curl |  curl_easy_getinfo() function to extract useful information from the curl | ||||||
|  session. |  session. | ||||||
|  |  | ||||||
|  Recent versions may loop and do all this several times if many URLs were |  It may loop and do all this several times if many URLs were specified on the | ||||||
|  specified on the command line or config file. |  command line or config file. | ||||||
|  |  | ||||||
| Memory Debugging | Memory Debugging | ||||||
| ================ | ================ | ||||||
|   | |||||||
| @@ -3,6 +3,36 @@ join in and help us correct one or more of these! Also be sure to check the | |||||||
| changelog of the current development status, as one or more of these problems | changelog of the current development status, as one or more of these problems | ||||||
| may have been fixed since this was written! | may have been fixed since this was written! | ||||||
|  |  | ||||||
|  | 87. -J/--remote-header-name doesn't decode %-encoded file names. RFC6266 | ||||||
|  |   details how it should be done. The can of worm is basically that we have no | ||||||
|  |   charset handling in curl and ascii >=128 is a challenge for us. Not to | ||||||
|  |   mention that decoding also means that we need to check for nastyness that is | ||||||
|  |   attempted, like "../" sequences and the like. Probably everything to the left | ||||||
|  |   of any embedded slashes should be cut off. | ||||||
|  |   http://curl.haxx.se/bug/view.cgi?id=1294 | ||||||
|  |  | ||||||
|  | 86. The disconnect commands (LOGOUT and QUIT) may not be sent by IMAP, POP3 | ||||||
|  |   and SMTP if a failure occures during the authentication phase of a | ||||||
|  |   connection. | ||||||
|  |  | ||||||
|  | 85. Wrong STARTTRANSFER timer accounting for POST requests | ||||||
|  |   Timer works fine with GET requests, but while using POST the time for | ||||||
|  |   CURLINFO_STARTTRANSFER_TIME is wrong. While using POST | ||||||
|  |   CURLINFO_STARTTRANSFER_TIME minus CURLINFO_PRETRANSFER_TIME is near to zero | ||||||
|  |   every time. | ||||||
|  |   http://curl.haxx.se/bug/view.cgi?id=1213 | ||||||
|  |  | ||||||
|  | 84. CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL and NSS | ||||||
|  |   backends, so relying on this information in a generic app is flaky. | ||||||
|  |  | ||||||
|  | 83. curl is unable to load non-default openssl engines, because openssl isn't | ||||||
|  |   initialized properly. This seems to require OpenSSL_config() or | ||||||
|  |   CONF_modules_load_file() to be used by libcurl but the first seems to not | ||||||
|  |   work and we've gotten not reports from tests with the latter. Possibly we | ||||||
|  |   need to discuss with OpenSSL developers how this is supposed to be done. We | ||||||
|  |   need users with actual external openssl engines for testing to work on this. | ||||||
|  |   http://curl.haxx.se/bug/view.cgi?id=1208 | ||||||
|  |  | ||||||
| 82. When building with the Windows Borland compiler, it fails because the | 82. When building with the Windows Borland compiler, it fails because the | ||||||
|   "tlib" tool doesn't support hyphens (minus signs) in file names and we have |   "tlib" tool doesn't support hyphens (minus signs) in file names and we have | ||||||
|   such in the build. |   such in the build. | ||||||
| @@ -16,18 +46,18 @@ may have been fixed since this was written! | |||||||
|  |  | ||||||
| 80. Curl doesn't recognize certificates in DER format in keychain, but it | 80. Curl doesn't recognize certificates in DER format in keychain, but it | ||||||
|   works with PEM. |   works with PEM. | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=3439999 |   http://curl.haxx.se/bug/view.cgi?id=1065 | ||||||
|  |  | ||||||
| 79. SMTP. When sending data to multiple recipients, curl will abort and return | 79. SMTP. When sending data to multiple recipients, curl will abort and return | ||||||
|   failure if one of the recipients indicate failure (on the "RCPT TO" |   failure if one of the recipients indicate failure (on the "RCPT TO" | ||||||
|   command). Ordinary mail programs would proceed and still send to the ones |   command). Ordinary mail programs would proceed and still send to the ones | ||||||
|   that can receive data. This is subject for change in the future. |   that can receive data. This is subject for change in the future. | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=3438362 |   http://curl.haxx.se/bug/view.cgi?id=1116 | ||||||
|  |  | ||||||
| 78. curl and libcurl don't always signal the client properly when "sending" | 78. curl and libcurl don't always signal the client properly when "sending" | ||||||
|   zero bytes files - it makes for example the command line client not creating |   zero bytes files - it makes for example the command line client not creating | ||||||
|   any file at all. Like when using FTP. |   any file at all. Like when using FTP. | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=3438362 |   http://curl.haxx.se/bug/view.cgi?id=1063 | ||||||
|  |  | ||||||
| 77. CURLOPT_FORBID_REUSE on a handle prevents NTLM from working since it | 77. CURLOPT_FORBID_REUSE on a handle prevents NTLM from working since it | ||||||
|   "abuses" the underlying connection re-use system and if connections are |   "abuses" the underlying connection re-use system and if connections are | ||||||
| @@ -42,7 +72,7 @@ may have been fixed since this was written! | |||||||
|   properly if built with UNICODE defined together with the schannel/winssl |   properly if built with UNICODE defined together with the schannel/winssl | ||||||
|   backend. The original problem was mentioned in: |   backend. The original problem was mentioned in: | ||||||
|   http://curl.haxx.se/mail/lib-2009-10/0024.html |   http://curl.haxx.se/mail/lib-2009-10/0024.html | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=2944325 |   http://curl.haxx.se/bug/view.cgi?id=896 | ||||||
|  |  | ||||||
|   The schannel version verified to work as mentioned in |   The schannel version verified to work as mentioned in | ||||||
|   http://curl.haxx.se/mail/lib-2012-07/0073.html |   http://curl.haxx.se/mail/lib-2012-07/0073.html | ||||||
| @@ -52,7 +82,7 @@ may have been fixed since this was written! | |||||||
|   acknowledge the connection timeout during that phase but only the "real" |   acknowledge the connection timeout during that phase but only the "real" | ||||||
|   timeout - which may surprise users as it is probably considered to be the |   timeout - which may surprise users as it is probably considered to be the | ||||||
|   connect phase to most people. Brought up (and is being misunderstood) in: |   connect phase to most people. Brought up (and is being misunderstood) in: | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=2844077 |   http://curl.haxx.se/bug/view.cgi?id=856 | ||||||
|  |  | ||||||
| 72. "Pausing pipeline problems." | 72. "Pausing pipeline problems." | ||||||
|   http://curl.haxx.se/mail/lib-2009-07/0214.html |   http://curl.haxx.se/mail/lib-2009-07/0214.html | ||||||
| @@ -70,7 +100,7 @@ may have been fixed since this was written! | |||||||
|   http://tools.ietf.org/html/draft-reschke-rfc2231-in-http-02 |   http://tools.ietf.org/html/draft-reschke-rfc2231-in-http-02 | ||||||
|  |  | ||||||
| 66. When using telnet, the time limitation options don't work. | 66. When using telnet, the time limitation options don't work. | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=2818950 |   http://curl.haxx.se/bug/view.cgi?id=846 | ||||||
|  |  | ||||||
| 65. When doing FTP over a socks proxy or CONNECT through HTTP proxy and the | 65. When doing FTP over a socks proxy or CONNECT through HTTP proxy and the | ||||||
|   multi interface is used, libcurl will fail if the (passive) TCP connection |   multi interface is used, libcurl will fail if the (passive) TCP connection | ||||||
| @@ -96,19 +126,12 @@ may have been fixed since this was written! | |||||||
|   CURLOPT_FAILONERROR with FTP to detect if a file exists or not, but it is |   CURLOPT_FAILONERROR with FTP to detect if a file exists or not, but it is | ||||||
|   not working: http://curl.haxx.se/mail/lib-2008-07/0295.html |   not working: http://curl.haxx.se/mail/lib-2008-07/0295.html | ||||||
|  |  | ||||||
| 57. On VMS-Alpha: When using an http-file-upload the file is not sent to the |  | ||||||
|   Server with the correct content-length.  Sending a file with 511 or less |  | ||||||
|   bytes, content-length 512 is used.  Sending a file with 513 - 1023 bytes, |  | ||||||
|   content-length 1024 is used.  Files with a length of a multiple of 512 Bytes |  | ||||||
|   show the correct content-length. Only these files work for upload. |  | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=2057858 |  | ||||||
|  |  | ||||||
| 56. When libcurl sends CURLOPT_POSTQUOTE commands when connected to a SFTP | 56. When libcurl sends CURLOPT_POSTQUOTE commands when connected to a SFTP | ||||||
|   server using the multi interface, the commands are not being sent correctly |   server using the multi interface, the commands are not being sent correctly | ||||||
|   and instead the connection is "cancelled" (the operation is considered done) |   and instead the connection is "cancelled" (the operation is considered done) | ||||||
|   prematurely. There is a half-baked (busy-looping) patch provided in the bug |   prematurely. There is a half-baked (busy-looping) patch provided in the bug | ||||||
|   report but it cannot be accepted as-is. See |   report but it cannot be accepted as-is. See | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=2006544 |   http://curl.haxx.se/bug/view.cgi?id=748 | ||||||
|  |  | ||||||
| 55. libcurl fails to build with MIT Kerberos for Windows (KfW) due to KfW's | 55. libcurl fails to build with MIT Kerberos for Windows (KfW) due to KfW's | ||||||
|   library header files exporting symbols/macros that should be kept private |   library header files exporting symbols/macros that should be kept private | ||||||
| @@ -132,12 +155,12 @@ may have been fixed since this was written! | |||||||
|   protocol code. This should be very rare. |   protocol code. This should be very rare. | ||||||
|  |  | ||||||
| 43. There seems to be a problem when connecting to the Microsoft telnet server. | 43. There seems to be a problem when connecting to the Microsoft telnet server. | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=1720605 |   http://curl.haxx.se/bug/view.cgi?id=649 | ||||||
|  |  | ||||||
| 41. When doing an operation over FTP that requires the ACCT command (but not | 41. When doing an operation over FTP that requires the ACCT command (but not | ||||||
|   when logging in), the operation will fail since libcurl doesn't detect this |   when logging in), the operation will fail since libcurl doesn't detect this | ||||||
|   and thus fails to issue the correct command: |   and thus fails to issue the correct command: | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=1693337 |   http://curl.haxx.se/bug/view.cgi?id=635 | ||||||
|  |  | ||||||
| 39. Steffen Rumler's Race Condition in Curl_proxyCONNECT: | 39. Steffen Rumler's Race Condition in Curl_proxyCONNECT: | ||||||
|   http://curl.haxx.se/mail/lib-2007-01/0045.html |   http://curl.haxx.se/mail/lib-2007-01/0045.html | ||||||
| @@ -150,7 +173,7 @@ may have been fixed since this was written! | |||||||
|  |  | ||||||
| 34. The SOCKS4 connection codes don't properly acknowledge (connect) timeouts. | 34. The SOCKS4 connection codes don't properly acknowledge (connect) timeouts. | ||||||
|   Also see #12. According to bug #1556528, even the SOCKS5 connect code does |   Also see #12. According to bug #1556528, even the SOCKS5 connect code does | ||||||
|   not do it right: http://curl.haxx.se/bug/view.cgi?id=1556528, |   not do it right: http://curl.haxx.se/bug/view.cgi?id=604 | ||||||
|  |  | ||||||
| 31. "curl-config --libs" will include details set in LDFLAGS when configure is | 31. "curl-config --libs" will include details set in LDFLAGS when configure is | ||||||
|   run that might be needed only for building libcurl. Further, curl-config |   run that might be needed only for building libcurl. Further, curl-config | ||||||
| @@ -165,13 +188,12 @@ may have been fixed since this was written! | |||||||
|   IDs in URLs to get around the problem of percent signs being |   IDs in URLs to get around the problem of percent signs being | ||||||
|   special. According to the reporter, Firefox deals with the URL _with_ a |   special. According to the reporter, Firefox deals with the URL _with_ a | ||||||
|   percent letter (which seems like a blatant URL spec violation). |   percent letter (which seems like a blatant URL spec violation). | ||||||
|   libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25). |   libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25): | ||||||
|  |   http://curl.haxx.se/bug/view.cgi?id=555 | ||||||
|    See http://curl.haxx.se/bug/view.cgi?id=1371118 |  | ||||||
|  |  | ||||||
| 26. NTLM authentication using SSPI (on Windows) when (lib)curl is running in | 26. NTLM authentication using SSPI (on Windows) when (lib)curl is running in | ||||||
|   "system context" will make it use wrong(?) user name - at least when compared |   "system context" will make it use wrong(?) user name - at least when compared | ||||||
|   to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867 |   to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=535 | ||||||
|  |  | ||||||
| 23. SOCKS-related problems: | 23. SOCKS-related problems: | ||||||
|   B) libcurl doesn't support FTPS over a SOCKS proxy. |   B) libcurl doesn't support FTPS over a SOCKS proxy. | ||||||
| @@ -180,12 +202,6 @@ may have been fixed since this was written! | |||||||
|   We probably have even more bugs and lack of features when a SOCKS proxy is |   We probably have even more bugs and lack of features when a SOCKS proxy is | ||||||
|   used. |   used. | ||||||
|  |  | ||||||
| 22. Sending files to a FTP server using curl on VMS, might lead to curl |  | ||||||
|   complaining on "unaligned file size" on completion. The problem is related |  | ||||||
|   to VMS file structures and the perceived file sizes stat() returns. A |  | ||||||
|   possible fix would involve sending a "STRU VMS" command. |  | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=1156287 |  | ||||||
|  |  | ||||||
| 21. FTP ASCII transfers do not follow RFC959. They don't convert the data | 21. FTP ASCII transfers do not follow RFC959. They don't convert the data | ||||||
|    accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1 |    accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1 | ||||||
|    clearly describes how this should be done: |    clearly describes how this should be done: | ||||||
| @@ -223,7 +239,7 @@ may have been fixed since this was written! | |||||||
| 10. To get HTTP Negotiate authentication to work fine, you need to provide a | 10. To get HTTP Negotiate authentication to work fine, you need to provide a | ||||||
|   (fake) user name (this concerns both curl and the lib) because the code |   (fake) user name (this concerns both curl and the lib) because the code | ||||||
|   wrongly only considers authentication if there's a user name provided. |   wrongly only considers authentication if there's a user name provided. | ||||||
|   http://curl.haxx.se/bug/view.cgi?id=1004841. How? |   http://curl.haxx.se/bug/view.cgi?id=440 How? | ||||||
|   http://curl.haxx.se/mail/lib-2004-08/0182.html |   http://curl.haxx.se/mail/lib-2004-08/0182.html | ||||||
|  |  | ||||||
| 8. Doing resumed upload over HTTP does not work with '-C -', because curl | 8. Doing resumed upload over HTTP does not work with '-C -', because curl | ||||||
|   | |||||||
							
								
								
									
										245
									
								
								docs/LIBCURL-STRUCTS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								docs/LIBCURL-STRUCTS
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | |||||||
|  |                                   _   _ ____  _ | ||||||
|  |                               ___| | | |  _ \| | | ||||||
|  |                              / __| | | | |_) | | | ||||||
|  |                             | (__| |_| |  _ <| |___ | ||||||
|  |                              \___|\___/|_| \_\_____| | ||||||
|  |  | ||||||
|  | Structs in libcurl | ||||||
|  |  | ||||||
|  | This document should cover 7.32.0 pretty accurately, but will make sense even | ||||||
|  | for older and later versions as things don't change drastically that often. | ||||||
|  |  | ||||||
|  |  1. The main structs in libcurl | ||||||
|  |   1.1 SessionHandle | ||||||
|  |   1.2 connectdata | ||||||
|  |   1.3 Curl_multi | ||||||
|  |   1.4 Curl_handler | ||||||
|  |   1.5 conncache | ||||||
|  |   1.6 Curl_share | ||||||
|  |   1.7 CookieInfo | ||||||
|  |  | ||||||
|  | ============================================================================== | ||||||
|  |  | ||||||
|  | 1. The main structs in libcurl | ||||||
|  |  | ||||||
|  |   1.1 SessionHandle | ||||||
|  |  | ||||||
|  |   The SessionHandle handle struct is the one returned to the outside in the | ||||||
|  |   external API as a "CURL *". This is usually known as an easy handle in API | ||||||
|  |   documentations and examples. | ||||||
|  |  | ||||||
|  |   Information and state that is related to the actual connection is in the | ||||||
|  |   'connectdata' struct. When a transfer is about to be made, libcurl will | ||||||
|  |   either create a new connection or re-use an existing one. The particular | ||||||
|  |   connectdata that is used by this handle is pointed out by | ||||||
|  |   SessionHandle->easy_conn. | ||||||
|  |  | ||||||
|  |   Data and information that regard this particular single transfer is put in | ||||||
|  |   the SingleRequest sub-struct. | ||||||
|  |  | ||||||
|  |   When the SessionHandle struct is added to a multi handle, as it must be in | ||||||
|  |   order to do any transfer, the ->multi member will point to the Curl_multi | ||||||
|  |   struct it belongs to. The ->prev and ->next members will then be used by the | ||||||
|  |   multi code to keep a linked list of SessionHandle structs that are added to | ||||||
|  |   that same multi handle. libcurl always uses multi so ->multi *will* point to | ||||||
|  |   a Curl_multi when a transfer is in progress. | ||||||
|  |  | ||||||
|  |   ->mstate is the multi state of this particular SessionHandle. When | ||||||
|  |   multi_runsingle() is called, it will act on this handle according to which | ||||||
|  |   state it is in. The mstate is also what tells which sockets to return for a | ||||||
|  |   speicific SessionHandle when curl_multi_fdset() is called etc. | ||||||
|  |  | ||||||
|  |   The libcurl source code generally use the name 'data' for the variable that | ||||||
|  |   points to the SessionHandle. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   1.2 connectdata | ||||||
|  |  | ||||||
|  |   A general idea in libcurl is to keep connections around in a connection | ||||||
|  |   "cache" after they have been used in case they will be used again and then | ||||||
|  |   re-use an existing one instead of creating a new as it creates a significant | ||||||
|  |   performance boost. | ||||||
|  |  | ||||||
|  |   Each 'connectdata' identifies a single physical conncetion to a server. If | ||||||
|  |   the connection can't be kept alive, the connection will be closed after use | ||||||
|  |   and then this struct can be removed from the cache and freed. | ||||||
|  |  | ||||||
|  |   Thus, the same SessionHandle can be used multiple times and each time select | ||||||
|  |   another connectdata struct to use for the connection. Keep this in mind, as | ||||||
|  |   it is then important to consider if options or choices are based on the | ||||||
|  |   connection or the SessionHandle. | ||||||
|  |  | ||||||
|  |   Functions in libcurl will assume that connectdata->data points to the | ||||||
|  |   SessionHandle that uses this connection. | ||||||
|  |  | ||||||
|  |   As a special complexity, some protocols supported by libcurl require a | ||||||
|  |   special disconnect procedure that is more than just shutting down the | ||||||
|  |   socket. It can involve sending one or more commands to the server before | ||||||
|  |   doing so. Since connections are kept in the connection cache after use, the | ||||||
|  |   original SessionHandle may no longer be around when the time comes to shut | ||||||
|  |   down a particular connection. For this purpose, libcurl holds a special | ||||||
|  |   dummy 'closure_handle' SessionHandle in the Curl_multi struct to  | ||||||
|  |  | ||||||
|  |   FTP uses two TCP connections for a typical transfer but it keeps both in | ||||||
|  |   this single struct and thus can be considered a single connection for most | ||||||
|  |   internal concerns. | ||||||
|  |  | ||||||
|  |   The libcurl source code generally use the name 'conn' for the variable that | ||||||
|  |   points to the connectdata. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   1.3 Curl_multi | ||||||
|  |  | ||||||
|  |   Internally, the easy interface is implemented as a wrapper around multi | ||||||
|  |   interface functions. This makes everything multi interface. | ||||||
|  |  | ||||||
|  |   Curl_multi is the multi handle struct exposed as "CURLM *" in external APIs. | ||||||
|  |  | ||||||
|  |   This struct holds a list of SessionHandle structs that have been added to | ||||||
|  |   this handle with curl_multi_add_handle(). The start of the list is ->easyp | ||||||
|  |   and ->num_easy is a counter of added SessionHandles. | ||||||
|  |  | ||||||
|  |   ->msglist is a linked list of messages to send back when | ||||||
|  |   curl_multi_info_read() is called. Basically a node is added to that list | ||||||
|  |   when an individual SessionHandle's transfer has completed. | ||||||
|  |  | ||||||
|  |   ->hostcache points to the name cache. It is a hash table for looking up name | ||||||
|  |   to IP. The nodes have a limited life time in there and this cache is meant | ||||||
|  |   to reduce the time for when the same name is wanted within a short period of | ||||||
|  |   time. | ||||||
|  |  | ||||||
|  |   ->timetree points to a tree of SessionHandles, sorted by the remaining time | ||||||
|  |   until it should be checked - normally some sort of timeout. Each | ||||||
|  |   SessionHandle has one node in the tree. | ||||||
|  |  | ||||||
|  |   ->sockhash is a hash table to allow fast lookups of socket descriptor to | ||||||
|  |   which SessionHandle that uses that descriptor. This is necessary for the | ||||||
|  |   multi_socket API. | ||||||
|  |  | ||||||
|  |   ->conn_cache points to the connection cache. It keeps track of all | ||||||
|  |   connections that are kept after use. The cache has a maximum size. | ||||||
|  |  | ||||||
|  |   ->closure_handle is described in the 'connectdata' section. | ||||||
|  |  | ||||||
|  |   The libcurl source code generally use the name 'multi' for the variable that | ||||||
|  |   points to the Curl_multi struct. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   1.4 Curl_handler | ||||||
|  |  | ||||||
|  |   Each unique protocol that is supported by libcurl needs to provide at least | ||||||
|  |   one Curl_handler struct. It defines what the protocol is called and what | ||||||
|  |   functions the main code should call to deal with protocol specific issues. | ||||||
|  |   In general, there's a source file named [protocol].c in which there's a | ||||||
|  |   "struct Curl_handler Curl_handler_[protocol]" declared. In url.c there's | ||||||
|  |   then the main array with all individual Curl_handler structs pointed to from | ||||||
|  |   a single array which is scanned through when a URL is given to libcurl to | ||||||
|  |   work with. | ||||||
|  |  | ||||||
|  |   ->scheme is the URL scheme name, usually spelled out in uppercase. That's | ||||||
|  |   "HTTP" or "FTP" etc. SSL versions of the protcol need its own Curl_handler | ||||||
|  |   setup so HTTPS separate from HTTP. | ||||||
|  |  | ||||||
|  |   ->setup_connection is called to allow the protocol code to allocate protocol | ||||||
|  |   specific data that then gets associated with that SessionHandle for the rest | ||||||
|  |   of this transfer. It gets freed again at the end of the transfer. It will be | ||||||
|  |   called before the 'connectdata' for the transfer has been selected/created. | ||||||
|  |   Most protocols will allocate its private 'struct [PROTOCOL]' here and assign | ||||||
|  |   SessionHandle->req.protop to point to it. | ||||||
|  |  | ||||||
|  |   ->connect_it allows a protocol to do some specific actions after the TCP | ||||||
|  |   connect is done, that can still be considered part of the connection phase. | ||||||
|  |  | ||||||
|  |   Some protocols will alter the connectdata->recv[] and connectdata->send[] | ||||||
|  |   function pointers in this function. | ||||||
|  |  | ||||||
|  |   ->connecting is similarly a function that keeps getting called as long as the | ||||||
|  |   protocol considers itself still in the connecting phase. | ||||||
|  |  | ||||||
|  |   ->do_it is the function called to issue the transfer request. What we call | ||||||
|  |   the DO action internally. If the DO is not enough and things need to be kept | ||||||
|  |   getting done for the entier DO sequence to complete, ->doing is then usually | ||||||
|  |   also provided. Each protocol that needs to do multiple commands or similar | ||||||
|  |   for do/doing need to implement their own state machines (see SCP, SFTP, | ||||||
|  |   FTP). Some protocols (only FTP and only due to historical reasons) has a | ||||||
|  |   separate piece of the DO state called DO_MORE. | ||||||
|  |  | ||||||
|  |   ->doing keeps getting called while issudeing the transfer request command(s) | ||||||
|  |  | ||||||
|  |   ->done gets called when the transfer is complete and DONE. That's after the | ||||||
|  |   main data has been transferred. | ||||||
|  |  | ||||||
|  |   ->do_more gets called doring the DO_MORE state. The FTP protocol uses this | ||||||
|  |   state when setting up the second connection. | ||||||
|  |  | ||||||
|  |   ->proto_getsock | ||||||
|  |   ->doing_getsock | ||||||
|  |   ->domore_getsock | ||||||
|  |   ->perform_getsock | ||||||
|  |   Functions that return socket information. Which socket(s) to wait for which | ||||||
|  |   action(s) during the particular multi state. | ||||||
|  |  | ||||||
|  |   ->disconnect is called immediately before the TCP connection is shutdown. | ||||||
|  |  | ||||||
|  |   ->readwrite gets called during transfer to allow the protocol to do extra | ||||||
|  |   reads/writes | ||||||
|  |  | ||||||
|  |   ->defport is the default report TCP or UDP port this protocol uses | ||||||
|  |  | ||||||
|  |   ->protocol is one or more bits in the CURLPROTO_* set. The SSL versions have | ||||||
|  |   their "base" protocol set and then the SSL variation. Like "HTTP|HTTPS". | ||||||
|  |  | ||||||
|  |   ->flags is a bitmask with additional information about the protocol that will | ||||||
|  |   make it get treated differently by the generic engine: | ||||||
|  |  | ||||||
|  |     PROTOPT_SSL - will make it connect and negotiate SSL | ||||||
|  |  | ||||||
|  |     PROTOPT_DUAL - this protocol uses two connections | ||||||
|  |  | ||||||
|  |     PROTOPT_CLOSEACTION - this protocol has actions to do before closing the | ||||||
|  |     connection. This flag is no longer used by code, yet still set for a bunch | ||||||
|  |     protocol handlers. | ||||||
|  |    | ||||||
|  |     PROTOPT_DIRLOCK - "direction lock". The SSH protocols set this bit to | ||||||
|  |     limit which "direction" of socket actions that the main engine will | ||||||
|  |     concern itself about. | ||||||
|  |  | ||||||
|  |     PROTOPT_NONETWORK - a protocol that doesn't use network (read file:) | ||||||
|  |  | ||||||
|  |     PROTOPT_NEEDSPWD - this protocol needs a password and will use a default | ||||||
|  |     one unless one is provided | ||||||
|  |  | ||||||
|  |     PROTOPT_NOURLQUERY - this protocol can't handle a query part on the URL | ||||||
|  |     (?foo=bar) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   1.5 conncache | ||||||
|  |  | ||||||
|  |   Is a hash table with connections for later re-use. Each SessionHandle has | ||||||
|  |   a pointer to its connection cache. Each multi handle sets up a connection | ||||||
|  |   cache that all added SessionHandles share by default. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   1.6 Curl_share | ||||||
|  |    | ||||||
|  |   The libcurl share API allocates a Curl_share struct, exposed to the external | ||||||
|  |   API as "CURLSH *". | ||||||
|  |  | ||||||
|  |   The idea is that the struct can have a set of own versions of caches and | ||||||
|  |   pools and then by providing this struct in the CURLOPT_SHARE option, those | ||||||
|  |   specific SessionHandles will use the caches/pools that this share handle | ||||||
|  |   holds. | ||||||
|  |  | ||||||
|  |   Then individual SessionHandle structs can be made to share specific things | ||||||
|  |   that they otherwise wouldn't, such as cookies. | ||||||
|  |  | ||||||
|  |   The Curl_share struct can currently hold cookies, DNS cache and the SSL | ||||||
|  |   session cache. | ||||||
|  |  | ||||||
|  |    | ||||||
|  |   1.7 CookieInfo | ||||||
|  |  | ||||||
|  |   This is the main cookie struct. It holds all known cookies and related | ||||||
|  |   information. Each SessionHandle has its own private CookieInfo even when | ||||||
|  |   they are added to a multi handle. They can be made to share cookies by using | ||||||
|  |   the share API. | ||||||
| @@ -5,7 +5,7 @@ | |||||||
| #                            | (__| |_| |  _ <| |___ | #                            | (__| |_| |  _ <| |___ | ||||||
| #                             \___|\___/|_| \_\_____| | #                             \___|\___/|_| \_\_____| | ||||||
| # | # | ||||||
| # Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. | # Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
| # | # | ||||||
| # This software is licensed as described in the file COPYING, which | # This software is licensed as described in the file COPYING, which | ||||||
| # you should have received as part of this distribution. The terms | # you should have received as part of this distribution. The terms | ||||||
| @@ -22,7 +22,8 @@ | |||||||
|  |  | ||||||
| AUTOMAKE_OPTIONS = foreign no-dependencies | AUTOMAKE_OPTIONS = foreign no-dependencies | ||||||
|  |  | ||||||
| man_MANS = curl.1 curl-config.1 mk-ca-bundle.1 | man_MANS = curl.1 curl-config.1 | ||||||
|  | noinst_man_MANS = mk-ca-bundle.1 | ||||||
| GENHTMLPAGES = curl.html curl-config.html mk-ca-bundle.html | GENHTMLPAGES = curl.html curl-config.html mk-ca-bundle.html | ||||||
| PDFPAGES = curl.pdf curl-config.pdf mk-ca-bundle.pdf | PDFPAGES = curl.pdf curl-config.pdf mk-ca-bundle.pdf | ||||||
|  |  | ||||||
| @@ -36,7 +37,7 @@ EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS	 \ | |||||||
|  README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS	 \ |  README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS	 \ | ||||||
|  KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL		 \ |  KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL		 \ | ||||||
|  $(PDFPAGES) LICENSE-MIXING README.netware DISTRO-DILEMMA INSTALL.devcpp \ |  $(PDFPAGES) LICENSE-MIXING README.netware DISTRO-DILEMMA INSTALL.devcpp \ | ||||||
|  MAIL-ETIQUETTE HTTP-COOKIES |  MAIL-ETIQUETTE HTTP-COOKIES LIBCURL-STRUCTS SECURITY | ||||||
|  |  | ||||||
| MAN2HTML= roffit < $< >$@ | MAN2HTML= roffit < $< >$@ | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										91
									
								
								docs/SECURITY
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								docs/SECURITY
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  |                                   _   _ ____  _ | ||||||
|  |                               ___| | | |  _ \| | | ||||||
|  |                              / __| | | | |_) | | | ||||||
|  |                             | (__| |_| |  _ <| |___ | ||||||
|  |                              \___|\___/|_| \_\_____| | ||||||
|  |  | ||||||
|  | CURL SECURITY FOR DEVELOPERS | ||||||
|  |  | ||||||
|  | This document is intended to provide guidance to curl developers on how | ||||||
|  | security vulnerabilities should be handled. | ||||||
|  |  | ||||||
|  | PUBLISHING INFORMATION | ||||||
|  |  | ||||||
|  | All known and public curl or libcurl related vulnerabilities are listed at | ||||||
|  | http://curl.haxx.se/docs/security.html | ||||||
|  |  | ||||||
|  | Security vulnerabilities should not be entered in the project's public bug | ||||||
|  | tracker unless the necessary configuration is in place to limit access to the | ||||||
|  | issue to only the reporter and the project's security team. | ||||||
|  |  | ||||||
|  | VULNERABILITY HANDLING | ||||||
|  |  | ||||||
|  | The typical process for handling a new security vulnerability is as follows. | ||||||
|  |  | ||||||
|  | No information should be made public about a vulnerability until it is | ||||||
|  | formally announced at the end of this process. That means, for example that a | ||||||
|  | bug tracker entry must NOT be created to track the issue since that will make | ||||||
|  | the issue public and it should not be discussed on any of the project's public | ||||||
|  | mailing lists. Also messages associated with any commits should not make | ||||||
|  | any reference to the security nature of the commit if done prior to the public | ||||||
|  | announcement. | ||||||
|  |  | ||||||
|  | - The person discovering the issue, the reporter, reports the vulnerability | ||||||
|  |   privately to curl-security@haxx.se. That's an email alias that reaches a | ||||||
|  |   handful of selected and trusted people. | ||||||
|  |  | ||||||
|  | - Messages that do not relate to the reporting or managing of an undisclosed | ||||||
|  |   security vulnerability in curl or libcurl are ignored and no further action | ||||||
|  |   is required. | ||||||
|  |  | ||||||
|  | - A person in the security team sends an e-mail to the original reporter to | ||||||
|  |   acknowledge the report. | ||||||
|  |  | ||||||
|  | - The security team investigates the report and either rejects it or accepts | ||||||
|  |   it. | ||||||
|  |  | ||||||
|  | - If the report is rejected, the team writes to the reporter to explain why. | ||||||
|  |  | ||||||
|  | - If the report is accepted, the team writes to the reporter to let him/her | ||||||
|  |   know it is accepted and that they are working on a fix. | ||||||
|  |  | ||||||
|  | - The security team discusses the problem, works out a fix, considers the | ||||||
|  |   impact of the problem and suggests a release schedule. This discussion | ||||||
|  |   should involve the reporter as much as possible. | ||||||
|  |  | ||||||
|  | - The release of the information should be "as soon as possible" and is most | ||||||
|  |   often synced with an upcoming release that contains the fix. If the | ||||||
|  |   reporter, or anyone else, thinks the next planned release is too far away | ||||||
|  |   then a separate earlier release for security reasons should be considered. | ||||||
|  |  | ||||||
|  | - Write a security advisory draft about the problem that explains what the | ||||||
|  |   problem is, its impact, which versions it affects, solutions or | ||||||
|  |   work-arounds, when the release is out and make sure to credit all | ||||||
|  |   contributors properly. | ||||||
|  |  | ||||||
|  | - Request a CVE number from distros@openwall.org[1] when also informing and | ||||||
|  |   preparing them for the upcoming public security vulnerability announcement - | ||||||
|  |   attach the advisory draft for information. Note that 'distros' won't accept | ||||||
|  |   an embargo longer than 19 days. | ||||||
|  |  | ||||||
|  | - Update the "security advisory" with the CVE number. | ||||||
|  |  | ||||||
|  | - The security team commits the fix in a private branch. The commit message | ||||||
|  |   should ideally contain the CVE number. This fix is usually also distributed | ||||||
|  |   to the 'distros' mailing list to allow them to use the fix prior to the | ||||||
|  |   public announcement. | ||||||
|  |  | ||||||
|  | - At the day of the next release, the private branch is merged into the master | ||||||
|  |   branch and pushed. Once pushed, the information is accessible to the public | ||||||
|  |   and the actual release should follow suit immediately afterwards. | ||||||
|  |  | ||||||
|  | - The project team creates a release that includes the fix. | ||||||
|  |  | ||||||
|  | - The project team announces the release and the vulnerability to the world in | ||||||
|  |   the same manner we always announce releases. It gets sent to the | ||||||
|  |   curl-announce, curl-library and curl-users mailing lists. | ||||||
|  |  | ||||||
|  | - The security web page on the web site should get the new vulernability | ||||||
|  |   mentioned. | ||||||
|  |  | ||||||
|  | [1] = http://oss-security.openwall.org/wiki/mailing-lists/distros | ||||||
							
								
								
									
										79
									
								
								docs/THANKS
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								docs/THANKS
									
									
									
									
									
								
							| @@ -21,11 +21,13 @@ Albert Choy | |||||||
| Ale Vesely | Ale Vesely | ||||||
| Alejandro Alvarez | Alejandro Alvarez | ||||||
| Aleksandar Milivojevic | Aleksandar Milivojevic | ||||||
|  | Aleksey Tulinov | ||||||
| Alessandro Ghedini | Alessandro Ghedini | ||||||
| Alessandro Vesely | Alessandro Vesely | ||||||
| Alex Bligh | Alex Bligh | ||||||
| Alex Fishman | Alex Fishman | ||||||
| Alex Gruz | Alex Gruz | ||||||
|  | Alex McLellan | ||||||
| Alex Neblett | Alex Neblett | ||||||
| Alex Suykov | Alex Suykov | ||||||
| Alex Vinnik | Alex Vinnik | ||||||
| @@ -47,11 +49,13 @@ Amol Pattekar | |||||||
| Amr Shahin | Amr Shahin | ||||||
| Anatoli Tubman | Anatoli Tubman | ||||||
| Anders Gustafsson | Anders Gustafsson | ||||||
|  | Anders Havn | ||||||
| Andi Jahja | Andi Jahja | ||||||
| Andre Guibert de Bruet | Andre Guibert de Bruet | ||||||
| Andreas Damm | Andreas Damm | ||||||
| Andreas Faerber | Andreas Faerber | ||||||
| Andreas Farber | Andreas Farber | ||||||
|  | Andreas Malzahn | ||||||
| Andreas Ntaflos | Andreas Ntaflos | ||||||
| Andreas Olsson | Andreas Olsson | ||||||
| Andreas Rieke | Andreas Rieke | ||||||
| @@ -59,6 +63,7 @@ Andreas Schuldei | |||||||
| Andreas Wurf | Andreas Wurf | ||||||
| Andrei Benea | Andrei Benea | ||||||
| Andrei Cipu | Andrei Cipu | ||||||
|  | Andrej E Baranov | ||||||
| Andres Garcia | Andres Garcia | ||||||
| Andrew Benham | Andrew Benham | ||||||
| Andrew Biggs | Andrew Biggs | ||||||
| @@ -69,6 +74,7 @@ Andrew Kurushin | |||||||
| Andrew Moise | Andrew Moise | ||||||
| Andrew Wansink | Andrew Wansink | ||||||
| Andrew de los Reyes | Andrew de los Reyes | ||||||
|  | Andrii Moiseiev | ||||||
| Andrés García | Andrés García | ||||||
| Andy Cedilnik | Andy Cedilnik | ||||||
| Andy Serpa | Andy Serpa | ||||||
| @@ -103,10 +109,13 @@ Ben Van Hof | |||||||
| Ben Winslow | Ben Winslow | ||||||
| Benbuck Nason | Benbuck Nason | ||||||
| Benjamin Gerard | Benjamin Gerard | ||||||
|  | Benjamin Gilbert | ||||||
| Benjamin Johnson | Benjamin Johnson | ||||||
|  | Benoit Sigoure | ||||||
| Bernard Leak | Bernard Leak | ||||||
| Bernhard Reutner-Fischer | Bernhard Reutner-Fischer | ||||||
| Bertrand Demiddelaer | Bertrand Demiddelaer | ||||||
|  | Bill Doyle | ||||||
| Bill Egert | Bill Egert | ||||||
| Bill Hoffman | Bill Hoffman | ||||||
| Bill Middlecamp | Bill Middlecamp | ||||||
| @@ -136,6 +145,7 @@ Bruce Mitchener | |||||||
| Bruno de Carvalho | Bruno de Carvalho | ||||||
| Bryan Henderson | Bryan Henderson | ||||||
| Bryan Kemp | Bryan Kemp | ||||||
|  | Byrial Jensen | ||||||
| Cameron Kaiser | Cameron Kaiser | ||||||
| Camille Moncelier | Camille Moncelier | ||||||
| Caolan McNamara | Caolan McNamara | ||||||
| @@ -148,6 +158,7 @@ Charles Kerr | |||||||
| Chih-Chung Chang | Chih-Chung Chang | ||||||
| Chris "Bob Bob" | Chris "Bob Bob" | ||||||
| Chris Combes | Chris Combes | ||||||
|  | Chris Conlon | ||||||
| Chris Conroy | Chris Conroy | ||||||
| Chris Deidun | Chris Deidun | ||||||
| Chris Flerackers | Chris Flerackers | ||||||
| @@ -162,6 +173,7 @@ Christian Kurz | |||||||
| Christian Robottom Reis | Christian Robottom Reis | ||||||
| Christian Schmitz | Christian Schmitz | ||||||
| Christian Vogt | Christian Vogt | ||||||
|  | Christian Weisgerber | ||||||
| Christophe Demory | Christophe Demory | ||||||
| Christophe Legry | Christophe Legry | ||||||
| Christopher Conroy | Christopher Conroy | ||||||
| @@ -174,6 +186,7 @@ Clarence Gardner | |||||||
| Clemens Gruber | Clemens Gruber | ||||||
| Clifford Wolf | Clifford Wolf | ||||||
| Cody Jones | Cody Jones | ||||||
|  | Colby Ranger | ||||||
| Colin Hogben | Colin Hogben | ||||||
| Colin Watson | Colin Watson | ||||||
| Colm Buckley | Colm Buckley | ||||||
| @@ -187,6 +200,7 @@ Cristian Rodríguez | |||||||
| Curt Bogmine | Curt Bogmine | ||||||
| Cyrill Osterwalder | Cyrill Osterwalder | ||||||
| Cédric Deltheil | Cédric Deltheil | ||||||
|  | D. Flinkmann | ||||||
| Dag Ekengren | Dag Ekengren | ||||||
| Dagobert Michelsen | Dagobert Michelsen | ||||||
| Damien Adant | Damien Adant | ||||||
| @@ -214,6 +228,7 @@ Dave Halbakken | |||||||
| Dave Hamilton | Dave Hamilton | ||||||
| Dave May | Dave May | ||||||
| Dave Reisner | Dave Reisner | ||||||
|  | Dave Thompson | ||||||
| Dave Vasilevsky | Dave Vasilevsky | ||||||
| David Bau | David Bau | ||||||
| David Binderman | David Binderman | ||||||
| @@ -234,15 +249,19 @@ David Odin | |||||||
| David Phillips | David Phillips | ||||||
| David Rosenstrauch | David Rosenstrauch | ||||||
| David Shaw | David Shaw | ||||||
|  | David Strauss | ||||||
| David Tarendash | David Tarendash | ||||||
| David Thiel | David Thiel | ||||||
|  | David Walser | ||||||
| David Wright | David Wright | ||||||
| David Yan | David Yan | ||||||
| Dengminwen | Dengminwen | ||||||
|  | Derek Higgins | ||||||
| Detlef Schmier | Detlef Schmier | ||||||
| Didier Brisebourg | Didier Brisebourg | ||||||
| Diego Casorran | Diego Casorran | ||||||
| Dima Barsky | Dima Barsky | ||||||
|  | Dima Tisnek | ||||||
| Dimitre Dimitrov | Dimitre Dimitrov | ||||||
| Dimitris Sarris | Dimitris Sarris | ||||||
| Dinar | Dinar | ||||||
| @@ -266,6 +285,7 @@ Douglas R. Horner | |||||||
| Douglas Steinwand | Douglas Steinwand | ||||||
| Dov Murik | Dov Murik | ||||||
| Duane Cathey | Duane Cathey | ||||||
|  | Duncan | ||||||
| Duncan Mac-Vicar Prett | Duncan Mac-Vicar Prett | ||||||
| Dustin Boswell | Dustin Boswell | ||||||
| Dylan Ellicott | Dylan Ellicott | ||||||
| @@ -274,11 +294,13 @@ Early Ehlinger | |||||||
| Ebenezer Ikonne | Ebenezer Ikonne | ||||||
| Edin Kadribasic | Edin Kadribasic | ||||||
| Eduard Bloch | Eduard Bloch | ||||||
|  | Edward Rudd | ||||||
| Edward Sheldrake | Edward Sheldrake | ||||||
| Eelco Dolstra | Eelco Dolstra | ||||||
| Eetu Ojanen | Eetu Ojanen | ||||||
| Eldar Zaitov | Eldar Zaitov | ||||||
| Ellis Pritchard | Ellis Pritchard | ||||||
|  | Elmira A Semenova | ||||||
| Emanuele Bovisio | Emanuele Bovisio | ||||||
| Emil Romanus | Emil Romanus | ||||||
| Emiliano Ida | Emiliano Ida | ||||||
| @@ -288,27 +310,33 @@ Eric Cooper | |||||||
| Eric Hu | Eric Hu | ||||||
| Eric Landes | Eric Landes | ||||||
| Eric Lavigne | Eric Lavigne | ||||||
|  | Eric Lubin | ||||||
| Eric Melville | Eric Melville | ||||||
| Eric Mertens | Eric Mertens | ||||||
| Eric Rautman | Eric Rautman | ||||||
|  | Eric S. Raymond | ||||||
| Eric Thelin | Eric Thelin | ||||||
| Eric Vergnaud | Eric Vergnaud | ||||||
| Eric Wong | Eric Wong | ||||||
| Eric Young | Eric Young | ||||||
| Erick Nuwendam | Erick Nuwendam | ||||||
|  | Erik Johansson | ||||||
| Erwan Legrand | Erwan Legrand | ||||||
| Erwin Authried | Erwin Authried | ||||||
| Eugene Kotlyarov | Eugene Kotlyarov | ||||||
| Evan Jordan | Evan Jordan | ||||||
|  | Evgeny Turnaev | ||||||
| Eygene Ryabinkin | Eygene Ryabinkin | ||||||
| Fabian Hiernaux | Fabian Hiernaux | ||||||
| Fabian Keil | Fabian Keil | ||||||
| Fabrizio Ammollo | Fabrizio Ammollo | ||||||
| Fedor Karpelevitch | Fedor Karpelevitch | ||||||
|  | Felix Yan | ||||||
| Felix von Leitner | Felix von Leitner | ||||||
| Feng Tu | Feng Tu | ||||||
| Florian Schoppmann | Florian Schoppmann | ||||||
| Forrest Cahoon | Forrest Cahoon | ||||||
|  | Francois Charlier | ||||||
| Frank Hempel | Frank Hempel | ||||||
| Frank Keeney | Frank Keeney | ||||||
| Frank McGeough | Frank McGeough | ||||||
| @@ -329,11 +357,13 @@ Gautam Kachroo | |||||||
| Gautam Mani | Gautam Mani | ||||||
| Gavrie Philipson | Gavrie Philipson | ||||||
| Gaz Iqbal | Gaz Iqbal | ||||||
|  | Geoff Beier | ||||||
| Georg Horn | Georg Horn | ||||||
| Georg Huettenegger | Georg Huettenegger | ||||||
| Georg Lippitsch | Georg Lippitsch | ||||||
| Georg Wicherski | Georg Wicherski | ||||||
| Gerd v. Egidy | Gerd v. Egidy | ||||||
|  | Gergely Nagy | ||||||
| Gerhard Herre | Gerhard Herre | ||||||
| Gerrit Bruchhäuser | Gerrit Bruchhäuser | ||||||
| Ghennadi Procopciuc | Ghennadi Procopciuc | ||||||
| @@ -349,6 +379,8 @@ Giuseppe D'Ambrosio | |||||||
| Glen Nakamura | Glen Nakamura | ||||||
| Glen Scott | Glen Scott | ||||||
| Gokhan Sengun | Gokhan Sengun | ||||||
|  | Gordon Marler | ||||||
|  | Gorilla Maguila | ||||||
| Grant Erickson | Grant Erickson | ||||||
| Greg Hewgill | Greg Hewgill | ||||||
| Greg Morse | Greg Morse | ||||||
| @@ -364,14 +396,17 @@ Gwenole Beauchesne | |||||||
| Götz Babin-Ebell | Götz Babin-Ebell | ||||||
| Hamish Mackenzie | Hamish Mackenzie | ||||||
| Hang Kin Lau | Hang Kin Lau | ||||||
|  | Hang Su | ||||||
| Hanno Kranzhoff | Hanno Kranzhoff | ||||||
| Hans Steegers | Hans Steegers | ||||||
| Hans-Jurgen May | Hans-Jurgen May | ||||||
| Hardeep Singh | Hardeep Singh | ||||||
| Harshal Pradhan | Harshal Pradhan | ||||||
| Hauke Duden | Hauke Duden | ||||||
|  | He Qin | ||||||
| Heikki Korpela | Heikki Korpela | ||||||
| Heinrich Ko | Heinrich Ko | ||||||
|  | Heinrich Schaefer | ||||||
| Hendrik Visage | Hendrik Visage | ||||||
| Henrik Storner | Henrik Storner | ||||||
| Henry Ludemann | Henry Ludemann | ||||||
| @@ -398,6 +433,7 @@ Immanuel Gregoire | |||||||
| Ingmar Runge | Ingmar Runge | ||||||
| Ingo Ralf Blum | Ingo Ralf Blum | ||||||
| Ingo Wilken | Ingo Wilken | ||||||
|  | Ishan SinghLevett | ||||||
| Jack Zhang | Jack Zhang | ||||||
| Jacky Lam | Jacky Lam | ||||||
| Jacob Meuser | Jacob Meuser | ||||||
| @@ -407,6 +443,7 @@ James Bursa | |||||||
| James Cheng | James Cheng | ||||||
| James Clancy | James Clancy | ||||||
| James Cone | James Cone | ||||||
|  | James Dury | ||||||
| James Gallagher | James Gallagher | ||||||
| James Griffiths | James Griffiths | ||||||
| James Housley | James Housley | ||||||
| @@ -419,12 +456,14 @@ Jan Koen Annot | |||||||
| Jan Kunder | Jan Kunder | ||||||
| Jan Schaumann | Jan Schaumann | ||||||
| Jan Van Boghout | Jan Van Boghout | ||||||
|  | Jared Jennings | ||||||
| Jared Lundell | Jared Lundell | ||||||
| Jari Sundell | Jari Sundell | ||||||
| Jason Glasgow | Jason Glasgow | ||||||
| Jason Liu | Jason Liu | ||||||
| Jason McDonald | Jason McDonald | ||||||
| Jason S. Priebe | Jason S. Priebe | ||||||
|  | Javier Barroso | ||||||
| Jay Austin | Jay Austin | ||||||
| Jayesh A Shah | Jayesh A Shah | ||||||
| Jaz Fresh | Jaz Fresh | ||||||
| @@ -433,9 +472,11 @@ Jean-Claude Chauve | |||||||
| Jean-Francois Bertrand | Jean-Francois Bertrand | ||||||
| Jean-Louis Lemaire | Jean-Louis Lemaire | ||||||
| Jean-Marc Ranger | Jean-Marc Ranger | ||||||
|  | Jean-Noel Rouvignac | ||||||
| Jean-Philippe Barrette-LaPierre | Jean-Philippe Barrette-LaPierre | ||||||
| Jeff Connelly | Jeff Connelly | ||||||
| Jeff Johnson | Jeff Johnson | ||||||
|  | Jeff King | ||||||
| Jeff Lawson | Jeff Lawson | ||||||
| Jeff Phillips | Jeff Phillips | ||||||
| Jeff Pohlmeyer | Jeff Pohlmeyer | ||||||
| @@ -445,6 +486,7 @@ Jeremy Friesner | |||||||
| Jeremy Huddleston | Jeremy Huddleston | ||||||
| Jerome Muffat-Meridol | Jerome Muffat-Meridol | ||||||
| Jerome Vouillon | Jerome Vouillon | ||||||
|  | Jerry Krinock | ||||||
| Jerry Wu | Jerry Wu | ||||||
| Jes Badwal | Jes Badwal | ||||||
| Jesper Jensen | Jesper Jensen | ||||||
| @@ -469,7 +511,9 @@ Johannes Bauer | |||||||
| John Bradshaw | John Bradshaw | ||||||
| John Crow | John Crow | ||||||
| John Dennis | John Dennis | ||||||
|  | John Dunn | ||||||
| John E. Malmberg | John E. Malmberg | ||||||
|  | John Gardiner Myers | ||||||
| John Janssen | John Janssen | ||||||
| John Joseph Bachir | John Joseph Bachir | ||||||
| John Kelly | John Kelly | ||||||
| @@ -511,6 +555,7 @@ Julien Royer | |||||||
| Jun-ichiro itojun Hagino | Jun-ichiro itojun Hagino | ||||||
| Jurij Smakov | Jurij Smakov | ||||||
| Justin Fletcher | Justin Fletcher | ||||||
|  | Justin Karneges | ||||||
| Jörg Mueller-Tolk | Jörg Mueller-Tolk | ||||||
| Jörn Hartroth | Jörn Hartroth | ||||||
| Kai Engert | Kai Engert | ||||||
| @@ -544,11 +589,13 @@ Kimmo Kinnunen | |||||||
| Kjell Ericson | Kjell Ericson | ||||||
| Kjetil Jacobsen | Kjetil Jacobsen | ||||||
| Klevtsov Vadim | Klevtsov Vadim | ||||||
|  | Konstantin Isakov | ||||||
| Kris Kennaway | Kris Kennaway | ||||||
| Krishnendu Majumdar | Krishnendu Majumdar | ||||||
| Krister Johansen | Krister Johansen | ||||||
| Kristian Gunstone | Kristian Gunstone | ||||||
| Kristian Köhntopp | Kristian Köhntopp | ||||||
|  | Kyle L. Huff | ||||||
| Kyle Sallee | Kyle Sallee | ||||||
| Lachlan O'Dea | Lachlan O'Dea | ||||||
| Larry Campbell | Larry Campbell | ||||||
| @@ -556,6 +603,7 @@ Larry Fahnoe | |||||||
| Lars Buitinck | Lars Buitinck | ||||||
| Lars Gustafsson | Lars Gustafsson | ||||||
| Lars J. Aas | Lars J. Aas | ||||||
|  | Lars Johannesen | ||||||
| Lars Nilsson | Lars Nilsson | ||||||
| Lars Torben Wilson | Lars Torben Wilson | ||||||
| Lau Hang Kin | Lau Hang Kin | ||||||
| @@ -578,6 +626,7 @@ Loren Kirkby | |||||||
| Luca Altea | Luca Altea | ||||||
| Luca Alteas | Luca Alteas | ||||||
| Lucas Adamski | Lucas Adamski | ||||||
|  | Ludovico Cavedon | ||||||
| Lukasz Czekierda | Lukasz Czekierda | ||||||
| Luke Amery | Luke Amery | ||||||
| Luke Call | Luke Call | ||||||
| @@ -589,12 +638,15 @@ Mandy Wu | |||||||
| Manfred Schwarb | Manfred Schwarb | ||||||
| Manuel Massing | Manuel Massing | ||||||
| Marc Boucher | Marc Boucher | ||||||
|  | Marc Deslauriers | ||||||
|  | Marc Doughty | ||||||
| Marc Hoersken | Marc Hoersken | ||||||
| Marc Kleine-Budde | Marc Kleine-Budde | ||||||
| Marcel Raad | Marcel Raad | ||||||
| Marcel Roelofs | Marcel Roelofs | ||||||
| Marcelo Juchem | Marcelo Juchem | ||||||
| Marcin Adamski | Marcin Adamski | ||||||
|  | Marcin Gryszkalis | ||||||
| Marcin Konicki | Marcin Konicki | ||||||
| Marco G. Salvagno | Marco G. Salvagno | ||||||
| Marco Maggi | Marco Maggi | ||||||
| @@ -649,6 +701,7 @@ Maxim Prohorov | |||||||
| Maxime Larocque | Maxime Larocque | ||||||
| Mehmet Bozkurt | Mehmet Bozkurt | ||||||
| Mekonikum | Mekonikum | ||||||
|  | Melissa Mears | ||||||
| Mettgut Jamalla | Mettgut Jamalla | ||||||
| Michael Benedict | Michael Benedict | ||||||
| Michael Calmer | Michael Calmer | ||||||
| @@ -660,6 +713,7 @@ Michael Jahn | |||||||
| Michael Jerris | Michael Jerris | ||||||
| Michael Mealling | Michael Mealling | ||||||
| Michael Mueller | Michael Mueller | ||||||
|  | Michael Osipov | ||||||
| Michael Smith | Michael Smith | ||||||
| Michael Stillwell | Michael Stillwell | ||||||
| Michael Wallner | Michael Wallner | ||||||
| @@ -668,13 +722,16 @@ Michal Gorny | |||||||
| Michal Kowalczyk | Michal Kowalczyk | ||||||
| Michal Marek | Michal Marek | ||||||
| Michele Bini | Michele Bini | ||||||
|  | Miguel Angel | ||||||
| Mihai Ionescu | Mihai Ionescu | ||||||
| Mikael Johansson | Mikael Johansson | ||||||
| Mikael Sennerholm | Mikael Sennerholm | ||||||
| Mike Bytnar | Mike Bytnar | ||||||
| Mike Crowe | Mike Crowe | ||||||
| Mike Dobbs | Mike Dobbs | ||||||
|  | Mike Giancola | ||||||
| Mike Hommey | Mike Hommey | ||||||
|  | Mike Mio | ||||||
| Mike Power | Mike Power | ||||||
| Mike Protts | Mike Protts | ||||||
| Mike Revi | Mike Revi | ||||||
| @@ -684,6 +741,7 @@ Mohamed Lrhazi | |||||||
| Mohun Biswas | Mohun Biswas | ||||||
| Moonesamy | Moonesamy | ||||||
| Myk Taylor | Myk Taylor | ||||||
|  | Nach M. S. | ||||||
| Nathan Coulter | Nathan Coulter | ||||||
| Nathan O'Sullivan | Nathan O'Sullivan | ||||||
| Nathanael Nerode | Nathanael Nerode | ||||||
| @@ -718,6 +776,7 @@ Olaf Flebbe | |||||||
| Olaf Stueben | Olaf Stueben | ||||||
| Olaf Stüben | Olaf Stüben | ||||||
| Oliver Gondža | Oliver Gondža | ||||||
|  | Oliver Kuckertz | ||||||
| Olivier Berger | Olivier Berger | ||||||
| Oren Tirosh | Oren Tirosh | ||||||
| Ori Avtalion | Ori Avtalion | ||||||
| @@ -736,8 +795,10 @@ Patrick Scott | |||||||
| Patrick Smith | Patrick Smith | ||||||
| Patrik Thunstrom | Patrik Thunstrom | ||||||
| Pau Garcia i Quiles | Pau Garcia i Quiles | ||||||
|  | Paul Donohue | ||||||
| Paul Harrington | Paul Harrington | ||||||
| Paul Howarth | Paul Howarth | ||||||
|  | Paul Marks | ||||||
| Paul Marquis | Paul Marquis | ||||||
| Paul Moore | Paul Moore | ||||||
| Paul Nolan | Paul Nolan | ||||||
| @@ -752,6 +813,7 @@ Pedro Neves | |||||||
| Pete Su | Pete Su | ||||||
| Peter Bray | Peter Bray | ||||||
| Peter Forret | Peter Forret | ||||||
|  | Peter Gal | ||||||
| Peter Heuchert | Peter Heuchert | ||||||
| Peter Hjalmarsson | Peter Hjalmarsson | ||||||
| Peter Korsgaard | Peter Korsgaard | ||||||
| @@ -765,6 +827,8 @@ Peter Todd | |||||||
| Peter Verhas | Peter Verhas | ||||||
| Peter Wullinger | Peter Wullinger | ||||||
| Peteris Krumins | Peteris Krumins | ||||||
|  | Petr Bahula | ||||||
|  | Petr Pisar | ||||||
| Phil Blundell | Phil Blundell | ||||||
| Phil Karn | Phil Karn | ||||||
| Phil Lisiecki | Phil Lisiecki | ||||||
| @@ -804,6 +868,7 @@ Reinout van Schouwen | |||||||
| Renato Botelho | Renato Botelho | ||||||
| Renaud Chaillat | Renaud Chaillat | ||||||
| Renaud Duhaut | Renaud Duhaut | ||||||
|  | Renaud Guillard | ||||||
| Rene Bernhardt | Rene Bernhardt | ||||||
| Rene Rebe | Rene Rebe | ||||||
| Reuven Wachtfogel | Reuven Wachtfogel | ||||||
| @@ -847,6 +912,7 @@ Roland Zimmermann | |||||||
| Rolland Dudemaine | Rolland Dudemaine | ||||||
| Roman Koifman | Roman Koifman | ||||||
| Roman Mamedov | Roman Mamedov | ||||||
|  | Romulo A. Ceccon | ||||||
| Ron Zapp | Ron Zapp | ||||||
| Rosimildo da Silva | Rosimildo da Silva | ||||||
| Roy Shan | Roy Shan | ||||||
| @@ -856,6 +922,7 @@ Rutger Hofman | |||||||
| Ryan Chan | Ryan Chan | ||||||
| Ryan Nelson | Ryan Nelson | ||||||
| Ryan Schmidt | Ryan Schmidt | ||||||
|  | Rémy Léone | ||||||
| S. Moonesamy | S. Moonesamy | ||||||
| Salvador Dávila | Salvador Dávila | ||||||
| Salvatore Sorrentino | Salvatore Sorrentino | ||||||
| @@ -881,11 +948,13 @@ Sebastian Rasmussen | |||||||
| Sebastien Willemijns | Sebastien Willemijns | ||||||
| Senthil Raja Velu | Senthil Raja Velu | ||||||
| Sergei Nikulov | Sergei Nikulov | ||||||
|  | Sergey Tatarincev | ||||||
| Sergio Ballestrero | Sergio Ballestrero | ||||||
| Seshubabu Pasam | Seshubabu Pasam | ||||||
| Sh Diao | Sh Diao | ||||||
| Sharad Gupta | Sharad Gupta | ||||||
| Shard | Shard | ||||||
|  | Shawn Landden | ||||||
| Shawn Poulson | Shawn Poulson | ||||||
| Shmulik Regev | Shmulik Regev | ||||||
| Siddhartha Prakash Jain | Siddhartha Prakash Jain | ||||||
| @@ -903,6 +972,7 @@ Stan van de Burgt | |||||||
| Stanislav Ivochkin | Stanislav Ivochkin | ||||||
| Stefan Esser | Stefan Esser | ||||||
| Stefan Krause | Stefan Krause | ||||||
|  | Stefan Neis | ||||||
| Stefan Teleman | Stefan Teleman | ||||||
| Stefan Tomanek | Stefan Tomanek | ||||||
| Stefan Ulrich | Stefan Ulrich | ||||||
| @@ -950,6 +1020,7 @@ Tim Harder | |||||||
| Tim Heckman | Tim Heckman | ||||||
| Tim Newsome | Tim Newsome | ||||||
| Tim Sneddon | Tim Sneddon | ||||||
|  | Timo Sirainen | ||||||
| Tinus van den Berg | Tinus van den Berg | ||||||
| Tobias Rundström | Tobias Rundström | ||||||
| Toby Peterson | Toby Peterson | ||||||
| @@ -967,6 +1038,7 @@ Tom Mueller | |||||||
| Tom Regner | Tom Regner | ||||||
| Tom Wright | Tom Wright | ||||||
| Tom Zerucha | Tom Zerucha | ||||||
|  | Tomas Hoger | ||||||
| Tomas Mlcoch | Tomas Mlcoch | ||||||
| Tomas Pospisek | Tomas Pospisek | ||||||
| Tomas Szepe | Tomas Szepe | ||||||
| @@ -984,7 +1056,9 @@ Traian Nicolescu | |||||||
| Troels Walsted Hansen | Troels Walsted Hansen | ||||||
| Troy Engel | Troy Engel | ||||||
| Tupone Alfredo | Tupone Alfredo | ||||||
|  | Tyler Hall | ||||||
| Ulf Härnhammar | Ulf Härnhammar | ||||||
|  | Ulf Samuelsson | ||||||
| Ulrich Doehner | Ulrich Doehner | ||||||
| Ulrich Zadow | Ulrich Zadow | ||||||
| Venkat Akella | Venkat Akella | ||||||
| @@ -1011,19 +1085,24 @@ Wesley Laxton | |||||||
| Wesley Miaw | Wesley Miaw | ||||||
| Wez Furlong | Wez Furlong | ||||||
| Wilfredo Sanchez | Wilfredo Sanchez | ||||||
|  | Will Dietz | ||||||
| Willem Sparreboom | Willem Sparreboom | ||||||
| Wojciech Zwiefka | Wojciech Zwiefka | ||||||
|  | Wouter Van Rooy | ||||||
| Wu Yongzheng | Wu Yongzheng | ||||||
| Xavier Bouchoux | Xavier Bouchoux | ||||||
|  | Yaakov Selkowitz | ||||||
| Yamada Yasuharu | Yamada Yasuharu | ||||||
| Yang Tse | Yang Tse | ||||||
| Yarram Sunil | Yarram Sunil | ||||||
| Yehoshua Hershberg | Yehoshua Hershberg | ||||||
|  | Yi Huang | ||||||
| Yukihiro Kawada | Yukihiro Kawada | ||||||
| Yuriy Sosov | Yuriy Sosov | ||||||
| Yves Arrouye | Yves Arrouye | ||||||
| Yves Lejeune | Yves Lejeune | ||||||
| Zdenek Pavlas | Zdenek Pavlas | ||||||
|  | Zekun Ni | ||||||
| Zmey Petroff | Zmey Petroff | ||||||
| Zvi Har'El | Zvi Har'El | ||||||
| nk | nk | ||||||
|   | |||||||
							
								
								
									
										82
									
								
								docs/TODO
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								docs/TODO
									
									
									
									
									
								
							| @@ -16,8 +16,7 @@ | |||||||
|  1.3 struct lifreq |  1.3 struct lifreq | ||||||
|  1.4 signal-based resolver timeouts |  1.4 signal-based resolver timeouts | ||||||
|  1.5 get rid of PATH_MAX |  1.5 get rid of PATH_MAX | ||||||
|  1.6 progress callback without doubles |  1.6 Modified buffer size approach | ||||||
|  1.7 Happy Eyeball dual stack connect |  | ||||||
|  |  | ||||||
|  2. libcurl - multi interface |  2. libcurl - multi interface | ||||||
|  2.1 More non-blocking |  2.1 More non-blocking | ||||||
| @@ -39,6 +38,7 @@ | |||||||
|  5.2 support FF3 sqlite cookie files |  5.2 support FF3 sqlite cookie files | ||||||
|  5.3 Rearrange request header order |  5.3 Rearrange request header order | ||||||
|  5.4 HTTP2/SPDY |  5.4 HTTP2/SPDY | ||||||
|  |  5.5 auth= in URLs | ||||||
|  |  | ||||||
|  6. TELNET |  6. TELNET | ||||||
|  6.1 ditch stdin |  6.1 ditch stdin | ||||||
| @@ -48,17 +48,14 @@ | |||||||
|  |  | ||||||
|  7. SMTP |  7. SMTP | ||||||
|  7.1 Pipelining |  7.1 Pipelining | ||||||
|  7.2 Graceful base64 decoding failure |  7.2 Enhanced capability support | ||||||
|  7.3 Enhanced capability support |  | ||||||
|   |   | ||||||
|  8. POP3 |  8. POP3 | ||||||
|  8.1 Pipelining |  8.1 Pipelining | ||||||
|  8.2 Graceful base64 decoding failure |  8.2 Enhanced capability support | ||||||
|  8.3 Enhanced capability support |  | ||||||
|   |   | ||||||
|  9. IMAP |  9. IMAP | ||||||
|  9.1 Graceful base64 decoding failure |  9.1 Enhanced capability support | ||||||
|  9.2 Enhanced capability support |  | ||||||
|   |   | ||||||
|  10. LDAP |  10. LDAP | ||||||
|  10.1 SASL based authentication mechanisms |  10.1 SASL based authentication mechanisms | ||||||
| @@ -157,26 +154,27 @@ | |||||||
|  we need libssh2 to properly tell us when we pass in a too small buffer and |  we need libssh2 to properly tell us when we pass in a too small buffer and | ||||||
|  its current API (as of libssh2 1.2.7) doesn't. |  its current API (as of libssh2 1.2.7) doesn't. | ||||||
|  |  | ||||||
| 1.6 progress callback without doubles | 1.6 Modified buffer size approach | ||||||
|  |  | ||||||
|  The progress callback was introduced way back in the days and the choice to |  Current libcurl allocates a fixed 16K size buffer for download and an | ||||||
|  use doubles in the arguments was possibly good at the time. Today the doubles |  additional 16K for upload. They are always unconditionally part of the easy | ||||||
|  only confuse users and make the amounts less precise. We should introduce |  handle. If CRLF translations are requested, an additional 32K "scratch | ||||||
|  another progress callback option that take precedence over the old one and |  buffer" is allocated. A total of 64K transfer buffers in the worst case. | ||||||
|  have both co-exist for a forseeable time until we can remove the double-using |  | ||||||
|  one. |  | ||||||
|  |  | ||||||
| 1.7 Happy Eyeball dual stack connect |  First, while the handles are not actually in use these buffers could be freed | ||||||
|  |  so that lingering handles just kept in queues or whatever waste less memory. | ||||||
|  |  | ||||||
|  In order to make alternative technologies not suffer when transitioning, like |  Secondly, SFTP is a protocol that needs to handle many ~30K blocks at once | ||||||
|  when introducing IPv6 as an alternative to IPv4 and there are more than one |  since each need to be individually acked and therefore libssh2 must be | ||||||
|  option existing simultaneously there are reasons to reconsider internal |  allowed to send (or receive) many separate ones in parallel to achieve high | ||||||
|  choices. |  transfer speeds. A current libcurl build with a 16K buffer makes that | ||||||
|  |  impossible, but one with a 512K buffer will reach MUCH faster transfers. But | ||||||
|  |  allocating 512K unconditionally for all buffers just in case they would like | ||||||
|  |  to do fast SFTP transfers at some point is not a good solution either. | ||||||
|  |  | ||||||
|  To make libcurl do blazing fast IPv6 in a dual-stack configuration, this needs |  Dynamically allocate buffer size depending on protocol in use in combination | ||||||
|  to be addressed: |  with freeing it after each individual transfer? Other suggestions? | ||||||
|  |  | ||||||
|     http://tools.ietf.org/html/rfc6555 |  | ||||||
|  |  | ||||||
| 2. libcurl - multi interface | 2. libcurl - multi interface | ||||||
|  |  | ||||||
| @@ -287,6 +285,17 @@ | |||||||
|  be a better option, either used directly or wrapped with a more spindly-like |  be a better option, either used directly or wrapped with a more spindly-like | ||||||
|  API. |  API. | ||||||
|  |  | ||||||
|  | 5.5 auth= in URLs | ||||||
|  |  | ||||||
|  |  Add the ability to specify the preferred authentication mechanism to use by | ||||||
|  |  using ;auth=<mech> in the login part of the URL. | ||||||
|  |  | ||||||
|  |  For example: | ||||||
|  |  | ||||||
|  |  http://test:pass;auth=NTLM@example.com would be equivalent to specifing --user | ||||||
|  |  test:pass;auth=NTLM or --user test:pass --ntlm from the command line.  | ||||||
|  |  | ||||||
|  |  Additionally this should be implemented for proxy base URLs as well. | ||||||
|  |  | ||||||
| 6. TELNET | 6. TELNET | ||||||
|  |  | ||||||
| @@ -318,14 +327,7 @@ to provide the data to send. | |||||||
|  |  | ||||||
|  Add support for pipelining emails. |  Add support for pipelining emails. | ||||||
|  |  | ||||||
| 7.2 Graceful base64 decoding failure | 7.2 Enhanced capability support | ||||||
|  |  | ||||||
|  Rather than shutting down the session and returning an error when the |  | ||||||
|  decoding of a base64 encoded authentication response fails, we should |  | ||||||
|  gracefully shutdown the authentication process by sending a * response to the |  | ||||||
|  server as per RFC4954. |  | ||||||
|  |  | ||||||
| 7.3 Enhanced capability support |  | ||||||
|  |  | ||||||
|  Add the ability, for an application that uses libcurl, to obtain the list of |  Add the ability, for an application that uses libcurl, to obtain the list of | ||||||
|  capabilities returned from the EHLO command. |  capabilities returned from the EHLO command. | ||||||
| @@ -336,28 +338,14 @@ to provide the data to send. | |||||||
|  |  | ||||||
|  Add support for pipelining commands. |  Add support for pipelining commands. | ||||||
|  |  | ||||||
| 8.2 Graceful base64 decoding failure | 8.2 Enhanced capability support | ||||||
|  |  | ||||||
|  Rather than shutting down the session and returning an error when the |  | ||||||
|  decoding of a base64 encoded authentication response fails, we should |  | ||||||
|  gracefully shutdown the authentication process by sending a * response to the |  | ||||||
|  server as per RFC5034. |  | ||||||
|   |  | ||||||
| 8.3 Enhanced capability support |  | ||||||
|  |  | ||||||
|  Add the ability, for an application that uses libcurl, to obtain the list of |  Add the ability, for an application that uses libcurl, to obtain the list of | ||||||
|  capabilities returned from the CAPA command. |  capabilities returned from the CAPA command. | ||||||
|  |  | ||||||
| 9. IMAP | 9. IMAP | ||||||
|  |  | ||||||
| 9.1 Graceful base64 decoding failure | 9.1 Enhanced capability support | ||||||
|  |  | ||||||
|  Rather than shutting down the session and returning an error when the |  | ||||||
|  decoding of a base64 encoded authentication response fails, we should |  | ||||||
|  gracefully shutdown the authentication process by sending a * response to the |  | ||||||
|  server as per RFC3501. |  | ||||||
|  |  | ||||||
| 9.2 Enhanced capability support |  | ||||||
|  |  | ||||||
|  Add the ability, for an application that uses libcurl, to obtain the list of |  Add the ability, for an application that uses libcurl, to obtain the list of | ||||||
|  capabilities returned from the CAPABILITY command. |  capabilities returned from the CAPABILITY command. | ||||||
|   | |||||||
							
								
								
									
										252
									
								
								docs/curl.1
									
									
									
									
									
								
							
							
						
						
									
										252
									
								
								docs/curl.1
									
									
									
									
									
								
							| @@ -103,6 +103,18 @@ any response data to the terminal. | |||||||
| If you prefer a progress "bar" instead of the regular meter, \fI-#\fP is your | If you prefer a progress "bar" instead of the regular meter, \fI-#\fP is your | ||||||
| friend. | friend. | ||||||
| .SH OPTIONS | .SH OPTIONS | ||||||
|  | Options start with one or two dashes. Many of the options require an addition | ||||||
|  | value next to it. | ||||||
|  |  | ||||||
|  | The short "single-dash" form of the options, -d for example, may be used with | ||||||
|  | or without a space between it and its value, although a space is a recommended | ||||||
|  | separator. The long "double-dash" form, --data for example, requires a space | ||||||
|  | between it and its value. | ||||||
|  |  | ||||||
|  | Short version options that don't need any additional values can be used | ||||||
|  | immediately next to each other, like for example you can specify all the | ||||||
|  | options -O, -L and -v at once as -OLv. | ||||||
|  |  | ||||||
| In general, all boolean options are enabled with --\fBoption\fP and yet again | In general, all boolean options are enabled with --\fBoption\fP and yet again | ||||||
| disabled with --\fBno-\fPoption. That is, you use the exact same option name | disabled with --\fBno-\fPoption. That is, you use the exact same option name | ||||||
| but prefix it with "no-". However, in this list we mostly only list and show | but prefix it with "no-". However, in this list we mostly only list and show | ||||||
| @@ -113,8 +125,14 @@ same command line option.) | |||||||
| Make curl display progress as a simple progress bar instead of the standard, | Make curl display progress as a simple progress bar instead of the standard, | ||||||
| more informational, meter. | more informational, meter. | ||||||
| .IP "-0, --http1.0" | .IP "-0, --http1.0" | ||||||
| (HTTP) Forces curl to issue its requests using HTTP 1.0 instead of using its | (HTTP) Tells curl to use HTTP version 1.0 instead of using its internally | ||||||
| internally preferred: HTTP 1.1. | preferred: HTTP 1.1. | ||||||
|  | .IP "--http1.1" | ||||||
|  | (HTTP) Tells curl to use HTTP version 1.1. This is the internal default | ||||||
|  | version. (Added in 7.33.0) | ||||||
|  | .IP "--http2.0" | ||||||
|  | (HTTP) Tells curl to issue its requests using HTTP 2.0. This requires that the | ||||||
|  | underlying libcurl was built to support it. (Added in 7.33.0) | ||||||
| .IP "-1, --tlsv1" | .IP "-1, --tlsv1" | ||||||
| (SSL) | (SSL) | ||||||
| Forces curl to use TLS version 1 when negotiating with a remote TLS server. | Forces curl to use TLS version 1 when negotiating with a remote TLS server. | ||||||
| @@ -230,7 +248,9 @@ server sends an unsupported encoding, curl will report an error. | |||||||
| .IP "--connect-timeout <seconds>" | .IP "--connect-timeout <seconds>" | ||||||
| Maximum time in seconds that you allow the connection to the server to take. | Maximum time in seconds that you allow the connection to the server to take. | ||||||
| This only limits the connection phase, once curl has connected this option is | This only limits the connection phase, once curl has connected this option is | ||||||
| of no more use. See also the \fI-m, --max-time\fP option. | of no more use.  Since 7.32.0, this option accepts decimal values, but the | ||||||
|  | actual timeout will decrease in accuracy as the specified timeout increases in | ||||||
|  | decimal precision. See also the \fI-m, --max-time\fP option. | ||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. | If this option is used several times, the last one will be used. | ||||||
| .IP "--create-dirs" | .IP "--create-dirs" | ||||||
| @@ -270,7 +290,8 @@ If you start the data with the letter @, the rest should be a file name to | |||||||
| read the data from, or - if you want curl to read the data from stdin.  The | read the data from, or - if you want curl to read the data from stdin.  The | ||||||
| contents of the file must already be URL-encoded. Multiple files can also be | contents of the file must already be URL-encoded. Multiple files can also be | ||||||
| specified. Posting data from a file named 'foobar' would thus be done with | specified. Posting data from a file named 'foobar' would thus be done with | ||||||
| \fI--data @foobar\fP. | \fI--data\fP @foobar. When --data is told to read from a file like that, | ||||||
|  | carriage returns and newlines will be stripped out. | ||||||
| .IP "-D, --dump-header <file>" | .IP "-D, --dump-header <file>" | ||||||
| Write the protocol headers to the specified file. | Write the protocol headers to the specified file. | ||||||
|  |  | ||||||
| @@ -292,7 +313,7 @@ whatsoever. | |||||||
|  |  | ||||||
| If you start the data with the letter @, the rest should be a filename.  Data | If you start the data with the letter @, the rest should be a filename.  Data | ||||||
| is posted in a similar manner as \fI--data-ascii\fP does, except that newlines | is posted in a similar manner as \fI--data-ascii\fP does, except that newlines | ||||||
| are preserved and conversions are never done. | and carriage returns are preserved and conversions are never done. | ||||||
|  |  | ||||||
| If this option is used several times, the ones following the first will append | If this option is used several times, the ones following the first will append | ||||||
| data as described in \fI-d, --data\fP. | data as described in \fI-d, --data\fP. | ||||||
| @@ -367,6 +388,39 @@ is an alias for \fB--disable-epsv\fP. | |||||||
|  |  | ||||||
| Disabling EPSV only changes the passive behavior. If you want to switch to | Disabling EPSV only changes the passive behavior. If you want to switch to | ||||||
| active mode you need to use \fI-P, --ftp-port\fP. | active mode you need to use \fI-P, --ftp-port\fP. | ||||||
|  | .IP "--dns-interface <interface>" | ||||||
|  | Tell curl to send outgoing DNS requests through <interface>. This option | ||||||
|  | is a counterpart to \fI--interface\fP (which does not affect DNS). The | ||||||
|  | supplied string must be an interface name (not an address). | ||||||
|  |  | ||||||
|  | This option requires that libcurl was built with a resolver backend that | ||||||
|  | supports this operation. The c-ares backend is the only such one. (Added in | ||||||
|  | 7.33.0) | ||||||
|  | .IP "--dns-ipv4-addr <ip-address>" | ||||||
|  | Tell curl to bind to <ip-address> when making IPv4 DNS requests, so that | ||||||
|  | the DNS requests originate from this address. The argument should be a | ||||||
|  | single IPv4 address. | ||||||
|  |  | ||||||
|  | This option requires that libcurl was built with a resolver backend that | ||||||
|  | supports this operation. The c-ares backend is the only such one.  (Added in | ||||||
|  | 7.33.0) | ||||||
|  | .IP "--dns-ipv6-addr <ip-address>" | ||||||
|  | Tell curl to bind to <ip-address> when making IPv6 DNS requests, so that | ||||||
|  | the DNS requests originate from this address. The argument should be a | ||||||
|  | single IPv6 address. | ||||||
|  |  | ||||||
|  | This option requires that libcurl was built with a resolver backend that | ||||||
|  | supports this operation. The c-ares backend is the only such one.  (Added in | ||||||
|  | 7.33.0) | ||||||
|  | .IP "--dns-servers <ip-address,ip-address>" | ||||||
|  | Set the list of DNS servers to be used instead of the system default. | ||||||
|  | The list of IP addresses should be separated with commas. Port numbers | ||||||
|  | may also optionally be given as \fI:<port-number>\fP after each IP | ||||||
|  | address. | ||||||
|  |  | ||||||
|  | This option requires that libcurl was built with a resolver backend that | ||||||
|  | supports this operation. The c-ares backend is the only such one.  (Added in | ||||||
|  | 7.33.0) | ||||||
| .IP "-e, --referer <URL>" | .IP "-e, --referer <URL>" | ||||||
| (HTTP) Sends the "Referer Page" information to the HTTP server. This can also | (HTTP) Sends the "Referer Page" information to the HTTP server. This can also | ||||||
| be set with the \fI-H, --header\fP flag of course.  When used with | be set with the \fI-H, --header\fP flag of course.  When used with | ||||||
| @@ -378,7 +432,8 @@ If this option is used several times, the last one will be used. | |||||||
| .IP "-E, --cert <certificate[:password]>" | .IP "-E, --cert <certificate[:password]>" | ||||||
| (SSL) Tells curl to use the specified client certificate file when getting a | (SSL) Tells curl to use the specified client certificate file when getting a | ||||||
| file with HTTPS, FTPS or another SSL-based protocol. The certificate must be | file with HTTPS, FTPS or another SSL-based protocol. The certificate must be | ||||||
| in PEM format.  If the optional password isn't specified, it will be queried | in PKCS#12 format if using Secure Transport, or PEM format if using any other | ||||||
|  | engine.  If the optional password isn't specified, it will be queried | ||||||
| for on the terminal. Note that this option assumes a \&"certificate" file that | for on the terminal. Note that this option assumes a \&"certificate" file that | ||||||
| is the private key and the private certificate concatenated! See \fI--cert\fP | is the private key and the private certificate concatenated! See \fI--cert\fP | ||||||
| and \fI--key\fP to specify them independently. | and \fI--key\fP to specify them independently. | ||||||
| @@ -393,7 +448,11 @@ nickname contains ":", it needs to be preceded by "\\" so that it is not | |||||||
| recognized as password delimiter.  If the nickname contains "\\", it needs to | recognized as password delimiter.  If the nickname contains "\\", it needs to | ||||||
| be escaped as "\\\\" so that it is not recognized as an escape character. | be escaped as "\\\\" so that it is not recognized as an escape character. | ||||||
|  |  | ||||||
| (iOS and Mac OS X only) If curl is built against Secure Transport, then the certificate string must match the name of a certificate that's in the system or user keychain. The private key corresponding to the certificate, and certificate chain (if any),  must also be present in the keychain. | (iOS and Mac OS X only) If curl is built against Secure Transport, then the | ||||||
|  | certificate string can either be the name of a certificate/private key in the | ||||||
|  | system or user keychain, or the path to a PKCS#12-encoded certificate and | ||||||
|  | private key. If you want to use a file from the current directory, please | ||||||
|  | precede it with "./" prefix, in order to avoid confusion with a nickname. | ||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. | If this option is used several times, the last one will be used. | ||||||
| .IP "--engine <name>" | .IP "--engine <name>" | ||||||
| @@ -587,10 +646,10 @@ you can specify URLs that contain the letters {}[] without having them being | |||||||
| interpreted by curl itself. Note that these letters are not normal legal URL | interpreted by curl itself. Note that these letters are not normal legal URL | ||||||
| contents but they should be encoded according to the URI standard. | contents but they should be encoded according to the URI standard. | ||||||
| .IP "-G, --get" | .IP "-G, --get" | ||||||
| When used, this option will make all data specified with \fI-d, --data\fP or | When used, this option will make all data specified with \fI-d, --data\fP, | ||||||
| \fI--data-binary\fP to be used in an HTTP GET request instead of the POST | \fI--data-binary\fP or \fI--data-urlencode\fP to be used in an HTTP GET | ||||||
| request that otherwise would be used. The data will be appended to the URL | request instead of the POST request that otherwise would be used. The data | ||||||
| with a '?' separator. | will be appended to the URL with a '?' separator. | ||||||
|  |  | ||||||
| If used in combination with -I, the POST data will instead be appended to the | If used in combination with -I, the POST data will instead be appended to the | ||||||
| URL with a HEAD request. | URL with a HEAD request. | ||||||
| @@ -652,6 +711,9 @@ cookies when they're closed down. | |||||||
| (HTTP) This option tells the \fI-O, --remote-name\fP option to use the | (HTTP) This option tells the \fI-O, --remote-name\fP option to use the | ||||||
| server-specified Content-Disposition filename instead of extracting a filename | server-specified Content-Disposition filename instead of extracting a filename | ||||||
| from the URL. | from the URL. | ||||||
|  |  | ||||||
|  | There's no attempt to decode %-sequences (yet) in the provided file name, so | ||||||
|  | this option may provide you with rather unexpected file names. | ||||||
| .IP "-k, --insecure" | .IP "-k, --insecure" | ||||||
| (SSL) This option explicitly allows curl to perform "insecure" SSL connections | (SSL) This option explicitly allows curl to perform "insecure" SSL connections | ||||||
| and transfers. All SSL connections are attempted to be made secure by using | and transfers. All SSL connections are attempted to be made secure by using | ||||||
| @@ -663,16 +725,21 @@ See this online resource for further details: | |||||||
| .IP "-K, --config <config file>" | .IP "-K, --config <config file>" | ||||||
| Specify which config file to read curl arguments from. The config file is a | Specify which config file to read curl arguments from. The config file is a | ||||||
| text file in which command line arguments can be written which then will be | text file in which command line arguments can be written which then will be | ||||||
| used as if they were written on the actual command line. Options and their | used as if they were written on the actual command line. | ||||||
| parameters must be specified on the same config file line, separated by |  | ||||||
| whitespace, colon, the equals sign or any combination thereof (however, | Options and their parameters must be specified on the same config file line, | ||||||
| the preferred separator is the equals sign). If the parameter is to contain | separated by whitespace, colon, or the equals sign. Long option names can | ||||||
| whitespace, the parameter must be enclosed within quotes. Within double | optionally be given in the config file without the initial double dashes and | ||||||
| quotes, the following escape sequences are available: \\\\, \\", \\t, \\n, | if so, the colon or equals characters can be used as separators. If the option | ||||||
| \\r and \\v. A backslash preceding any other letter is ignored. If the | is specified with one or two dashes, there can be no colon or equals character | ||||||
| first column of a config line is a '#' character, the rest of the line will be | between the option and its parameter. | ||||||
| treated as a comment. Only write one option per physical line in the config |  | ||||||
| file. | If the parameter is to contain whitespace, the parameter must be enclosed | ||||||
|  | within quotes. Within double quotes, the following escape sequences are | ||||||
|  | available: \\\\, \\", \\t, \\n, \\r and \\v. A backslash preceding any other | ||||||
|  | letter is ignored. If the first column of a config line is a '#' character, | ||||||
|  | the rest of the line will be treated as a comment. Only write one option per | ||||||
|  | physical line in the config file. | ||||||
|  |  | ||||||
| Specify the filename to -K, --config as '-' to make curl read the file from | Specify the filename to -K, --config as '-' to make curl read the file from | ||||||
| stdin. | stdin. | ||||||
| @@ -683,9 +750,6 @@ line. So, it could look similar to this: | |||||||
|  |  | ||||||
| url = "http://curl.haxx.se/docs/" | url = "http://curl.haxx.se/docs/" | ||||||
|  |  | ||||||
| Long option names can optionally be given in the config file without the |  | ||||||
| initial double dashes. |  | ||||||
|  |  | ||||||
| When curl is invoked, it always (unless \fI-q\fP is used) checks for a default | When curl is invoked, it always (unless \fI-q\fP is used) checks for a default | ||||||
| config file and uses it if found. The default config file is checked for in | config file and uses it if found. The default config file is checked for in | ||||||
| the following places in this order: | the following places in this order: | ||||||
| @@ -747,15 +811,23 @@ see if your curl supports it. | |||||||
| If this option is used several times, the last one will be used. | If this option is used several times, the last one will be used. | ||||||
| .IP "-l, --list-only" | .IP "-l, --list-only" | ||||||
| (FTP) | (FTP) | ||||||
| When listing an FTP directory, this switch forces a name-only view. | When listing an FTP directory, this switch forces a name-only view. This is | ||||||
| Especially useful if you want to machine-parse the contents of an FTP | especially useful if the user wants to machine-parse the contents of an FTP | ||||||
| directory since the normal directory view doesn't use a standard look | directory since the normal directory view doesn't use a standard look or | ||||||
| or format. | format. When used like this, the option causes a NLST command to be sent to | ||||||
|  | the server instead of LIST. | ||||||
|  |  | ||||||
| This option causes an FTP NLST command to be sent.  Some FTP servers | Note: Some FTP servers list only files in their response to NLST; they do not | ||||||
| list only files in their response to NLST; they do not include | include sub-directories and symbolic links. | ||||||
| subdirectories and symbolic links. |  | ||||||
|  |  | ||||||
|  | (POP3) | ||||||
|  | When retrieving a specific email from POP3, this switch forces a LIST command | ||||||
|  | to be performed instead of RETR. This is particularly useful if the user wants | ||||||
|  | to see if a specific message id exists on the server and what size it is. | ||||||
|  |  | ||||||
|  | Note: When combined with \fI-X, --request <command>\fP, this option can be used | ||||||
|  | to send an UIDL command instead, so the user may use the email's unique | ||||||
|  | identifier rather than it's message id to make the request. (Added in 7.21.5) | ||||||
| .IP "-L, --location" | .IP "-L, --location" | ||||||
| (HTTP/HTTPS) If the server reports that the requested page has moved to a | (HTTP/HTTPS) If the server reports that the requested page has moved to a | ||||||
| different location (indicated with a Location: header and a 3XX response code), | different location (indicated with a Location: header and a 3XX response code), | ||||||
| @@ -810,7 +882,10 @@ Basic authentication). | |||||||
| .IP "-m, --max-time <seconds>" | .IP "-m, --max-time <seconds>" | ||||||
| Maximum time in seconds that you allow the whole operation to take.  This is | Maximum time in seconds that you allow the whole operation to take.  This is | ||||||
| useful for preventing your batch jobs from hanging for hours due to slow | useful for preventing your batch jobs from hanging for hours due to slow | ||||||
| networks or links going down.  See also the \fI--connect-timeout\fP option. | networks or links going down.  Since 7.32.0, this option accepts decimal | ||||||
|  | values, but the actual timeout will decrease in accuracy as the specified | ||||||
|  | timeout increases in decimal precision.  See also the \fI--connect-timeout\fP | ||||||
|  | option. | ||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. | If this option is used several times, the last one will be used. | ||||||
| .IP "--mail-auth <address>" | .IP "--mail-auth <address>" | ||||||
| @@ -832,10 +907,18 @@ return with exit code 63. | |||||||
| files this option has no effect even if the file transfer ends up being larger | files this option has no effect even if the file transfer ends up being larger | ||||||
| than this given limit. This concerns both FTP and HTTP transfers. | than this given limit. This concerns both FTP and HTTP transfers. | ||||||
| .IP "--mail-rcpt <address>" | .IP "--mail-rcpt <address>" | ||||||
| (SMTP) Specify a single address that the given mail should get sent to. This | (SMTP) Specify a single address, user name or mailing list name. | ||||||
| option can be used multiple times to specify many recipients. |  | ||||||
|  |  | ||||||
| (Added in 7.20.0) | When performing a mail transfer, the recipient should specify a valid email | ||||||
|  | address to send the mail to. (Added in 7.20.0) | ||||||
|  |  | ||||||
|  | When performing an address verification (VRFY command), the recipient should be | ||||||
|  | specified as the user name or user name and domain (as per Section 3.5 of | ||||||
|  | RFC5321). (Added in 7.34.0) | ||||||
|  |  | ||||||
|  | When performing a mailing list expand (EXPN command), the recipient should be | ||||||
|  | specified using the mailing list name, such as "Friends" or "London-Office". | ||||||
|  | (Added in 7.34.0) | ||||||
| .IP "--max-redirs <num>" | .IP "--max-redirs <num>" | ||||||
| Set maximum number of redirection-followings allowed. If \fI-L, --location\fP | Set maximum number of redirection-followings allowed. If \fI-L, --location\fP | ||||||
| is used, this option can be used to prevent curl from following redirections | is used, this option can be used to prevent curl from following redirections | ||||||
| @@ -991,7 +1074,19 @@ Consequentially, the file will be saved in the current working directory. If | |||||||
| you want the file saved in a different directory, make sure you change current | you want the file saved in a different directory, make sure you change current | ||||||
| working directory before you invoke curl with the \fB-O, --remote-name\fP flag! | working directory before you invoke curl with the \fB-O, --remote-name\fP flag! | ||||||
|  |  | ||||||
|  | There is no URL decoding done on the file name. If it has %20 or other URL | ||||||
|  | encoded parts of the name, they will end up as-is as file name. | ||||||
|  |  | ||||||
| You may use this option as many times as the number of URLs you have. | You may use this option as many times as the number of URLs you have. | ||||||
|  | .IP "--oauth2-bearer" | ||||||
|  | (IMAP, POP3, SMTP) | ||||||
|  | Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token | ||||||
|  | is used in conjunction with the user name which can be specified as part of the | ||||||
|  | \fI--url\fP or \fI-u, --user\fP options. | ||||||
|  |  | ||||||
|  | The Bearer Token and user name are formatted according to RFC 6750. | ||||||
|  |  | ||||||
|  | If this option is used several times, the last one will be used. | ||||||
| .IP "-p, --proxytunnel" | .IP "-p, --proxytunnel" | ||||||
| When an HTTP proxy is used (\fI-x, --proxy\fP), this option will cause non-HTTP | When an HTTP proxy is used (\fI-x, --proxy\fP), this option will cause non-HTTP | ||||||
| protocols to attempt to tunnel through the proxy instead of merely using it to | protocols to attempt to tunnel through the proxy instead of merely using it to | ||||||
| @@ -1043,6 +1138,13 @@ ubiquitous in web browsers, so curl does the conversion by default to maintain | |||||||
| consistency. However, a server may require a POST to remain a POST after such | consistency. However, a server may require a POST to remain a POST after such | ||||||
| a redirection. This option is meaningful only when using \fI-L, --location\fP | a redirection. This option is meaningful only when using \fI-L, --location\fP | ||||||
| (Added in 7.19.1) | (Added in 7.19.1) | ||||||
|  | .IP "--post303" | ||||||
|  | (HTTP) Tells curl to respect RFC 2616/10.3.2 and not convert POST requests | ||||||
|  | into GET requests when following a 303 redirection. The non-RFC behaviour is | ||||||
|  | ubiquitous in web browsers, so curl does the conversion by default to maintain | ||||||
|  | consistency. However, a server may require a POST to remain a POST after such | ||||||
|  | a redirection. This option is meaningful only when using \fI-L, --location\fP | ||||||
|  | (Added in 7.26.0) | ||||||
| .IP "--proto <protocols>" | .IP "--proto <protocols>" | ||||||
| Tells curl to use the listed protocols for its initial retrieval. Protocols | Tells curl to use the listed protocols for its initial retrieval. Protocols | ||||||
| are evaluated left to right, are comma separated, and are each a protocol | are evaluated left to right, are comma separated, and are each a protocol | ||||||
| @@ -1280,6 +1382,9 @@ If this option is used several times, the last one will be used. | |||||||
| Silent or quiet mode. Don't show progress meter or error messages.  Makes Curl | Silent or quiet mode. Don't show progress meter or error messages.  Makes Curl | ||||||
| mute. It will still output the data you ask for, potentially even to the | mute. It will still output the data you ask for, potentially even to the | ||||||
| terminal/stdout unless you redirect it. | terminal/stdout unless you redirect it. | ||||||
|  | .IP "--sasl-ir" | ||||||
|  | Enable initial response in SASL authentication. | ||||||
|  | (Added in 7.31.0) | ||||||
| .IP "-S, --show-error" | .IP "-S, --show-error" | ||||||
| When used with \fI-s\fP it makes curl show an error message if it fails. | When used with \fI-s\fP it makes curl show an error message if it fails. | ||||||
| .IP "--ssl" | .IP "--ssl" | ||||||
| @@ -1418,14 +1523,26 @@ Set TLS authentication type. Currently, the only supported option is "SRP", | |||||||
| for TLS-SRP (RFC 5054). If \fI--tlsuser\fP and \fI--tlspassword\fP are | for TLS-SRP (RFC 5054). If \fI--tlsuser\fP and \fI--tlspassword\fP are | ||||||
| specified but \fI--tlsauthtype\fP is not, then this option defaults to "SRP". | specified but \fI--tlsauthtype\fP is not, then this option defaults to "SRP". | ||||||
| (Added in 7.21.4) | (Added in 7.21.4) | ||||||
| .IP "--tlsuser <user>" |  | ||||||
| Set username for use with the TLS authentication method specified with |  | ||||||
| \fI--tlsauthtype\fP. Requires that \fI--tlspassword\fP also be set.  (Added in |  | ||||||
| 7.21.4) |  | ||||||
| .IP "--tlspassword <password>" | .IP "--tlspassword <password>" | ||||||
| Set password for use with the TLS authentication method specified with | Set password for use with the TLS authentication method specified with | ||||||
| \fI--tlsauthtype\fP. Requires that \fI--tlsuser\fP also be set.  (Added in | \fI--tlsauthtype\fP. Requires that \fI--tlsuser\fP also be set.  (Added in | ||||||
| 7.21.4) | 7.21.4) | ||||||
|  | .IP "--tlsuser <user>" | ||||||
|  | Set username for use with the TLS authentication method specified with | ||||||
|  | \fI--tlsauthtype\fP. Requires that \fI--tlspassword\fP also be set.  (Added in | ||||||
|  | 7.21.4) | ||||||
|  | .IP "--tlsv1.0" | ||||||
|  | (SSL) | ||||||
|  | Forces curl to use TLS version 1.0 when negotiating with a remote TLS server. | ||||||
|  | (Added in 7.34.0) | ||||||
|  | .IP "--tlsv1.1" | ||||||
|  | (SSL) | ||||||
|  | Forces curl to use TLS version 1.1 when negotiating with a remote TLS server. | ||||||
|  | (Added in 7.34.0) | ||||||
|  | .IP "--tlsv1.2" | ||||||
|  | (SSL) | ||||||
|  | Forces curl to use TLS version 1.2 when negotiating with a remote TLS server. | ||||||
|  | (Added in 7.34.0) | ||||||
| .IP "--tr-encoding" | .IP "--tr-encoding" | ||||||
| (HTTP) Request a compressed Transfer-Encoding response using one of the | (HTTP) Request a compressed Transfer-Encoding response using one of the | ||||||
| algorithms curl supports, and uncompress the data while receiving it. | algorithms curl supports, and uncompress the data while receiving it. | ||||||
| @@ -1455,16 +1572,23 @@ If this option is used several times, the last one will be used. | |||||||
| .IP "--trace-time" | .IP "--trace-time" | ||||||
| Prepends a time stamp to each trace or verbose line that curl displays. | Prepends a time stamp to each trace or verbose line that curl displays. | ||||||
| (Added in 7.14.0) | (Added in 7.14.0) | ||||||
| .IP "-u, --user <user:password>" | .IP "-u, --user <user:password;options>" | ||||||
| Specify the user name and password to use for server authentication. Overrides | Specify the user name, password and optional login options to use for server | ||||||
| \fI-n, --netrc\fP and \fI--netrc-optional\fP. | authentication. Overrides \fI-n, --netrc\fP and \fI--netrc-optional\fP. | ||||||
|  |  | ||||||
| If you just give the user name (without entering a colon) curl will prompt for | If you simply specify the user name, with or without the login options, curl | ||||||
| a password. | will prompt for a password. | ||||||
|  |  | ||||||
| If you use an SSPI-enabled curl binary and do NTLM authentication, you can | If you use an SSPI-enabled curl binary and perform NTLM authentication, you | ||||||
| force curl to pick up the user name and password from your environment by | can force curl to select the user name and password from your environment by | ||||||
| simply specifying a single colon with this option: "-u :". | simply specifying a single colon with this option: "-u :" or by specfying the | ||||||
|  | login options on their own, for example "-u ;auth=NTLM". | ||||||
|  |  | ||||||
|  | You can use the optional login options part to specify protocol specific | ||||||
|  | options that may be used during authentication. At present only IMAP, POP3 and | ||||||
|  | SMTP support login options as part of the user login information. For more | ||||||
|  | information about the login options please see RFC 2384, RFC 5092 and IETF | ||||||
|  | draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).  | ||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. | If this option is used several times, the last one will be used. | ||||||
| .IP "-U, --proxy-user <user:password>" | .IP "-U, --proxy-user <user:password>" | ||||||
| @@ -1625,8 +1749,16 @@ to follow location: headers. | |||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. | If this option is used several times, the last one will be used. | ||||||
| .IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>" | .IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>" | ||||||
| Use the specified HTTP proxy. If the port number is not specified, it is | Use the specified proxy. | ||||||
| assumed at port 1080. |  | ||||||
|  | The proxy string can be specified with a protocol:// prefix to specify | ||||||
|  | alternative proxy protocols. Use socks4://, socks4a://, socks5:// or | ||||||
|  | socks5h:// to request the specific SOCKS version to be used. No protocol | ||||||
|  | specified, http:// and all others will be treated as HTTP proxies. (The | ||||||
|  | protocol support was added in curl 7.21.7) | ||||||
|  |  | ||||||
|  | If the port number is not specified in the proxy string, it is assumed to be | ||||||
|  | 1080. | ||||||
|  |  | ||||||
| This option overrides existing environment variables that set the proxy to | This option overrides existing environment variables that set the proxy to | ||||||
| use. If there's an environment variable setting a proxy, you can set proxy to | use. If there's an environment variable setting a proxy, you can set proxy to | ||||||
| @@ -1645,11 +1777,6 @@ The proxy host can be specified the exact same way as the proxy environment | |||||||
| variables, including the protocol prefix (http://) and the embedded user + | variables, including the protocol prefix (http://) and the embedded user + | ||||||
| password. | password. | ||||||
|  |  | ||||||
| From 7.21.7, the proxy string may be specified with a protocol:// prefix to |  | ||||||
| specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or |  | ||||||
| socks5h:// to request the specific SOCKS version to be used. No protocol |  | ||||||
| specified, http:// and all others will be treated as HTTP proxies. |  | ||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. | If this option is used several times, the last one will be used. | ||||||
| .IP "-X, --request <command>" | .IP "-X, --request <command>" | ||||||
| (HTTP) Specifies a custom request method to use when communicating with the | (HTTP) Specifies a custom request method to use when communicating with the | ||||||
| @@ -1671,11 +1798,20 @@ option. | |||||||
| Specifies a custom FTP command to use instead of LIST when doing file lists | Specifies a custom FTP command to use instead of LIST when doing file lists | ||||||
| with FTP. | with FTP. | ||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. | (POP3) | ||||||
|  | Specifies a custom POP3 command to use instead of LIST or RETR. (Added in | ||||||
|  | 7.26.0) | ||||||
|  |  | ||||||
|  | (IMAP) | ||||||
|  | Specifies a custom IMAP command to use insead of LIST. (Added in 7.30.0) | ||||||
|  |  | ||||||
|  | (SMTP) | ||||||
|  | Specifies a custom SMTP command to use instead of HELP or VRFY. (Added in 7.34.0) | ||||||
|  |  | ||||||
|  | If this option is used several times, the last one will be used. | ||||||
| .IP "--xattr" | .IP "--xattr" | ||||||
| When saving output to a file, this option tells curl to store certain file | When saving output to a file, this option tells curl to store certain file | ||||||
| metadata in extened file attributes. Currently, the URL is stored in the | metadata in extended file attributes. Currently, the URL is stored in the | ||||||
| xdg.origin.url attribute and, for HTTP, the content type is stored in | xdg.origin.url attribute and, for HTTP, the content type is stored in | ||||||
| the mime_type attribute. If the file system does not support extended | the mime_type attribute. If the file system does not support extended | ||||||
| attributes, a warning is issued. | attributes, a warning is issued. | ||||||
| @@ -1695,7 +1831,7 @@ speed-time seconds it gets aborted. speed-time is set with \fI-y\fP and is 30 | |||||||
| if not set. | if not set. | ||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. | If this option is used several times, the last one will be used. | ||||||
| .IP "-z/--time-cond <date expression>|<file>" | .IP "-z, --time-cond <date expression>|<file>" | ||||||
| (HTTP/FTP) Request a file that has been modified later than the given time and | (HTTP/FTP) Request a file that has been modified later than the given time and | ||||||
| date, or one that has been modified before that time. The <date expression> | date, or one that has been modified before that time. The <date expression> | ||||||
| can be all sorts of date strings or if it doesn't match any internal ones, it | can be all sorts of date strings or if it doesn't match any internal ones, it | ||||||
| @@ -1965,6 +2101,8 @@ RTSP: mismatch of Session Identifiers | |||||||
| unable to parse FTP file list | unable to parse FTP file list | ||||||
| .IP 88 | .IP 88 | ||||||
| FTP chunk callback reported error | FTP chunk callback reported error | ||||||
|  | .IP 89 | ||||||
|  | No connection available, the session will be queued | ||||||
| .IP XX | .IP XX | ||||||
| More error codes will appear here in future releases. The existing ones | More error codes will appear here in future releases. The existing ones | ||||||
| are meant to never change. | are meant to never change. | ||||||
|   | |||||||
| @@ -5,8 +5,7 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \ | |||||||
|   persistant post-callback postit2 sepheaders simple simplepost simplessl  \ |   persistant post-callback postit2 sepheaders simple simplepost simplessl  \ | ||||||
|   sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \ |   sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \ | ||||||
|   smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \ |   smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \ | ||||||
|   progressfunc pop3s pop3slist imap url2file sftpget ftpsget \ |   progressfunc pop3s pop3slist imap url2file sftpget ftpsget postinmemory | ||||||
|   usercertinmem |  | ||||||
|  |  | ||||||
| # These examples require external dependencies that may not be commonly | # These examples require external dependencies that may not be commonly | ||||||
| # available on POSIX systems, so don't bother attempting to compile them here. | # available on POSIX systems, so don't bother attempting to compile them here. | ||||||
| @@ -14,4 +13,4 @@ COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.c	   \ | |||||||
|   ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c	   \ |   ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c	   \ | ||||||
|   opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \ |   opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \ | ||||||
|   smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \ |   smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \ | ||||||
|   multi-uv.c xmlstream.c |   multi-uv.c xmlstream.c usercertinmem.c sessioninfo.c | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -98,10 +98,6 @@ int main(void) | |||||||
|      * bytes big and contains the remote file. |      * bytes big and contains the remote file. | ||||||
|      * |      * | ||||||
|      * Do something nice with it! |      * Do something nice with it! | ||||||
|      * |  | ||||||
|      * You should be aware of the fact that at this point we might have an |  | ||||||
|      * allocated data block, and nothing has yet deallocated that data. So when |  | ||||||
|      * you're done with it, you should free() it as a nice application. |  | ||||||
|      */ |      */ | ||||||
|  |  | ||||||
|     printf("%lu bytes retrieved\n", (long)chunk.size); |     printf("%lu bytes retrieved\n", (long)chunk.size); | ||||||
|   | |||||||
| @@ -22,8 +22,6 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #include <unistd.h> |  | ||||||
|  |  | ||||||
| #include <curl/curl.h> | #include <curl/curl.h> | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -59,7 +57,6 @@ int main(int argc, char **argv) | |||||||
|   CURL *curl; |   CURL *curl; | ||||||
|   CURLcode res; |   CURLcode res; | ||||||
|   FILE * hd_src ; |   FILE * hd_src ; | ||||||
|   int hd ; |  | ||||||
|   struct stat file_info; |   struct stat file_info; | ||||||
|  |  | ||||||
|   char *file; |   char *file; | ||||||
| @@ -72,9 +69,7 @@ int main(int argc, char **argv) | |||||||
|   url = argv[2]; |   url = argv[2]; | ||||||
|  |  | ||||||
|   /* get the file size of the local file */ |   /* get the file size of the local file */ | ||||||
|   hd = open(file, O_RDONLY) ; |   stat(file, &file_info); | ||||||
|   fstat(hd, &file_info); |  | ||||||
|   close(hd) ; |  | ||||||
|  |  | ||||||
|   /* get a FILE * of the same file, could also be made with |   /* get a FILE * of the same file, could also be made with | ||||||
|      fdopen() from the previous descriptor, but hey this is just |      fdopen() from the previous descriptor, but hey this is just | ||||||
|   | |||||||
							
								
								
									
										111
									
								
								docs/examples/postinmemory.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								docs/examples/postinmemory.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | /*************************************************************************** | ||||||
|  |  *                                  _   _ ____  _ | ||||||
|  |  *  Project                     ___| | | |  _ \| | | ||||||
|  |  *                             / __| | | | |_) | | | ||||||
|  |  *                            | (__| |_| |  _ <| |___ | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  |  * This software is licensed as described in the file COPYING, which | ||||||
|  |  * you should have received as part of this distribution. The terms | ||||||
|  |  * are also available at http://curl.haxx.se/docs/copyright.html. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the COPYING file. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  ***************************************************************************/ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <curl/curl.h> | ||||||
|  |  | ||||||
|  | struct MemoryStruct { | ||||||
|  |   char *memory; | ||||||
|  |   size_t size; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static size_t | ||||||
|  | WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) | ||||||
|  | { | ||||||
|  |   size_t realsize = size * nmemb; | ||||||
|  |   struct MemoryStruct *mem = (struct MemoryStruct *)userp; | ||||||
|  |  | ||||||
|  |   mem->memory = realloc(mem->memory, mem->size + realsize + 1); | ||||||
|  |   if(mem->memory == NULL) { | ||||||
|  |     /* out of memory! */ | ||||||
|  |     printf("not enough memory (realloc returned NULL)\n"); | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   memcpy(&(mem->memory[mem->size]), contents, realsize); | ||||||
|  |   mem->size += realsize; | ||||||
|  |   mem->memory[mem->size] = 0; | ||||||
|  |  | ||||||
|  |   return realsize; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(void) | ||||||
|  | { | ||||||
|  |   CURL *curl; | ||||||
|  |   CURLcode res; | ||||||
|  |   struct MemoryStruct chunk; | ||||||
|  |   static const char *postthis="Field=1&Field=2&Field=3"; | ||||||
|  |  | ||||||
|  |   chunk.memory = malloc(1);  /* will be grown as needed by realloc above */ | ||||||
|  |   chunk.size = 0;    /* no data at this point */ | ||||||
|  |  | ||||||
|  |   curl_global_init(CURL_GLOBAL_ALL); | ||||||
|  |   curl = curl_easy_init(); | ||||||
|  |   if(curl) { | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.org/"); | ||||||
|  |  | ||||||
|  |     /* send all data to this function  */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); | ||||||
|  |  | ||||||
|  |     /* we pass our 'chunk' struct to the callback function */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); | ||||||
|  |  | ||||||
|  |     /* some servers don't like requests that are made without a user-agent | ||||||
|  |        field, so we provide one */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis); | ||||||
|  |  | ||||||
|  |     /* if we don't provide POSTFIELDSIZE, libcurl will strlen() by | ||||||
|  |        itself */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis)); | ||||||
|  |  | ||||||
|  |     /* Perform the request, res will get the return code */ | ||||||
|  |     res = curl_easy_perform(curl); | ||||||
|  |     /* Check for errors */ | ||||||
|  |     if(res != CURLE_OK) { | ||||||
|  |       fprintf(stderr, "curl_easy_perform() failed: %s\n", | ||||||
|  |               curl_easy_strerror(res)); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       /* | ||||||
|  |        * Now, our chunk.memory points to a memory block that is chunk.size | ||||||
|  |        * bytes big and contains the remote file. | ||||||
|  |        * | ||||||
|  |        * Do something nice with it! | ||||||
|  |        */ | ||||||
|  |       printf("%s\n",chunk.memory); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* always cleanup */ | ||||||
|  |     curl_easy_cleanup(curl); | ||||||
|  |  | ||||||
|  |     if(chunk.memory) | ||||||
|  |       free(chunk.memory); | ||||||
|  |  | ||||||
|  |     /* we're done with libcurl, so clean it up */ | ||||||
|  |     curl_global_cleanup(); | ||||||
|  |   } | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -30,9 +30,10 @@ struct myprogress { | |||||||
|   CURL *curl; |   CURL *curl; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int progress(void *p, | /* this is how the CURLOPT_XFERINFOFUNCTION callback works */ | ||||||
|                     double dltotal, double dlnow, | static int xferinfo(void *p, | ||||||
|                     double ultotal, double ulnow) |                     curl_off_t dltotal, curl_off_t dlnow, | ||||||
|  |                     curl_off_t ultotal, curl_off_t ulnow) | ||||||
| { | { | ||||||
|   struct myprogress *myp = (struct myprogress *)p; |   struct myprogress *myp = (struct myprogress *)p; | ||||||
|   CURL *curl = myp->curl; |   CURL *curl = myp->curl; | ||||||
| @@ -48,7 +49,9 @@ static int progress(void *p, | |||||||
|     fprintf(stderr, "TOTAL TIME: %f \r\n", curtime); |     fprintf(stderr, "TOTAL TIME: %f \r\n", curtime); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   fprintf(stderr, "UP: %g of %g  DOWN: %g of %g\r\n", |   fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T | ||||||
|  |           "  DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T | ||||||
|  |           "\r\n", | ||||||
|           ulnow, ultotal, dlnow, dltotal); |           ulnow, ultotal, dlnow, dltotal); | ||||||
|  |  | ||||||
|   if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES) |   if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES) | ||||||
| @@ -56,6 +59,19 @@ static int progress(void *p, | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* for libcurl older than 7.32.0 (CURLOPT_PROGRESSFUNCTION) */ | ||||||
|  | static int older_progress(void *p, | ||||||
|  |                           double dltotal, double dlnow, | ||||||
|  |                           double ultotal, double ulnow) | ||||||
|  | { | ||||||
|  |   return xferinfo(p, | ||||||
|  |                   (curl_off_t)dltotal, | ||||||
|  |                   (curl_off_t)dlnow, | ||||||
|  |                   (curl_off_t)ultotal, | ||||||
|  |                   (curl_off_t)ulnow); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| int main(void) | int main(void) | ||||||
| { | { | ||||||
|   CURL *curl; |   CURL *curl; | ||||||
| @@ -68,9 +84,28 @@ int main(void) | |||||||
|     prog.curl = curl; |     prog.curl = curl; | ||||||
|  |  | ||||||
|     curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/"); |     curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/"); | ||||||
|     curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress); |  | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, older_progress); | ||||||
|     /* pass the struct pointer into the progress function */ |     /* pass the struct pointer into the progress function */ | ||||||
|     curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog); |     curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog); | ||||||
|  |  | ||||||
|  | #if LIBCURL_VERSION_NUM >= 0x072000 | ||||||
|  |     /* xferinfo was introduced in 7.32.0, no earlier libcurl versions will | ||||||
|  |        compile as they won't have the symbols around. | ||||||
|  |  | ||||||
|  |        If built with a newer libcurl, but running with an older libcurl: | ||||||
|  |        curl_easy_setopt() will fail in run-time trying to set the new | ||||||
|  |        callback, making the older callback get used. | ||||||
|  |  | ||||||
|  |        New libcurls will prefer the new callback and instead use that one even | ||||||
|  |        if both callbacks are set. */ | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); | ||||||
|  |     /* pass the struct pointer into the xferinfo function, note that this is | ||||||
|  |        an alias to CURLOPT_PROGRESSDATA */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); |     curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); | ||||||
|     res = curl_easy_perform(curl); |     res = curl_easy_perform(curl); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										105
									
								
								docs/examples/sessioninfo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								docs/examples/sessioninfo.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | |||||||
|  | /*************************************************************************** | ||||||
|  |  *                                  _   _ ____  _ | ||||||
|  |  *  Project                     ___| | | |  _ \| | | ||||||
|  |  *                             / __| | | | |_) | | | ||||||
|  |  *                            | (__| |_| |  _ <| |___ | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  |  * This software is licensed as described in the file COPYING, which | ||||||
|  |  * you should have received as part of this distribution. The terms | ||||||
|  |  * are also available at http://curl.haxx.se/docs/copyright.html. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the COPYING file. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | /* Note that this example currently requires cURL to be linked against | ||||||
|  |    GnuTLS (and this program must also be linked against -lgnutls). */ | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #include <curl/curl.h> | ||||||
|  | #include <gnutls/gnutls.h> | ||||||
|  |  | ||||||
|  | static CURL *curl; | ||||||
|  |  | ||||||
|  | static size_t wrfu(void *ptr, size_t size, size_t nmemb, void *stream) | ||||||
|  | { | ||||||
|  |   const struct curl_tlssessioninfo *info; | ||||||
|  |   unsigned int cert_list_size; | ||||||
|  |   const gnutls_datum_t *chainp; | ||||||
|  |   CURLcode res; | ||||||
|  |  | ||||||
|  |   (void)stream; | ||||||
|  |   (void)ptr; | ||||||
|  |  | ||||||
|  |   res = curl_easy_getinfo(curl, CURLINFO_TLS_SESSION, &info); | ||||||
|  |  | ||||||
|  |   if(!res) { | ||||||
|  |     switch(info->backend) { | ||||||
|  |     case CURLSSLBACKEND_GNUTLS: | ||||||
|  |       /* info->internals is now the gnutls_session_t */ | ||||||
|  |       chainp = gnutls_certificate_get_peers(info->internals, &cert_list_size); | ||||||
|  |       if((chainp) && (cert_list_size)) { | ||||||
|  |         unsigned int i; | ||||||
|  |  | ||||||
|  |         for(i = 0; i < cert_list_size; i++) { | ||||||
|  |           gnutls_x509_crt_t cert; | ||||||
|  |           gnutls_datum_t dn; | ||||||
|  |  | ||||||
|  |           if(GNUTLS_E_SUCCESS == gnutls_x509_crt_init(&cert)) { | ||||||
|  |             if(GNUTLS_E_SUCCESS == | ||||||
|  |                gnutls_x509_crt_import(cert, &chainp[i], GNUTLS_X509_FMT_DER)) { | ||||||
|  |               if(GNUTLS_E_SUCCESS == | ||||||
|  |                  gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &dn)) { | ||||||
|  |                 fprintf(stderr, "Certificate #%d: %.*s", i, dn.size, dn.data); | ||||||
|  |  | ||||||
|  |                 gnutls_free(dn.data); | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             gnutls_x509_crt_deinit(cert); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case CURLSSLBACKEND_NONE: | ||||||
|  |     default: | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return size * nmemb; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(void) | ||||||
|  | { | ||||||
|  |   curl_global_init(CURL_GLOBAL_DEFAULT); | ||||||
|  |  | ||||||
|  |   curl = curl_easy_init(); | ||||||
|  |   if(curl) { | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, wrfu); | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); | ||||||
|  |  | ||||||
|  |     (void) curl_easy_perform(curl); | ||||||
|  |  | ||||||
|  |     curl_easy_cleanup(curl); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   curl_global_cleanup(); | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
| @@ -22,8 +22,9 @@ | |||||||
| /* Example using an in memory PEM user certificate and RSA key to retrieve an | /* Example using an in memory PEM user certificate and RSA key to retrieve an | ||||||
|  * https page. |  * https page. | ||||||
|  * Written by Ishan SinghLevett, based on Theo Borm's cacertinmem.c. |  * Written by Ishan SinghLevett, based on Theo Borm's cacertinmem.c. | ||||||
|  * Note this example does not use a CA certificate, however one should be used |  * Note that to maintain simplicity this example does not use a CA certificate  | ||||||
|  * if you want a properly secure connection |  * for peer verification.  However, some form of peer verification | ||||||
|  |  * must be used in real circumstances when a secure connection is required. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <openssl/ssl.h> | #include <openssl/ssl.h> | ||||||
| @@ -152,6 +153,18 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm) | |||||||
|     printf("Use Key failed\n"); |     printf("Use Key failed\n"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /* free resources that have been allocated by openssl functions */ | ||||||
|  |   if (bio) | ||||||
|  |     BIO_free(bio); | ||||||
|  |  | ||||||
|  |   if (kbio) | ||||||
|  |     BIO_free(kbio); | ||||||
|  |  | ||||||
|  |   if (rsa) | ||||||
|  |     RSA_free(rsa); | ||||||
|  |  | ||||||
|  |   if (cert) | ||||||
|  |     X509_free(cert); | ||||||
|  |  | ||||||
|   /* all set to go */ |   /* all set to go */ | ||||||
|   return CURLE_OK ; |   return CURLE_OK ; | ||||||
|   | |||||||
| @@ -79,9 +79,12 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf			 \ | |||||||
|  curl_multi_assign.pdf curl_easy_pause.pdf curl_easy_recv.pdf		 \ |  curl_multi_assign.pdf curl_easy_pause.pdf curl_easy_recv.pdf		 \ | ||||||
|  curl_easy_send.pdf curl_multi_socket_action.pdf curl_multi_wait.pdf |  curl_easy_send.pdf curl_multi_socket_action.pdf curl_multi_wait.pdf | ||||||
|  |  | ||||||
|  | m4macrodir = $(datadir)/aclocal | ||||||
|  | dist_m4macro_DATA = libcurl.m4 | ||||||
|  |  | ||||||
| CLEANFILES = $(HTMLPAGES) $(PDFPAGES) | CLEANFILES = $(HTMLPAGES) $(PDFPAGES) | ||||||
|  |  | ||||||
| EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) libcurl.m4 ABI \ | EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) ABI \ | ||||||
|   symbols-in-versions symbols.pl |   symbols-in-versions symbols.pl | ||||||
| MAN2HTML= roffit --mandir=. < $< >$@ | MAN2HTML= roffit --mandir=. < $< >$@ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| .\" *                            | (__| |_| |  _ <| |___ | .\" *                            | (__| |_| |  _ <| |___ | ||||||
| .\" *                             \___|\___/|_| \_\_____| | .\" *                             \___|\___/|_| \_\_____| | ||||||
| .\" * | .\" * | ||||||
| .\" * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. | .\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
| .\" * | .\" * | ||||||
| .\" * This software is licensed as described in the file COPYING, which | .\" * This software is licensed as described in the file COPYING, which | ||||||
| .\" * you should have received as part of this distribution. The terms | .\" * you should have received as part of this distribution. The terms | ||||||
| @@ -219,8 +219,20 @@ done. The struct reports how many certs it found and then you can extract info | |||||||
| for each of those certs by following the linked lists. The info chain is | for each of those certs by following the linked lists. The info chain is | ||||||
| provided in a series of data in the format "name:content" where the content is | provided in a series of data in the format "name:content" where the content is | ||||||
| for the specific named data. See also the certinfo.c example. NOTE: this | for the specific named data. See also the certinfo.c example. NOTE: this | ||||||
| option is only available in libcurl built with OpenSSL support. (Added in | option is only available in libcurl built with OpenSSL, NSS, GSKit or QsoSSL | ||||||
| 7.19.1) | support. (Added in 7.19.1) | ||||||
|  | .IP CURLINFO_TLS_SESSION | ||||||
|  | Pass a pointer to a 'struct curl_tlsinfo *'.  The pointer will be initialized | ||||||
|  | to refer to a 'struct curl_tlsinfo *' that will contain an enum indicating the | ||||||
|  | SSL library used for the handshake and the respective internal TLS session | ||||||
|  | structure of this underlying SSL library. | ||||||
|  |  | ||||||
|  | This may then be used to extract certificate information in a format | ||||||
|  | convenient for further processing, such as manual validation. NOTE: this | ||||||
|  | option may not be available for all SSL backends; unsupported SSL backends | ||||||
|  | will return 'CURLSSLBACKEND_NONE' to indicate that they are not supported; | ||||||
|  | this does not mean that no SSL backend was used. (Added in 7.34.0) | ||||||
|  |  | ||||||
| .IP CURLINFO_CONDITION_UNMET | .IP CURLINFO_CONDITION_UNMET | ||||||
| Pass a pointer to a long to receive the number 1 if the condition provided in | Pass a pointer to a long to receive the number 1 if the condition provided in | ||||||
| the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if | the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if | ||||||
| @@ -232,7 +244,7 @@ Pass a pointer to a char pointer to receive a pointer to a string holding the | |||||||
| most recent RTSP Session ID. | most recent RTSP Session ID. | ||||||
|  |  | ||||||
| Applications wishing to resume an RTSP session on another connection should | Applications wishing to resume an RTSP session on another connection should | ||||||
| retreive this info before closing the active connection. | retrieve this info before closing the active connection. | ||||||
| .IP CURLINFO_RTSP_CLIENT_CSEQ | .IP CURLINFO_RTSP_CLIENT_CSEQ | ||||||
| Pass a pointer to a long to receive the next CSeq that will be used by the | Pass a pointer to a long to receive the next CSeq that will be used by the | ||||||
| application. | application. | ||||||
| @@ -244,7 +256,7 @@ by the application. | |||||||
| unimplemented).\fP | unimplemented).\fP | ||||||
|  |  | ||||||
| Applications wishing to resume an RTSP session on another connection should | Applications wishing to resume an RTSP session on another connection should | ||||||
| retreive this info before closing the active connection. | retrieve this info before closing the active connection. | ||||||
| .IP CURLINFO_RTSP_CSEQ_RECV | .IP CURLINFO_RTSP_CSEQ_RECV | ||||||
| Pass a pointer to a long to receive the most recently received CSeq from the | Pass a pointer to a long to receive the most recently received CSeq from the | ||||||
| server. If your application encounters a \fICURLE_RTSP_CSEQ_ERROR\fP then you | server. If your application encounters a \fICURLE_RTSP_CSEQ_ERROR\fP then you | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| .\" *                            | (__| |_| |  _ <| |___ | .\" *                            | (__| |_| |  _ <| |___ | ||||||
| .\" *                             \___|\___/|_| \_\_____| | .\" *                             \___|\___/|_| \_\_____| | ||||||
| .\" * | .\" * | ||||||
| .\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. | .\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
| .\" * | .\" * | ||||||
| .\" * This software is licensed as described in the file COPYING, which | .\" * This software is licensed as described in the file COPYING, which | ||||||
| .\" * you should have received as part of this distribution. The terms | .\" * you should have received as part of this distribution. The terms | ||||||
| @@ -38,8 +38,11 @@ that returns pause signals to the library that it couldn't take care of any | |||||||
| data at all, and that data will then be delivered again to the callback when | data at all, and that data will then be delivered again to the callback when | ||||||
| the writing is later unpaused. | the writing is later unpaused. | ||||||
|  |  | ||||||
| NOTE: while it may feel tempting, take care and notice that you cannot call | While it may feel tempting, take care and notice that you cannot call this | ||||||
| this function from another thread. | function from another thread. To unpause, you may for example call it from the | ||||||
|  | progress callback (see \fIcurl_easy_setopt(3)\fP's | ||||||
|  | \fICURLOPT_PROGRESSFUNCTION\fP), which gets called at least once per second, | ||||||
|  | even if the connection is paused. | ||||||
|  |  | ||||||
| When this function is called to unpause reading, the chance is high that you | When this function is called to unpause reading, the chance is high that you | ||||||
| will get your write callback called before this function returns. | will get your write callback called before this function returns. | ||||||
| @@ -68,6 +71,18 @@ code means something wrong occurred after the new state was set.  See the | |||||||
| .SH AVAILABILITY | .SH AVAILABILITY | ||||||
| This function was added in libcurl 7.18.0. Before this version, there was no | This function was added in libcurl 7.18.0. Before this version, there was no | ||||||
| explicit support for pausing transfers. | explicit support for pausing transfers. | ||||||
|  | .SH "USAGE WITH THE MULTI-SOCKET INTERFACE" | ||||||
|  | Before libcurl 7.32.0, when a specific handle was unpaused with this function, | ||||||
|  | there was no particular forced rechecking or similar of the socket's state, | ||||||
|  | which made the continuation of the transfer get delayed until next | ||||||
|  | multi-socket call invoke or even longer. Alternatively, the user could | ||||||
|  | forcibly call for example curl_multi_socket_all(3) - with a rather hefty | ||||||
|  | performance penalty. | ||||||
|  |  | ||||||
|  | Starting in libcurl 7.32.0, unpausing a transfer will schedule a timeout | ||||||
|  | trigger for that handle 1 millisecond into the future, so that a | ||||||
|  | curl_multi_socket_action( ... CURL_SOCKET_TIMEOUT) can be used immediately | ||||||
|  | afterwards to get the transfer going again as desired. | ||||||
| .SH "MEMORY USE" | .SH "MEMORY USE" | ||||||
| When pausing a read by returning the magic return code from a write callback, | When pausing a read by returning the magic return code from a write callback, | ||||||
| the read data is already in libcurl's internal buffers so it'll have to keep | the read data is already in libcurl's internal buffers so it'll have to keep | ||||||
|   | |||||||
| @@ -260,9 +260,9 @@ used to fast forward a file in a resumed upload (instead of reading all | |||||||
| uploaded bytes with the normal read function/callback). It is also called to | uploaded bytes with the normal read function/callback). It is also called to | ||||||
| rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication | rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication | ||||||
| method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET, | method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET, | ||||||
| SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl | SEEK_CUR and SEEK_END as argument for origin, although libcurl currently only | ||||||
| only passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on | passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on success, 1 | ||||||
| success, 1 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2 | (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2 | ||||||
| (CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is | (CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is | ||||||
| free to work around the problem if possible. The latter can sometimes be done | free to work around the problem if possible. The latter can sometimes be done | ||||||
| by instead reading from the input or similar. | by instead reading from the input or similar. | ||||||
| @@ -377,10 +377,54 @@ function that performs transfers. | |||||||
|  |  | ||||||
| \fICURLOPT_NOPROGRESS\fP must be set to 0 to make this function actually | \fICURLOPT_NOPROGRESS\fP must be set to 0 to make this function actually | ||||||
| get called. | get called. | ||||||
|  | .IP CURLOPT_XFERINFOFUNCTION | ||||||
|  | Pass a pointer to a function that matches the following prototype: | ||||||
|  |  | ||||||
|  | .nf | ||||||
|  | \fBint function(void *clientp, curl_off_t dltotal, curl_off_t dlnow, | ||||||
|  |                 curl_off_t ultotal, curl_off_t ulnow);\fP | ||||||
|  | .fi | ||||||
|  |  | ||||||
|  | This function gets called by libcurl instead of its internal equivalent with a | ||||||
|  | frequent interval. While data is being transferred it will be called very | ||||||
|  | frequently, and during slow periods like when nothing is being transferred it | ||||||
|  | can slow down to about one call per second. | ||||||
|  |  | ||||||
|  | \fIclientp\fP is the pointer set with \fICURLOPT_XFERINFODATA\fP, it is only | ||||||
|  | passed along from the application to the callback. | ||||||
|  |  | ||||||
|  | The callback gets told how much data libcurl will transfer and has | ||||||
|  | transferred, in number of bytes. \fIdltotal\fP is the total number of bytes | ||||||
|  | libcurl expects to download in this transfer. \fIdlnow\fP is the number of | ||||||
|  | bytes downloaded so far. \fIultotal\fP is the total number of bytes libcurl | ||||||
|  | expects to upload in this transfer. \fIulnow\fP is the number of bytes | ||||||
|  | uploaded so far. | ||||||
|  |  | ||||||
|  | Unknown/unused argument values passed to the callback will be set to zero | ||||||
|  | (like if you only download data, the upload size will remain 0). Many times | ||||||
|  | the callback will be called one or more times first, before it knows the data | ||||||
|  | sizes so a program must be made to handle that. | ||||||
|  |  | ||||||
|  | Returning a non-zero value from this callback will cause libcurl to abort the | ||||||
|  | transfer and return \fICURLE_ABORTED_BY_CALLBACK\fP. | ||||||
|  |  | ||||||
|  | If you transfer data with the multi interface, this function will not be | ||||||
|  | called during periods of idleness unless you call the appropriate libcurl | ||||||
|  | function that performs transfers. | ||||||
|  |  | ||||||
|  | \fICURLOPT_NOPROGRESS\fP must be set to 0 to make this function actually | ||||||
|  | get called. | ||||||
|  |  | ||||||
|  | (Added in 7.32.0) | ||||||
| .IP CURLOPT_PROGRESSDATA | .IP CURLOPT_PROGRESSDATA | ||||||
| Pass a pointer that will be untouched by libcurl and passed as the first | Pass a pointer that will be untouched by libcurl and passed as the first | ||||||
| argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP. | argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP. | ||||||
| The default value of this parameter is unspecified. | The default value of this parameter is unspecified. | ||||||
|  | .IP CURLOPT_XFERINFODATA | ||||||
|  | Pass a pointer that will be untouched by libcurl and passed as the first | ||||||
|  | argument in the progress callback set with \fICURLOPT_XFERINFOFUNCTION\fP. | ||||||
|  | The default value of this parameter is unspecified. This option is an alias | ||||||
|  | for CURLOPT_PROGRESSDATA. (Added in 7.32.0) | ||||||
| .IP CURLOPT_HEADERFUNCTION | .IP CURLOPT_HEADERFUNCTION | ||||||
| Pass a pointer to a function that matches the following prototype: | Pass a pointer to a function that matches the following prototype: | ||||||
| \fBsize_t function( void *ptr, size_t size, size_t nmemb, void | \fBsize_t function( void *ptr, size_t size, size_t nmemb, void | ||||||
| @@ -847,6 +891,19 @@ Active Directory server. | |||||||
| For more information about the individual components of a LDAP URL please | For more information about the individual components of a LDAP URL please | ||||||
| see RFC4516. | see RFC4516. | ||||||
|  |  | ||||||
|  | .B RTMP | ||||||
|  |  | ||||||
|  | There's no official URL spec for RTMP so libcurl uses the URL syntax supported | ||||||
|  | by the underlying librtmp library. It has a syntax where it wants a | ||||||
|  | traditional URL, followed by a space and a series of space-separated | ||||||
|  | name=value pairs. | ||||||
|  |  | ||||||
|  | While space is not typically a "legal" letter, libcurl accepts them. When a | ||||||
|  | user wants to pass in a '#' (hash) character it will be treated as a fragment | ||||||
|  | and get cut off by libcurl if provided literally. You will instead have to | ||||||
|  | escape it by providing it as backslash and its ASCII value in hexadecimal: | ||||||
|  | "\\23". | ||||||
|  |  | ||||||
| .B NOTES | .B NOTES | ||||||
|  |  | ||||||
| Starting with version 7.20.0, the fragment part of the URI will not be sent as | Starting with version 7.20.0, the fragment part of the URI will not be sent as | ||||||
| @@ -1074,7 +1131,7 @@ option is omitted, and \fICURLOPT_NETRC\fP is set, libcurl will attempt to | |||||||
| find a .netrc file in the current user's home directory. (Added in 7.10.9) | find a .netrc file in the current user's home directory. (Added in 7.10.9) | ||||||
| .IP CURLOPT_USERPWD | .IP CURLOPT_USERPWD | ||||||
| Pass a char * as parameter, pointing to a zero terminated login details string | Pass a char * as parameter, pointing to a zero terminated login details string | ||||||
| for the connection. The format of which is: [user name]:[password];[options]. | for the connection. The format of which is: [user name]:[password]. | ||||||
|  |  | ||||||
| When using NTLM, you can set the domain by prepending it to the user name and | When using NTLM, you can set the domain by prepending it to the user name and | ||||||
| separating the domain and name with a forward (/) or backward slash (\\). Like | separating the domain and name with a forward (/) or backward slash (\\). Like | ||||||
| @@ -1088,15 +1145,18 @@ and password information to hosts using the initial host name (unless | |||||||
| other hosts it will not send the user and password to those. This is enforced | other hosts it will not send the user and password to those. This is enforced | ||||||
| to prevent accidental information leakage. | to prevent accidental information leakage. | ||||||
|  |  | ||||||
| At present only IMAP, POP3 and SMTP support login options as part of the |  | ||||||
| details string. For more information about the login options please see |  | ||||||
| RFC2384, RFC5092 and IETF draft draft-earhart-url-smtp-00.txt (Added in 7.31.0). |  | ||||||
|  |  | ||||||
| Use \fICURLOPT_HTTPAUTH\fP to specify the authentication method for HTTP based | Use \fICURLOPT_HTTPAUTH\fP to specify the authentication method for HTTP based | ||||||
| connections. | connections or \fICURLOPT_LOGIN_OPTIONS\fP to control IMAP, POP3 and SMTP | ||||||
|  | options. | ||||||
|  |  | ||||||
|  | The user and password strings are not URL decoded, so there's no way to send | ||||||
|  | in a user name containing a colon using this option. Use \fCURLOPT_USERNAME\fP | ||||||
|  | for that, or include it in the URL. | ||||||
| .IP CURLOPT_PROXYUSERPWD | .IP CURLOPT_PROXYUSERPWD | ||||||
| Pass a char * as parameter, which should be [user name]:[password] to use for | Pass a char * as parameter, which should be [user name]:[password] to use for | ||||||
| the connection to the HTTP proxy. | the connection to the HTTP proxy. Both the name and the password will be URL | ||||||
|  | decoded before use, so to include for example a colon in the user name you | ||||||
|  | should encode it as %3A. | ||||||
|  |  | ||||||
| Use \fICURLOPT_PROXYAUTH\fP to specify the authentication method. | Use \fICURLOPT_PROXYAUTH\fP to specify the authentication method. | ||||||
| .IP CURLOPT_USERNAME | .IP CURLOPT_USERNAME | ||||||
| @@ -1107,14 +1167,26 @@ user name to use for the transfer. | |||||||
| authentication. You should not use this option together with the (older) | authentication. You should not use this option together with the (older) | ||||||
| CURLOPT_USERPWD option. | CURLOPT_USERPWD option. | ||||||
|  |  | ||||||
| In order to specify the password to be used in conjunction with the user name | To specify the password and login options, along with the user name, use the | ||||||
| use the \fICURLOPT_PASSWORD\fP option.  (Added in 7.19.1) | \fICURLOPT_PASSWORD\fP and \fICURLOPT_LOGIN_OPTIONS\fP options. (Added in | ||||||
|  | 7.19.1) | ||||||
| .IP CURLOPT_PASSWORD | .IP CURLOPT_PASSWORD | ||||||
| Pass a char * as parameter, which should be pointing to the zero terminated | Pass a char * as parameter, which should be pointing to the zero terminated | ||||||
| password to use for the transfer. | password to use for the transfer. | ||||||
|  |  | ||||||
| The CURLOPT_PASSWORD option should be used in conjunction with | The CURLOPT_PASSWORD option should be used in conjunction with the | ||||||
| the \fICURLOPT_USERNAME\fP option. (Added in 7.19.1) | \fICURLOPT_USERNAME\fP option. (Added in 7.19.1) | ||||||
|  | .IP CURLOPT_LOGIN_OPTIONS | ||||||
|  | (Added in 7.34.0) Pass a char * as parameter, which should be pointing to the | ||||||
|  | zero terminated options string to use for the transfer. | ||||||
|  |  | ||||||
|  | At present only IMAP, POP3 and SMTP support login options. For more | ||||||
|  | information about the login options please see RFC2384, RFC5092 and IETF draft | ||||||
|  | draft-earhart-url-smtp-00.txt | ||||||
|  |  | ||||||
|  | \CURLOPT_LOGIN_OPTIONS\fP can be used to set protocol specific login options, | ||||||
|  | such as the preferred authentication mechanism via "AUTH=NTLM" or "AUTH=*", | ||||||
|  | and should be used in conjunction with the \fICURLOPT_USERNAME\fP option. | ||||||
| .IP CURLOPT_PROXYUSERNAME | .IP CURLOPT_PROXYUSERNAME | ||||||
| Pass a char * as parameter, which should be pointing to the zero terminated | Pass a char * as parameter, which should be pointing to the zero terminated | ||||||
| user name to use for the transfer while connecting to Proxy. | user name to use for the transfer while connecting to Proxy. | ||||||
| @@ -1245,6 +1317,13 @@ mechanisms and to the IMAP, POP3 and SMTP protocols. (Added in 7.31.0) | |||||||
| Note: Whilst IMAP supports this option there is no need to explicitly set it, | Note: Whilst IMAP supports this option there is no need to explicitly set it, | ||||||
| as libcurl can determine the feature itself when the server supports the | as libcurl can determine the feature itself when the server supports the | ||||||
| SASL-IR CAPABILITY. | SASL-IR CAPABILITY. | ||||||
|  | .IP CURLOPT_BEARER | ||||||
|  | Pass a char * as parameter, which should point to the zero terminated OAUTH | ||||||
|  | 2.0 Bearer Access Token for use with IMAP. POP3 and SMTP servers that support | ||||||
|  | the OAUTH 2.0 Authorization Framework. (Added in 7.33.0) | ||||||
|  |  | ||||||
|  | Note: The user name used to generate the Bearer Token should be supplied via | ||||||
|  | the \fICURLOPT_USERNAME\fP option. | ||||||
| .SH HTTP OPTIONS | .SH HTTP OPTIONS | ||||||
| .IP CURLOPT_AUTOREFERER | .IP CURLOPT_AUTOREFERER | ||||||
| Pass a parameter set to 1 to enable this. When enabled, libcurl will | Pass a parameter set to 1 to enable this. When enabled, libcurl will | ||||||
| @@ -1587,12 +1666,18 @@ SMTP mail request. The linked list should be a fully valid list of \fBstruct | |||||||
| curl_slist\fP structs properly filled in. Use \fIcurl_slist_append(3)\fP to | curl_slist\fP structs properly filled in. Use \fIcurl_slist_append(3)\fP to | ||||||
| create the list and \fIcurl_slist_free_all(3)\fP to clean up an entire list. | create the list and \fIcurl_slist_free_all(3)\fP to clean up an entire list. | ||||||
|  |  | ||||||
| Each recipient should be specified within a pair of angled brackets (<>), | When performing a mail transfer, each recipient should be specified within a | ||||||
| however, should you not use an angled bracket as the first character libcurl | pair of angled brackets (<>), however, should you not use an angled bracket as | ||||||
| will assume you provided a single email address and enclose that address | the first character libcurl will assume you provided a single email address and | ||||||
| within brackets for you. | enclose that address within brackets for you. (Added in 7.20.0) | ||||||
|  |  | ||||||
| (Added in 7.20.0) | When performing an address verification (VRFY command), each recipient should | ||||||
|  | be specified as the user name or user name and domain (as per Section 3.5 of | ||||||
|  | RFC5321). (Added in 7.34.0) | ||||||
|  |  | ||||||
|  | When performing a mailing list expand (EXPN command), each recipient should be | ||||||
|  | specified using the mailing list name, such as "Friends" or "London-Office". | ||||||
|  | (Added in 7.34.0) | ||||||
| .IP CURLOPT_MAIL_AUTH | .IP CURLOPT_MAIL_AUTH | ||||||
| Pass a pointer to a zero terminated string as parameter. This will be used | Pass a pointer to a zero terminated string as parameter. This will be used | ||||||
| to specify the authentication address (identity) of a submitted message that | to specify the authentication address (identity) of a submitted message that | ||||||
| @@ -1964,35 +2049,32 @@ source file to the remote target file. | |||||||
| Pass a curl_off_t as parameter. It contains the offset in number of bytes that | Pass a curl_off_t as parameter. It contains the offset in number of bytes that | ||||||
| you want the transfer to start from. (Added in 7.11.0) | you want the transfer to start from. (Added in 7.11.0) | ||||||
| .IP CURLOPT_CUSTOMREQUEST | .IP CURLOPT_CUSTOMREQUEST | ||||||
| Pass a pointer to a zero terminated string as parameter. It can be used to | Pass a pointer to a zero terminated string as parameter. | ||||||
| specify the request instead of GET or HEAD when performing HTTP based |  | ||||||
| requests, instead of LIST and NLST when performing FTP directory listings and |  | ||||||
| instead of LIST and RETR when issuing POP3 based commands. This is |  | ||||||
| particularly useful, for example, for performing a HTTP DELETE request or a |  | ||||||
| POP3 DELE command. |  | ||||||
|  |  | ||||||
| Please don't perform this at will, on HTTP based requests, by making sure |  | ||||||
| your server supports the command you are sending first. |  | ||||||
|  |  | ||||||
| When you change the request method by setting \fBCURLOPT_CUSTOMREQUEST\fP to | When you change the request method by setting \fBCURLOPT_CUSTOMREQUEST\fP to | ||||||
| something, you don't actually change how libcurl behaves or acts in regards | something, you don't actually change how libcurl behaves or acts in regards | ||||||
| to the particular request method, it will only change the actual string sent | to the particular request method, it will only change the actual string sent | ||||||
| in the request. | in the request. | ||||||
|  |  | ||||||
|  | Restore to the internal default by setting this to NULL. | ||||||
|  |  | ||||||
|  | This option can be used to specify the request: | ||||||
|  |  | ||||||
|  | .B HTTP | ||||||
|  |  | ||||||
|  | Instead of GET or HEAD when performing HTTP based requests. This is | ||||||
|  | particularly useful, for example, for performing a HTTP DELETE request. | ||||||
|  |  | ||||||
| For example: | For example: | ||||||
|  |  | ||||||
| With the HTTP protocol when you tell libcurl to do a HEAD request, but then | When you tell libcurl to do a HEAD request, but then specify a GET though a | ||||||
| specify a GET though a custom request libcurl will still act as if it sent a | custom request libcurl will still act as if it sent a HEAD. To switch to a | ||||||
| HEAD. To switch to a proper HEAD use \fICURLOPT_NOBODY\fP, to switch to a | proper HEAD use \fICURLOPT_NOBODY\fP, to switch to a proper POST use | ||||||
| proper POST use \fICURLOPT_POST\fP or \fICURLOPT_POSTFIELDS\fP and to switch | \fICURLOPT_POST\fP or \fICURLOPT_POSTFIELDS\fP and to switch to a proper GET | ||||||
| to a proper GET use CURLOPT_HTTPGET. | use CURLOPT_HTTPGET. | ||||||
|  |  | ||||||
| With the POP3 protocol when you tell libcurl to use a custom request it will | Please don't perform this at will, on HTTP based requests, by making sure | ||||||
| behave like a LIST or RETR command was sent where it expects data to be | your server supports the command you are sending first. | ||||||
| returned by the server. As such \fICURLOPT_NOBODY\fP should be used when |  | ||||||
| specifying commands such as DELE and NOOP for example. |  | ||||||
|  |  | ||||||
| Restore to the internal default by setting this to NULL. |  | ||||||
|  |  | ||||||
| Many people have wrongly used this option to replace the entire request with | Many people have wrongly used this option to replace the entire request with | ||||||
| their own, including multiple headers and POST contents. While that might | their own, including multiple headers and POST contents. While that might | ||||||
| @@ -2002,7 +2084,35 @@ could possibly confuse the remote server badly. Use \fICURLOPT_POST\fP and | |||||||
| replace or extend the set of headers sent by libcurl. Use | replace or extend the set of headers sent by libcurl. Use | ||||||
| \fICURLOPT_HTTP_VERSION\fP to change HTTP version. | \fICURLOPT_HTTP_VERSION\fP to change HTTP version. | ||||||
|  |  | ||||||
| (Support for POP3 added in 7.26.0) | .B FTP | ||||||
|  |  | ||||||
|  | Instead of LIST and NLST when performing FTP directory listings. | ||||||
|  |  | ||||||
|  | .B IMAP | ||||||
|  |  | ||||||
|  | Instead of LIST when issuing IMAP based requests. (Added in 7.30.0) | ||||||
|  |  | ||||||
|  | .B POP3 | ||||||
|  |  | ||||||
|  | Instead of LIST and RETR when issuing POP3 based requests. (Added in 7.26.0) | ||||||
|  |  | ||||||
|  | For example: | ||||||
|  |  | ||||||
|  | When you tell libcurl to use a custom request it will behave like a LIST or | ||||||
|  | RETR command was sent where it expects data to be returned by the server. As | ||||||
|  | such \fICURLOPT_NOBODY\fP should be used when specifying commands such as | ||||||
|  | DELE and NOOP for example. | ||||||
|  |  | ||||||
|  | .B SMTP | ||||||
|  |  | ||||||
|  | Instead of a HELP or VRFY when issuing SMTP based requests. (Added in 7.34.0) | ||||||
|  |  | ||||||
|  | For example: | ||||||
|  |  | ||||||
|  | Normally a multiline response is returned which can be used, in conjuection with | ||||||
|  | \fICURLOPT_MAIL_RCPT\fP, to specify an EXPN request. If the \fICURLOPT_NOBODY\fP | ||||||
|  | option is specified then the request can be used to issue NOOP and RSET | ||||||
|  | commands. | ||||||
| .IP CURLOPT_FILETIME | .IP CURLOPT_FILETIME | ||||||
| Pass a long. If it is 1, libcurl will attempt to get the modification date of | Pass a long. If it is 1, libcurl will attempt to get the modification date of | ||||||
| the remote document in this operation. This requires that the remote server | the remote document in this operation. This requires that the remote server | ||||||
| @@ -2098,10 +2208,14 @@ In unix-like systems, this might cause signals to be used unless | |||||||
|  |  | ||||||
| Default timeout is 0 (zero) which means it never times out. | Default timeout is 0 (zero) which means it never times out. | ||||||
| .IP CURLOPT_TIMEOUT_MS | .IP CURLOPT_TIMEOUT_MS | ||||||
| Like \fICURLOPT_TIMEOUT\fP but takes number of milliseconds instead. If | An alternative to \fICURLOPT_TIMEOUT\fP but takes number of milliseconds | ||||||
| libcurl is built to use the standard system name resolver, that portion | instead. If libcurl is built to use the standard system name resolver, that | ||||||
| of the transfer will still use full-second resolution for timeouts with | portion of the transfer will still use full-second resolution for timeouts | ||||||
| a minimum timeout allowed of one second. | with a minimum timeout allowed of one second. | ||||||
|  |  | ||||||
|  | If both \fICURLOPT_TIMEOUT\fP and \fICURLOPT_TIMEOUT_MS\fP are set, the value | ||||||
|  | set last will be used. | ||||||
|  |  | ||||||
| (Added in 7.16.2) | (Added in 7.16.2) | ||||||
| .IP CURLOPT_LOW_SPEED_LIMIT | .IP CURLOPT_LOW_SPEED_LIMIT | ||||||
| Pass a long as parameter. It contains the transfer speed in bytes per second | Pass a long as parameter. It contains the transfer speed in bytes per second | ||||||
| @@ -2225,7 +2339,9 @@ ADDRESS can of course be either IPv4 or IPv6 style addressing. | |||||||
|  |  | ||||||
| This option effectively pre-populates the DNS cache with entries for the | This option effectively pre-populates the DNS cache with entries for the | ||||||
| host+port pair so redirects and everything that operations against the | host+port pair so redirects and everything that operations against the | ||||||
| HOST+PORT will instead use your provided ADDRESS. | HOST+PORT will instead use your provided ADDRESS. Addresses to set with | ||||||
|  | \fICURL_RESOLVE\fP will not time-out from the DNS cache like ordindary | ||||||
|  | entries. | ||||||
|  |  | ||||||
| You can remove names from the DNS cache again, to stop providing these fake | You can remove names from the DNS cache again, to stop providing these fake | ||||||
| resolves, by including a string in the linked list that uses the format | resolves, by including a string in the linked list that uses the format | ||||||
| @@ -2247,6 +2363,36 @@ This option requires that libcurl was built with a resolver backend that | |||||||
| supports this operation. The c-ares backend is the only such one. | supports this operation. The c-ares backend is the only such one. | ||||||
|  |  | ||||||
| (Added in 7.24.0) | (Added in 7.24.0) | ||||||
|  | .IP CURLOPT_DNS_INTERFACE | ||||||
|  | Pass a char * as parameter. Set the name of the network interface that | ||||||
|  | the DNS resolver should bind to. This must be an interface name (not an | ||||||
|  | address). Set this option to NULL to use the default setting (don't | ||||||
|  | bind to a specific interface). | ||||||
|  |  | ||||||
|  | This option requires that libcurl was built with a resolver backend that | ||||||
|  | supports this operation. The c-ares backend is the only such one. | ||||||
|  |  | ||||||
|  | (Added in 7.33.0) | ||||||
|  | .IP CURLOPT_DNS_LOCAL_IP4 | ||||||
|  | Set the local IPv4 address that the resolver should bind to. The argument | ||||||
|  | should be of type char * and contain a single IPv4 address as a string. | ||||||
|  | Set this option to NULL to use the default setting (don't | ||||||
|  | bind to a specific IP address). | ||||||
|  |  | ||||||
|  | This option requires that libcurl was built with a resolver backend that | ||||||
|  | supports this operation. The c-ares backend is the only such one. | ||||||
|  |  | ||||||
|  | (Added in 7.33.0) | ||||||
|  | .IP CURLOPT_DNS_LOCAL_IP6 | ||||||
|  | Set the local IPv6 address that the resolver should bind to. The argument | ||||||
|  | should be of type char * and contain a single IPv6 address as a string. | ||||||
|  | Set this option to NULL to use the default setting (don't | ||||||
|  | bind to a specific IP address). | ||||||
|  |  | ||||||
|  | This option requires that libcurl was built with a resolver backend that | ||||||
|  | supports this operation. The c-ares backend is the only such one. | ||||||
|  |  | ||||||
|  | (Added in 7.33.0) | ||||||
| .IP CURLOPT_ACCEPTTIMEOUT_MS | .IP CURLOPT_ACCEPTTIMEOUT_MS | ||||||
| Pass a long telling libcurl the maximum number of milliseconds to wait for a | Pass a long telling libcurl the maximum number of milliseconds to wait for a | ||||||
| server to connect back to libcurl when an active FTP connection is used. If no | server to connect back to libcurl when an active FTP connection is used. If no | ||||||
| @@ -2254,22 +2400,20 @@ timeout is set, the internal default of 60000 will be used. (Added in 7.24.0) | |||||||
| .SH SSL and SECURITY OPTIONS | .SH SSL and SECURITY OPTIONS | ||||||
| .IP CURLOPT_SSLCERT | .IP CURLOPT_SSLCERT | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | Pass a pointer to a zero terminated string as parameter. The string should be | ||||||
| the file name of your certificate. The default format is "PEM" and can be | the file name of your certificate. The default format is "P12" on Secure | ||||||
| changed with \fICURLOPT_SSLCERTTYPE\fP. | Transport and "PEM" on other engines, and can be changed with | ||||||
|  | \fICURLOPT_SSLCERTTYPE\fP. | ||||||
|  |  | ||||||
| With NSS this can also be the nickname of the certificate you wish to | With NSS or Secure Transport, this can also be the nickname of the certificate | ||||||
| authenticate with. If you want to use a file from the current directory, please | you wish to authenticate with as it is named in the security database. If you | ||||||
| precede it with "./" prefix, in order to avoid confusion with a nickname. | want to use a file from the current directory, please precede it with "./" | ||||||
|  | prefix, in order to avoid confusion with a nickname. | ||||||
| (iOS and Mac OS X only) With Secure Transport, this string must match the name |  | ||||||
| of a certificate that's in the system or user keychain. You should encode this |  | ||||||
| string in UTF-8 format in case it contains non-ASCII characters. The private |  | ||||||
| key corresponding to the certificate, and certificate chain (if any),  must |  | ||||||
| also be present in the keychain. (Added in 7.31.0) |  | ||||||
| .IP CURLOPT_SSLCERTTYPE | .IP CURLOPT_SSLCERTTYPE | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | Pass a pointer to a zero terminated string as parameter. The string should be | ||||||
| the format of your certificate. Supported formats are "PEM" and "DER".  (Added | the format of your certificate. Supported formats are "PEM" and "DER", except | ||||||
| in 7.9.3) | with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport | ||||||
|  | (on iOS 5 or later, or OS X 10.7 or later) also support "P12" for | ||||||
|  | PKCS#12-encoded files. (Added in 7.9.3) | ||||||
| .IP CURLOPT_SSLKEY | .IP CURLOPT_SSLKEY | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | Pass a pointer to a zero terminated string as parameter. The string should be | ||||||
| the file name of your private key. The default format is "PEM" and can be | the file name of your private key. The default format is "PEM" and can be | ||||||
| @@ -2277,7 +2421,7 @@ changed with \fICURLOPT_SSLKEYTYPE\fP. | |||||||
|  |  | ||||||
| (iOS and Mac OS X only) This option is ignored if curl was built against Secure | (iOS and Mac OS X only) This option is ignored if curl was built against Secure | ||||||
| Transport. Secure Transport expects the private key to be already present in | Transport. Secure Transport expects the private key to be already present in | ||||||
| the keychain containing the certificate. | the keychain or PKCS#12 file containing the certificate. | ||||||
| .IP CURLOPT_SSLKEYTYPE | .IP CURLOPT_SSLKEYTYPE | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | Pass a pointer to a zero terminated string as parameter. The string should be | ||||||
| the format of your private key. Supported formats are "PEM", "DER" and "ENG". | the format of your private key. Supported formats are "PEM", "DER" and "ENG". | ||||||
| @@ -2314,6 +2458,8 @@ Even though this option doesn't need any parameter, in some configurations | |||||||
| arguments. Therefore, it's recommended to pass 1 as parameter to this option. | arguments. Therefore, it's recommended to pass 1 as parameter to this option. | ||||||
| .IP CURLOPT_SSLVERSION | .IP CURLOPT_SSLVERSION | ||||||
| Pass a long as parameter to control what version of SSL/TLS to attempt to use. | Pass a long as parameter to control what version of SSL/TLS to attempt to use. | ||||||
|  | (Added in 7.9.2) | ||||||
|  |  | ||||||
| The available options are: | The available options are: | ||||||
| .RS | .RS | ||||||
| .IP CURL_SSLVERSION_DEFAULT | .IP CURL_SSLVERSION_DEFAULT | ||||||
| @@ -2321,11 +2467,17 @@ The default action. This will attempt to figure out the remote SSL protocol | |||||||
| version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled | version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled | ||||||
| by default with 7.18.1). | by default with 7.18.1). | ||||||
| .IP CURL_SSLVERSION_TLSv1 | .IP CURL_SSLVERSION_TLSv1 | ||||||
| Force TLSv1 | Force TLSv1.x | ||||||
| .IP CURL_SSLVERSION_SSLv2 | .IP CURL_SSLVERSION_SSLv2 | ||||||
| Force SSLv2 | Force SSLv2 | ||||||
| .IP CURL_SSLVERSION_SSLv3 | .IP CURL_SSLVERSION_SSLv3 | ||||||
| Force SSLv3 | Force SSLv3 | ||||||
|  | .IP CURL_SSLVERSION_TLSv1_0 | ||||||
|  | Force TLSv1.0 (Added in 7.34.0) | ||||||
|  | .IP CURL_SSLVERSION_TLSv1_1 | ||||||
|  | Force TLSv1.1 (Added in 7.34.0) | ||||||
|  | .IP CURL_SSLVERSION_TLSv1_2 | ||||||
|  | Force TLSv1.2 (Added in 7.34.0) | ||||||
| .RE | .RE | ||||||
| .IP CURLOPT_SSL_VERIFYPEER | .IP CURLOPT_SSL_VERIFYPEER | ||||||
| Pass a long as parameter. By default, curl assumes a value of 1. | Pass a long as parameter. By default, curl assumes a value of 1. | ||||||
| @@ -2426,9 +2578,10 @@ Curl considers the server the intended one when the Common Name field or a | |||||||
| Subject Alternate Name field in the certificate matches the host name in the | Subject Alternate Name field in the certificate matches the host name in the | ||||||
| URL to which you told Curl to connect. | URL to which you told Curl to connect. | ||||||
|  |  | ||||||
| When the value is 1, libcurl will return a failure. It was previously (in | When the value is 1, \fIcurl_easy_setopt\fP will return an error and the option | ||||||
| 7.28.0 and earlier) a debug option of some sorts, but it is no longer | value will not be changed.  It was previously (in 7.28.0 and earlier) a debug | ||||||
| supported due to frequently leading to programmer mistakes. | option of some sorts, but it is no longer supported due to frequently leading | ||||||
|  | to programmer mistakes. | ||||||
|  |  | ||||||
| When the value is 0, the connection succeeds regardless of the names in the | When the value is 0, the connection succeeds regardless of the names in the | ||||||
| certificate. | certificate. | ||||||
| @@ -2438,14 +2591,14 @@ The default value for this option is 2. | |||||||
| This option controls checking the server's certificate's claimed identity. | This option controls checking the server's certificate's claimed identity. | ||||||
| The server could be lying.  To control lying, see | The server could be lying.  To control lying, see | ||||||
| \fICURLOPT_SSL_VERIFYPEER\fP.  If libcurl is built against NSS and | \fICURLOPT_SSL_VERIFYPEER\fP.  If libcurl is built against NSS and | ||||||
| \fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_SSL_VERIFYHOST\fP | \fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_SSL_VERIFYHOST\fP is also set | ||||||
| is ignored. | to zero and cannot be overridden. | ||||||
|  |  | ||||||
| .IP CURLOPT_CERTINFO | .IP CURLOPT_CERTINFO | ||||||
| Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With | Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With | ||||||
| this enabled, libcurl (if built with OpenSSL) will extract lots of information | this enabled, libcurl (if built with OpenSSL, NSS, GSKit or QsoSSL) will | ||||||
|  | extract lots of information | ||||||
| and data about the certificates in the certificate chain used in the SSL | and data about the certificates in the certificate chain used in the SSL | ||||||
| connection. This data is then possible to extract after a transfer using | connection. This data may then be retrieved after a transfer using | ||||||
| \fIcurl_easy_getinfo(3)\fP and its option \fICURLINFO_CERTINFO\fP. (Added in | \fIcurl_easy_getinfo(3)\fP and its option \fICURLINFO_CERTINFO\fP. (Added in | ||||||
| 7.19.1) | 7.19.1) | ||||||
| .IP CURLOPT_RANDOM_FILE | .IP CURLOPT_RANDOM_FILE | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| .\" *                            | (__| |_| |  _ <| |___ | .\" *                            | (__| |_| |  _ <| |___ | ||||||
| .\" *                             \___|\___/|_| \_\_____| | .\" *                             \___|\___/|_| \_\_____| | ||||||
| .\" * | .\" * | ||||||
| .\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. | .\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
| .\" * | .\" * | ||||||
| .\" * This software is licensed as described in the file COPYING, which | .\" * This software is licensed as described in the file COPYING, which | ||||||
| .\" * you should have received as part of this distribution. The terms | .\" * you should have received as part of this distribution. The terms | ||||||
| @@ -29,9 +29,9 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle); | |||||||
| .ad | .ad | ||||||
| .SH DESCRIPTION | .SH DESCRIPTION | ||||||
| Adds a standard easy handle to the multi stack. This function call will make | Adds a standard easy handle to the multi stack. This function call will make | ||||||
| this \fImulti_handle\fP control the specified \fIeasy_handle\fP. | this \fImulti_handle\fP control the specified \fIeasy_handle\fP.  Furthermore, | ||||||
| Furthermore, libcurl now initiates the connection associated with the | libcurl now initiates the connection associated with the specified | ||||||
| specified \fIeasy_handle\fP. | \fIeasy_handle\fP. | ||||||
|  |  | ||||||
| When an easy handle has been added to a multi stack, you can not and you must | When an easy handle has been added to a multi stack, you can not and you must | ||||||
| not use \fIcurl_easy_perform(3)\fP on that handle! | not use \fIcurl_easy_perform(3)\fP on that handle! | ||||||
| @@ -41,6 +41,12 @@ cache (CURLOPT_DNS_USE_GLOBAL_CACHE), it will be made to use the DNS cache | |||||||
| that is shared between all easy handles within the multi handle when | that is shared between all easy handles within the multi handle when | ||||||
| \fIcurl_multi_add_handle(3)\fP is called. | \fIcurl_multi_add_handle(3)\fP is called. | ||||||
|  |  | ||||||
|  | If you have CURLMOPT_TIMERFUNCTION set in the multi handle (and you really | ||||||
|  | should if you're working event-based with \fIcurl_multi_socket_action(3)\fP | ||||||
|  | and friends), that callback will be called from within this function to ask | ||||||
|  | for an updated timer so that your main event loop will get the activity on | ||||||
|  | this handle to get started. | ||||||
|  |  | ||||||
| The easy handle will remain added until you remove it again with | The easy handle will remain added until you remove it again with | ||||||
| \fIcurl_multi_remove_handle(3)\fP. You should remove the easy handle from the | \fIcurl_multi_remove_handle(3)\fP. You should remove the easy handle from the | ||||||
| multi stack before you terminate first the easy handle and then the multi | multi stack before you terminate first the easy handle and then the multi | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| .\" *                            | (__| |_| |  _ <| |___ | .\" *                            | (__| |_| |  _ <| |___ | ||||||
| .\" *                             \___|\___/|_| \_\_____| | .\" *                             \___|\___/|_| \_\_____| | ||||||
| .\" * | .\" * | ||||||
| .\" * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. | .\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
| .\" * | .\" * | ||||||
| .\" * This software is licensed as described in the file COPYING, which | .\" * This software is licensed as described in the file COPYING, which | ||||||
| .\" * you should have received as part of this distribution. The terms | .\" * you should have received as part of this distribution. The terms | ||||||
| @@ -273,6 +273,9 @@ The passed-in socket is not a valid one that libcurl already knows about. | |||||||
| .IP "CURLM_UNKNOWN_OPTION (6)" | .IP "CURLM_UNKNOWN_OPTION (6)" | ||||||
| curl_multi_setopt() with unsupported option | curl_multi_setopt() with unsupported option | ||||||
| (Added in 7.15.4) | (Added in 7.15.4) | ||||||
|  | .IP "CURLM_ADDED_ALREADY (7)" | ||||||
|  | An easy handle already added to a multi handle was attempted to get added a | ||||||
|  | second time. (Added in 7.32.1) | ||||||
| .SH "CURLSHcode" | .SH "CURLSHcode" | ||||||
| The "share" interface will return a CURLSHcode to indicate when an error has | The "share" interface will return a CURLSHcode to indicate when an error has | ||||||
| occurred.  Also consider \fIcurl_share_strerror(3)\fP. | occurred.  Also consider \fIcurl_share_strerror(3)\fP. | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| .\" *                            | (__| |_| |  _ <| |___ | .\" *                            | (__| |_| |  _ <| |___ | ||||||
| .\" *                             \___|\___/|_| \_\_____| | .\" *                             \___|\___/|_| \_\_____| | ||||||
| .\" * | .\" * | ||||||
| .\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. | .\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
| .\" * | .\" * | ||||||
| .\" * This software is licensed as described in the file COPYING, which | .\" * This software is licensed as described in the file COPYING, which | ||||||
| .\" * you should have received as part of this distribution. The terms | .\" * you should have received as part of this distribution. The terms | ||||||
| @@ -39,8 +39,15 @@ maintain while using libcurl.  This essentially means you call | |||||||
| for details. | for details. | ||||||
|  |  | ||||||
| To transfer files, you always set up an "easy handle" using | To transfer files, you always set up an "easy handle" using | ||||||
| \fIcurl_easy_init(3)\fP, but when you want the file(s) transferred you have | \fIcurl_easy_init(3)\fP for a single specific transfer (in either | ||||||
| the option of using the "easy" interface, or the "multi" interface. | direction). You then set your desired set of options in that handle with | ||||||
|  | \fIcurk_easy_setopt(3)\fP. Options you set with \fIcurl_easy_setopt(3)\fP will | ||||||
|  | be used on every repeated use of this handle until you either call the | ||||||
|  | function again and change the option, or you reset them all with | ||||||
|  | \fIcurl_easy_reset(3)\fP. | ||||||
|  |  | ||||||
|  | To actually transfer data you have the option of using the "easy" interface, | ||||||
|  | or the "multi" interface. | ||||||
|  |  | ||||||
| The easy interface is a synchronous interface with which you call | The easy interface is a synchronous interface with which you call | ||||||
| \fIcurl_easy_perform(3)\fP and let it perform the transfer. When it is | \fIcurl_easy_perform(3)\fP and let it perform the transfer. When it is | ||||||
| @@ -51,7 +58,8 @@ The multi interface on the other hand is an asynchronous interface, that you | |||||||
| call and that performs only a little piece of the transfer on each invoke. It | call and that performs only a little piece of the transfer on each invoke. It | ||||||
| is perfect if you want to do things while the transfer is in progress, or | is perfect if you want to do things while the transfer is in progress, or | ||||||
| similar. The multi interface allows you to select() on libcurl action, and | similar. The multi interface allows you to select() on libcurl action, and | ||||||
| even to easily download multiple files simultaneously using a single thread. See further details in the \fIlibcurl-multi(3)\fP man page. | even to easily download multiple files simultaneously using a single | ||||||
|  | thread. See further details in the \fIlibcurl-multi(3)\fP man page. | ||||||
|  |  | ||||||
| You can have multiple easy handles share certain data, even if they are used | You can have multiple easy handles share certain data, even if they are used | ||||||
| in different threads. This magic is setup using the share interface, as | in different threads. This magic is setup using the share interface, as | ||||||
| @@ -115,19 +123,21 @@ Persistent connections means that libcurl can re-use the same connection for | |||||||
| several transfers, if the conditions are right. | several transfers, if the conditions are right. | ||||||
|  |  | ||||||
| libcurl will \fBalways\fP attempt to use persistent connections. Whenever you | libcurl will \fBalways\fP attempt to use persistent connections. Whenever you | ||||||
| use \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP, libcurl will | use \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP etc, libcurl | ||||||
| attempt to use an existing connection to do the transfer, and if none exists | will attempt to use an existing connection to do the transfer, and if none | ||||||
| it'll open a new one that will be subject for re-use on a possible following | exists it'll open a new one that will be subject for re-use on a possible | ||||||
| call to \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP. | following call to \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP. | ||||||
|  |  | ||||||
| To allow libcurl to take full advantage of persistent connections, you should | To allow libcurl to take full advantage of persistent connections, you should | ||||||
| do as many of your file transfers as possible using the same curl handle. When | do as many of your file transfers as possible using the same handle. | ||||||
| you call \fIcurl_easy_cleanup(3)\fP, all the possibly open connections held by |  | ||||||
| libcurl will be closed and forgotten. |  | ||||||
|  |  | ||||||
| Note that the options set with \fIcurl_easy_setopt(3)\fP will be used on | If you use the easy interface, and you call \fIcurl_easy_cleanup(3)\fP, all | ||||||
| every repeated \fIcurl_easy_perform(3)\fP call. | the possibly open connections held by libcurl will be closed and forgotten. | ||||||
|  |  | ||||||
|  | When you've created a multi handle and are using the multi interface, the | ||||||
|  | connection pool is instead kept in the multi handle so closing and creating | ||||||
|  | new easy handles to do transfers will not affect them. Instead all added easy | ||||||
|  | handles can take advantage of the single shared pool. | ||||||
| .SH "GLOBAL CONSTANTS" | .SH "GLOBAL CONSTANTS" | ||||||
| There are a variety of constants that libcurl uses, mainly through its | There are a variety of constants that libcurl uses, mainly through its | ||||||
| internal use of other libraries, which are too complicated for the | internal use of other libraries, which are too complicated for the | ||||||
|   | |||||||
| @@ -85,8 +85,8 @@ CURLE_LDAP_SEARCH_FAILED        7.1 | |||||||
| CURLE_LIBRARY_NOT_FOUND         7.1           7.17.0 | CURLE_LIBRARY_NOT_FOUND         7.1           7.17.0 | ||||||
| CURLE_LOGIN_DENIED              7.13.1 | CURLE_LOGIN_DENIED              7.13.1 | ||||||
| CURLE_MALFORMAT_USER            7.1           7.17.0 | CURLE_MALFORMAT_USER            7.1           7.17.0 | ||||||
| CURLE_NO_CONNECTION_AVAILABLE   7.30.0 |  | ||||||
| CURLE_NOT_BUILT_IN              7.21.5 | CURLE_NOT_BUILT_IN              7.21.5 | ||||||
|  | CURLE_NO_CONNECTION_AVAILABLE   7.30.0 | ||||||
| CURLE_OK                        7.1 | CURLE_OK                        7.1 | ||||||
| CURLE_OPERATION_TIMEDOUT        7.10.2 | CURLE_OPERATION_TIMEDOUT        7.10.2 | ||||||
| CURLE_OPERATION_TIMEOUTED       7.1           7.17.0 | CURLE_OPERATION_TIMEOUTED       7.1           7.17.0 | ||||||
| @@ -250,6 +250,7 @@ CURLINFO_SSL_VERIFYRESULT       7.5 | |||||||
| CURLINFO_STARTTRANSFER_TIME     7.9.2 | CURLINFO_STARTTRANSFER_TIME     7.9.2 | ||||||
| CURLINFO_STRING                 7.4.1 | CURLINFO_STRING                 7.4.1 | ||||||
| CURLINFO_TEXT                   7.9.6 | CURLINFO_TEXT                   7.9.6 | ||||||
|  | CURLINFO_TLS_SESSION            7.34.0 | ||||||
| CURLINFO_TOTAL_TIME             7.4.1 | CURLINFO_TOTAL_TIME             7.4.1 | ||||||
| CURLINFO_TYPEMASK               7.4.1 | CURLINFO_TYPEMASK               7.4.1 | ||||||
| CURLIOCMD_NOP                   7.12.3 | CURLIOCMD_NOP                   7.12.3 | ||||||
| @@ -270,10 +271,10 @@ CURLKHTYPE_RSA1                 7.19.6 | |||||||
| CURLKHTYPE_UNKNOWN              7.19.6 | CURLKHTYPE_UNKNOWN              7.19.6 | ||||||
| CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0 | CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0 | ||||||
| CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0 | CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0 | ||||||
|  | CURLMOPT_MAXCONNECTS            7.16.3 | ||||||
| CURLMOPT_MAX_HOST_CONNECTIONS   7.30.0 | CURLMOPT_MAX_HOST_CONNECTIONS   7.30.0 | ||||||
| CURLMOPT_MAX_PIPELINE_LENGTH    7.30.0 | CURLMOPT_MAX_PIPELINE_LENGTH    7.30.0 | ||||||
| CURLMOPT_MAX_TOTAL_CONNECTIONS  7.30.0 | CURLMOPT_MAX_TOTAL_CONNECTIONS  7.30.0 | ||||||
| CURLMOPT_MAXCONNECTS            7.16.3 |  | ||||||
| CURLMOPT_PIPELINING             7.16.0 | CURLMOPT_PIPELINING             7.16.0 | ||||||
| CURLMOPT_PIPELINING_SERVER_BL   7.30.0 | CURLMOPT_PIPELINING_SERVER_BL   7.30.0 | ||||||
| CURLMOPT_PIPELINING_SITE_BL     7.30.0 | CURLMOPT_PIPELINING_SITE_BL     7.30.0 | ||||||
| @@ -283,6 +284,7 @@ CURLMOPT_TIMERDATA              7.16.0 | |||||||
| CURLMOPT_TIMERFUNCTION          7.16.0 | CURLMOPT_TIMERFUNCTION          7.16.0 | ||||||
| CURLMSG_DONE                    7.9.6 | CURLMSG_DONE                    7.9.6 | ||||||
| CURLMSG_NONE                    7.9.6 | CURLMSG_NONE                    7.9.6 | ||||||
|  | CURLM_ADDED_ALREADY             7.32.1 | ||||||
| CURLM_BAD_EASY_HANDLE           7.9.6 | CURLM_BAD_EASY_HANDLE           7.9.6 | ||||||
| CURLM_BAD_HANDLE                7.9.6 | CURLM_BAD_HANDLE                7.9.6 | ||||||
| CURLM_BAD_SOCKET                7.15.4 | CURLM_BAD_SOCKET                7.15.4 | ||||||
| @@ -331,6 +333,9 @@ CURLOPT_DEBUGDATA               7.9.6 | |||||||
| CURLOPT_DEBUGFUNCTION           7.9.6 | CURLOPT_DEBUGFUNCTION           7.9.6 | ||||||
| CURLOPT_DIRLISTONLY             7.17.0 | CURLOPT_DIRLISTONLY             7.17.0 | ||||||
| CURLOPT_DNS_CACHE_TIMEOUT       7.9.3 | CURLOPT_DNS_CACHE_TIMEOUT       7.9.3 | ||||||
|  | CURLOPT_DNS_INTERFACE           7.33.0 | ||||||
|  | CURLOPT_DNS_LOCAL_IP4           7.33.0 | ||||||
|  | CURLOPT_DNS_LOCAL_IP6           7.33.0 | ||||||
| CURLOPT_DNS_SERVERS             7.24.0 | CURLOPT_DNS_SERVERS             7.24.0 | ||||||
| CURLOPT_DNS_USE_GLOBAL_CACHE    7.9.3         7.11.1 | CURLOPT_DNS_USE_GLOBAL_CACHE    7.9.3         7.11.1 | ||||||
| CURLOPT_EGDSOCKET               7.7 | CURLOPT_EGDSOCKET               7.7 | ||||||
| @@ -390,6 +395,7 @@ CURLOPT_KRB4LEVEL               7.3           7.17.0 | |||||||
| CURLOPT_KRBLEVEL                7.16.4 | CURLOPT_KRBLEVEL                7.16.4 | ||||||
| CURLOPT_LOCALPORT               7.15.2 | CURLOPT_LOCALPORT               7.15.2 | ||||||
| CURLOPT_LOCALPORTRANGE          7.15.2 | CURLOPT_LOCALPORTRANGE          7.15.2 | ||||||
|  | CURLOPT_LOGIN_OPTIONS           7.34.0 | ||||||
| CURLOPT_LOW_SPEED_LIMIT         7.1 | CURLOPT_LOW_SPEED_LIMIT         7.1 | ||||||
| CURLOPT_LOW_SPEED_TIME          7.1 | CURLOPT_LOW_SPEED_TIME          7.1 | ||||||
| CURLOPT_MAIL_AUTH               7.25.0 | CURLOPT_MAIL_AUTH               7.25.0 | ||||||
| @@ -428,7 +434,7 @@ CURLOPT_POSTREDIR               7.19.1 | |||||||
| CURLOPT_PREQUOTE                7.9.5 | CURLOPT_PREQUOTE                7.9.5 | ||||||
| CURLOPT_PRIVATE                 7.10.3 | CURLOPT_PRIVATE                 7.10.3 | ||||||
| CURLOPT_PROGRESSDATA            7.1 | CURLOPT_PROGRESSDATA            7.1 | ||||||
| CURLOPT_PROGRESSFUNCTION        7.1 | CURLOPT_PROGRESSFUNCTION        7.1           7.32.0 | ||||||
| CURLOPT_PROTOCOLS               7.19.4 | CURLOPT_PROTOCOLS               7.19.4 | ||||||
| CURLOPT_PROXY                   7.1 | CURLOPT_PROXY                   7.1 | ||||||
| CURLOPT_PROXYAUTH               7.10.7 | CURLOPT_PROXYAUTH               7.10.7 | ||||||
| @@ -525,6 +531,9 @@ CURLOPT_WRITEDATA               7.9.7 | |||||||
| CURLOPT_WRITEFUNCTION           7.1 | CURLOPT_WRITEFUNCTION           7.1 | ||||||
| CURLOPT_WRITEHEADER             7.1 | CURLOPT_WRITEHEADER             7.1 | ||||||
| CURLOPT_WRITEINFO               7.1 | CURLOPT_WRITEINFO               7.1 | ||||||
|  | CURLOPT_XFERINFODATA            7.32.0 | ||||||
|  | CURLOPT_XFERINFOFUNCTION        7.32.0 | ||||||
|  | CURLOPT_XOAUTH2_BEARER          7.33.0 | ||||||
| CURLPAUSE_ALL                   7.18.0 | CURLPAUSE_ALL                   7.18.0 | ||||||
| CURLPAUSE_CONT                  7.18.0 | CURLPAUSE_CONT                  7.18.0 | ||||||
| CURLPAUSE_RECV                  7.18.0 | CURLPAUSE_RECV                  7.18.0 | ||||||
| @@ -586,6 +595,16 @@ CURLSSH_AUTH_KEYBOARD           7.16.1 | |||||||
| CURLSSH_AUTH_NONE               7.16.1 | CURLSSH_AUTH_NONE               7.16.1 | ||||||
| CURLSSH_AUTH_PASSWORD           7.16.1 | CURLSSH_AUTH_PASSWORD           7.16.1 | ||||||
| CURLSSH_AUTH_PUBLICKEY          7.16.1 | CURLSSH_AUTH_PUBLICKEY          7.16.1 | ||||||
|  | CURLSSLBACKEND_CYASSL           7.34.0 | ||||||
|  | CURLSSLBACKEND_DARWINSSL        7.34.0 | ||||||
|  | CURLSSLBACKEND_GNUTLS           7.34.0 | ||||||
|  | CURLSSLBACKEND_GSKIT            7.34.0 | ||||||
|  | CURLSSLBACKEND_NONE             7.34.0 | ||||||
|  | CURLSSLBACKEND_NSS              7.34.0 | ||||||
|  | CURLSSLBACKEND_OPENSSL          7.34.0 | ||||||
|  | CURLSSLBACKEND_POLARSSL         7.34.0 | ||||||
|  | CURLSSLBACKEND_QSOSSL           7.34.0 | ||||||
|  | CURLSSLBACKEND_SCHANNEL         7.34.0 | ||||||
| CURLSSLOPT_ALLOW_BEAST          7.25.0 | CURLSSLOPT_ALLOW_BEAST          7.25.0 | ||||||
| CURLUSESSL_ALL                  7.17.0 | CURLUSESSL_ALL                  7.17.0 | ||||||
| CURLUSESSL_CONTROL              7.17.0 | CURLUSESSL_CONTROL              7.17.0 | ||||||
| @@ -618,14 +637,15 @@ CURL_FORMADD_NULL               7.9.8 | |||||||
| CURL_FORMADD_OK                 7.9.8 | CURL_FORMADD_OK                 7.9.8 | ||||||
| CURL_FORMADD_OPTION_TWICE       7.9.8 | CURL_FORMADD_OPTION_TWICE       7.9.8 | ||||||
| CURL_FORMADD_UNKNOWN_OPTION     7.9.8 | CURL_FORMADD_UNKNOWN_OPTION     7.9.8 | ||||||
|  | CURL_GLOBAL_ACK_EINTR           7.30.0 | ||||||
| CURL_GLOBAL_ALL                 7.8 | CURL_GLOBAL_ALL                 7.8 | ||||||
| CURL_GLOBAL_DEFAULT             7.8 | CURL_GLOBAL_DEFAULT             7.8 | ||||||
| CURL_GLOBAL_NOTHING             7.8 | CURL_GLOBAL_NOTHING             7.8 | ||||||
| CURL_GLOBAL_SSL                 7.8 | CURL_GLOBAL_SSL                 7.8 | ||||||
| CURL_GLOBAL_WIN32               7.8.1 | CURL_GLOBAL_WIN32               7.8.1 | ||||||
| CURL_GLOBAL_ACK_EINTR           7.30.0 |  | ||||||
| CURL_HTTP_VERSION_1_0           7.9.1 | CURL_HTTP_VERSION_1_0           7.9.1 | ||||||
| CURL_HTTP_VERSION_1_1           7.9.1 | CURL_HTTP_VERSION_1_1           7.9.1 | ||||||
|  | CURL_HTTP_VERSION_2_0           7.33.0 | ||||||
| CURL_HTTP_VERSION_NONE          7.9.1 | CURL_HTTP_VERSION_NONE          7.9.1 | ||||||
| CURL_IPRESOLVE_V4               7.10.8 | CURL_IPRESOLVE_V4               7.10.8 | ||||||
| CURL_IPRESOLVE_V6               7.10.8 | CURL_IPRESOLVE_V6               7.10.8 | ||||||
| @@ -687,6 +707,9 @@ CURL_SSLVERSION_DEFAULT         7.9.2 | |||||||
| CURL_SSLVERSION_SSLv2           7.9.2 | CURL_SSLVERSION_SSLv2           7.9.2 | ||||||
| CURL_SSLVERSION_SSLv3           7.9.2 | CURL_SSLVERSION_SSLv3           7.9.2 | ||||||
| CURL_SSLVERSION_TLSv1           7.9.2 | CURL_SSLVERSION_TLSv1           7.9.2 | ||||||
|  | CURL_SSLVERSION_TLSv1_0         7.34.0 | ||||||
|  | CURL_SSLVERSION_TLSv1_1         7.34.0 | ||||||
|  | CURL_SSLVERSION_TLSv1_2         7.34.0 | ||||||
| CURL_TIMECOND_IFMODSINCE        7.9.7 | CURL_TIMECOND_IFMODSINCE        7.9.7 | ||||||
| CURL_TIMECOND_IFUNMODSINCE      7.9.7 | CURL_TIMECOND_IFUNMODSINCE      7.9.7 | ||||||
| CURL_TIMECOND_LASTMOD           7.9.7 | CURL_TIMECOND_LASTMOD           7.9.7 | ||||||
| @@ -698,6 +721,7 @@ CURL_VERSION_CONV               7.15.4 | |||||||
| CURL_VERSION_CURLDEBUG          7.19.6 | CURL_VERSION_CURLDEBUG          7.19.6 | ||||||
| CURL_VERSION_DEBUG              7.10.6 | CURL_VERSION_DEBUG              7.10.6 | ||||||
| CURL_VERSION_GSSNEGOTIATE       7.10.6 | CURL_VERSION_GSSNEGOTIATE       7.10.6 | ||||||
|  | CURL_VERSION_HTTP2              7.33.0 | ||||||
| CURL_VERSION_IDN                7.12.0 | CURL_VERSION_IDN                7.12.0 | ||||||
| CURL_VERSION_IPV6               7.10 | CURL_VERSION_IPV6               7.10 | ||||||
| CURL_VERSION_KERBEROS4          7.10 | CURL_VERSION_KERBEROS4          7.10 | ||||||
|   | |||||||
| @@ -60,11 +60,16 @@ unlink (remove) certdata.txt after processing | |||||||
| be verbose and print out processed CAs | be verbose and print out processed CAs | ||||||
| .SH EXIT STATUS | .SH EXIT STATUS | ||||||
| Returns 0 on success. Returns 1 if it fails to download data. | Returns 0 on success. Returns 1 if it fails to download data. | ||||||
|  | .SH CERTDATA FORMAT | ||||||
|  | The file format used by Mozilla for this trust information seems to be documented here: | ||||||
|  | .nf | ||||||
|  | http://p11-glue.freedesktop.org/doc/storing-trust-policy/storing-trust-existing.html | ||||||
|  | .fi | ||||||
| .SH SEE ALSO | .SH SEE ALSO | ||||||
| .BR curl (1) | .BR curl (1) | ||||||
| .SH HISTORY | .SH HISTORY | ||||||
| \fBmk-ca-bundle\fP is a command line tool that is shipped as part of every | \fBmk-ca-bundle\fP is a command line tool that is shipped as part of every | ||||||
| curl and libcurl release (see http://curl.haxx.se/). It was originally based | curl and libcurl release (see http://curl.haxx.se/). It was originally based | ||||||
| on the parse-certs script written by Roland Krikava and was later much | on the parse-certs script written by Roland Krikava and was later much | ||||||
| improved by Guenter Knauf.  This manual page was written by Jan Schaumann | improved by Guenter Knauf.  This manual page was initially written by Jan | ||||||
| \&<jschauma@netmeister.org>. | Schaumann \&<jschauma@netmeister.org>. | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ | |||||||
|    require it! */ |    require it! */ | ||||||
| #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ | #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ | ||||||
|     defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ |     defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ | ||||||
|     defined(ANDROID) || defined(__ANDROID__) || \ |     defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ | ||||||
|    (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) |    (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) | ||||||
| #include <sys/select.h> | #include <sys/select.h> | ||||||
| #endif | #endif | ||||||
| @@ -156,12 +156,22 @@ struct curl_httppost { | |||||||
|                                        HTTPPOST_CALLBACK posts */ |                                        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, | typedef int (*curl_progress_callback)(void *clientp, | ||||||
|                                       double dltotal, |                                       double dltotal, | ||||||
|                                       double dlnow, |                                       double dlnow, | ||||||
|                                       double ultotal, |                                       double ultotal, | ||||||
|                                       double ulnow); |                                       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 | #ifndef CURL_MAX_WRITE_SIZE | ||||||
|   /* Tests have proven that 20K is a very bad buffer size for uploads on |   /* 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. |      Windows, while 16K for some odd reason performed a lot better. | ||||||
| @@ -635,16 +645,18 @@ typedef enum { | |||||||
|  |  | ||||||
| #define CURL_ERROR_SIZE 256 | #define CURL_ERROR_SIZE 256 | ||||||
|  |  | ||||||
|  | enum curl_khtype { | ||||||
|  |   CURLKHTYPE_UNKNOWN, | ||||||
|  |   CURLKHTYPE_RSA1, | ||||||
|  |   CURLKHTYPE_RSA, | ||||||
|  |   CURLKHTYPE_DSS | ||||||
|  | }; | ||||||
|  |  | ||||||
| struct curl_khkey { | struct curl_khkey { | ||||||
|   const char *key; /* points to a zero-terminated string encoded with base64 |   const char *key; /* points to a zero-terminated string encoded with base64 | ||||||
|                       if len is zero, otherwise to the "raw" data */ |                       if len is zero, otherwise to the "raw" data */ | ||||||
|   size_t len; |   size_t len; | ||||||
|   enum type { |   enum curl_khtype keytype; | ||||||
|     CURLKHTYPE_UNKNOWN, |  | ||||||
|     CURLKHTYPE_RSA1, |  | ||||||
|     CURLKHTYPE_RSA, |  | ||||||
|     CURLKHTYPE_DSS |  | ||||||
|   } keytype; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* this is the set of return values expected from the curl_sshkeycallback | /* this is the set of return values expected from the curl_sshkeycallback | ||||||
| @@ -815,10 +827,10 @@ typedef enum { | |||||||
|   /* Name of proxy to use. */ |   /* Name of proxy to use. */ | ||||||
|   CINIT(PROXY, OBJECTPOINT, 4), |   CINIT(PROXY, OBJECTPOINT, 4), | ||||||
|  |  | ||||||
|   /* "name:password" to use when fetching. */ |   /* "user:password;options" to use when fetching. */ | ||||||
|   CINIT(USERPWD, OBJECTPOINT, 5), |   CINIT(USERPWD, OBJECTPOINT, 5), | ||||||
|  |  | ||||||
|   /* "name:password" to use with proxy. */ |   /* "user:password" to use with proxy. */ | ||||||
|   CINIT(PROXYUSERPWD, OBJECTPOINT, 6), |   CINIT(PROXYUSERPWD, OBJECTPOINT, 6), | ||||||
|  |  | ||||||
|   /* Range to get, specified as an ASCII string. */ |   /* Range to get, specified as an ASCII string. */ | ||||||
| @@ -968,13 +980,16 @@ typedef enum { | |||||||
|  |  | ||||||
|   /* 55 = OBSOLETE */ |   /* 55 = OBSOLETE */ | ||||||
|  |  | ||||||
|   /* Function that will be called instead of the internal progress display |   /* DEPRECATED | ||||||
|  |    * Function that will be called instead of the internal progress display | ||||||
|    * function. This function should be defined as the curl_progress_callback |    * function. This function should be defined as the curl_progress_callback | ||||||
|    * prototype defines. */ |    * prototype defines. */ | ||||||
|   CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), |   CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), | ||||||
|  |  | ||||||
|   /* Data passed to the progress callback */ |   /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION | ||||||
|  |      callbacks */ | ||||||
|   CINIT(PROGRESSDATA, OBJECTPOINT, 57), |   CINIT(PROGRESSDATA, OBJECTPOINT, 57), | ||||||
|  | #define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA | ||||||
|  |  | ||||||
|   /* We want the referrer field set automatically when following locations */ |   /* We want the referrer field set automatically when following locations */ | ||||||
|   CINIT(AUTOREFERER, LONG, 58), |   CINIT(AUTOREFERER, LONG, 58), | ||||||
| @@ -1373,8 +1388,7 @@ typedef enum { | |||||||
|   CINIT(ADDRESS_SCOPE, LONG, 171), |   CINIT(ADDRESS_SCOPE, LONG, 171), | ||||||
|  |  | ||||||
|   /* Collect certificate chain info and allow it to get retrievable with |   /* Collect certificate chain info and allow it to get retrievable with | ||||||
|      CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only |      CURLINFO_CERTINFO after the transfer is complete. */ | ||||||
|      working with OpenSSL-powered builds. */ |  | ||||||
|   CINIT(CERTINFO, LONG, 172), |   CINIT(CERTINFO, LONG, 172), | ||||||
|  |  | ||||||
|   /* "name" and "pwd" to use when fetching. */ |   /* "name" and "pwd" to use when fetching. */ | ||||||
| @@ -1533,6 +1547,30 @@ typedef enum { | |||||||
|   /* Enable/disable SASL initial response */ |   /* Enable/disable SASL initial response */ | ||||||
|   CINIT(SASL_IR, LONG, 218), |   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), | ||||||
|  |  | ||||||
|   CURLOPT_LASTENTRY /* the last unused */ |   CURLOPT_LASTENTRY /* the last unused */ | ||||||
| } CURLoption; | } CURLoption; | ||||||
|  |  | ||||||
| @@ -1585,6 +1623,7 @@ enum { | |||||||
|                              for us! */ |                              for us! */ | ||||||
|   CURL_HTTP_VERSION_1_0,  /* please use HTTP 1.0 in the request */ |   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_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 */ |   CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ | ||||||
| }; | }; | ||||||
| @@ -1622,9 +1661,12 @@ enum CURL_NETRC_OPTION { | |||||||
|  |  | ||||||
| enum { | enum { | ||||||
|   CURL_SSLVERSION_DEFAULT, |   CURL_SSLVERSION_DEFAULT, | ||||||
|   CURL_SSLVERSION_TLSv1, |   CURL_SSLVERSION_TLSv1, /* TLS 1.x */ | ||||||
|   CURL_SSLVERSION_SSLv2, |   CURL_SSLVERSION_SSLv2, | ||||||
|   CURL_SSLVERSION_SSLv3, |   CURL_SSLVERSION_SSLv3, | ||||||
|  |   CURL_SSLVERSION_TLSv1_0, | ||||||
|  |   CURL_SSLVERSION_TLSv1_1, | ||||||
|  |   CURL_SSLVERSION_TLSv1_2, | ||||||
|  |  | ||||||
|   CURL_SSLVERSION_LAST /* never use, keep last */ |   CURL_SSLVERSION_LAST /* never use, keep last */ | ||||||
| }; | }; | ||||||
| @@ -1943,6 +1985,28 @@ struct curl_certinfo { | |||||||
|                                    format "name: value" */ |                                    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_QSOSSL = 4, | ||||||
|  |   CURLSSLBACKEND_GSKIT = 5, | ||||||
|  |   CURLSSLBACKEND_POLARSSL = 6, | ||||||
|  |   CURLSSLBACKEND_CYASSL = 7, | ||||||
|  |   CURLSSLBACKEND_SCHANNEL = 8, | ||||||
|  |   CURLSSLBACKEND_DARWINSSL = 9 | ||||||
|  | } 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_STRING   0x100000 | ||||||
| #define CURLINFO_LONG     0x200000 | #define CURLINFO_LONG     0x200000 | ||||||
| #define CURLINFO_DOUBLE   0x300000 | #define CURLINFO_DOUBLE   0x300000 | ||||||
| @@ -1994,9 +2058,10 @@ typedef enum { | |||||||
|   CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40, |   CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40, | ||||||
|   CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41, |   CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41, | ||||||
|   CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42, |   CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42, | ||||||
|  |   CURLINFO_TLS_SESSION      = CURLINFO_SLIST  + 43, | ||||||
|   /* Fill in new entries below here! */ |   /* Fill in new entries below here! */ | ||||||
|  |  | ||||||
|   CURLINFO_LASTONE          = 42 |   CURLINFO_LASTONE          = 43 | ||||||
| } CURLINFO; | } CURLINFO; | ||||||
|  |  | ||||||
| /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as | /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as | ||||||
| @@ -2148,6 +2213,7 @@ typedef struct { | |||||||
| #define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking 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_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ | ||||||
| #define CURL_VERSION_NTLM_WB   (1<<15) /* NTLM delegating to winbind helper */ | #define CURL_VERSION_NTLM_WB   (1<<15) /* NTLM delegating to winbind helper */ | ||||||
|  | #define CURL_VERSION_HTTP2     (1<<16) /* HTTP2 support built-in */ | ||||||
|  |  | ||||||
|  /* |  /* | ||||||
|  * NAME curl_version_info() |  * NAME curl_version_info() | ||||||
|   | |||||||
| @@ -58,51 +58,52 @@ | |||||||
| /* ================================================================ */ | /* ================================================================ */ | ||||||
|  |  | ||||||
| #ifdef CURL_SIZEOF_LONG | #ifdef CURL_SIZEOF_LONG | ||||||
| #  error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" | #error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined |    Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_TYPEOF_CURL_SOCKLEN_T | #ifdef CURL_TYPEOF_CURL_SOCKLEN_T | ||||||
| #  error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" | #error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined |    Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_SIZEOF_CURL_SOCKLEN_T | #ifdef CURL_SIZEOF_CURL_SOCKLEN_T | ||||||
| #  error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" | #error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined |    Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_TYPEOF_CURL_OFF_T | #ifdef CURL_TYPEOF_CURL_OFF_T | ||||||
| #  error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" | #error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined |    Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_FORMAT_CURL_OFF_T | #ifdef CURL_FORMAT_CURL_OFF_T | ||||||
| #  error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" | #error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined |    Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_FORMAT_CURL_OFF_TU | #ifdef CURL_FORMAT_CURL_OFF_TU | ||||||
| #  error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" | #error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined |    Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_FORMAT_OFF_T | #ifdef CURL_FORMAT_OFF_T | ||||||
| #  error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" | #error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined |    Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_SIZEOF_CURL_OFF_T | #ifdef CURL_SIZEOF_CURL_OFF_T | ||||||
| #  error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" | #error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined |    Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_SUFFIX_CURL_OFF_T | #ifdef CURL_SUFFIX_CURL_OFF_T | ||||||
| #  error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" | #error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined |    Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef CURL_SUFFIX_CURL_OFF_TU | #ifdef CURL_SUFFIX_CURL_OFF_TU | ||||||
| #  error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" | #error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" | ||||||
|    Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined |    Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -110,71 +111,87 @@ | |||||||
| /*  EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY  */ | /*  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 <windows.h> | ||||||
|  | #  include <winsock2.h> | ||||||
|  | #  include <ws2tcpip.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* Configure process defines this to 1 when it finds out that system   */ | /* Configure process defines this to 1 when it finds out that system   */ | ||||||
| /* header file sys/types.h must be included by the external interface. */ | /* header file sys/types.h must be included by the external interface. */ | ||||||
| #cmakedefine CURL_PULL_SYS_TYPES_H ${CURL_PULL_SYS_TYPES_H} | #cmakedefine CURL_PULL_SYS_TYPES_H | ||||||
| #ifdef CURL_PULL_SYS_TYPES_H | #ifdef CURL_PULL_SYS_TYPES_H | ||||||
| #  include <sys/types.h> | #  include <sys/types.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* Configure process defines this to 1 when it finds out that system */ | /* Configure process defines this to 1 when it finds out that system */ | ||||||
| /* header file stdint.h must be included by the external interface.  */ | /* header file stdint.h must be included by the external interface.  */ | ||||||
| #cmakedefine CURL_PULL_STDINT_H ${CURL_PULL_STDINT_H} | #cmakedefine CURL_PULL_STDINT_H | ||||||
| #ifdef CURL_PULL_STDINT_H | #ifdef CURL_PULL_STDINT_H | ||||||
| #  include <stdint.h> | #  include <stdint.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* Configure process defines this to 1 when it finds out that system  */ | /* Configure process defines this to 1 when it finds out that system  */ | ||||||
| /* header file inttypes.h must be included by the external interface. */ | /* header file inttypes.h must be included by the external interface. */ | ||||||
| #cmakedefine CURL_PULL_INTTYPES_H ${CURL_PULL_INTTYPES_H} | #cmakedefine CURL_PULL_INTTYPES_H | ||||||
| #ifdef CURL_PULL_INTTYPES_H | #ifdef CURL_PULL_INTTYPES_H | ||||||
| #  include <inttypes.h> | #  include <inttypes.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* The size of `long', as computed by sizeof. */ | /* Configure process defines this to 1 when it finds out that system    */ | ||||||
| #cmakedefine CURL_SIZEOF_LONG ${CURL_SIZEOF_LONG} | /* header file sys/socket.h must be included by the external interface. */ | ||||||
|  | #cmakedefine CURL_PULL_SYS_SOCKET_H | ||||||
| /* Integral data type used for curl_socklen_t. */ | #ifdef CURL_PULL_SYS_SOCKET_H | ||||||
| #cmakedefine CURL_TYPEOF_CURL_SOCKLEN_T ${CURL_TYPEOF_CURL_SOCKLEN_T} |  | ||||||
|  |  | ||||||
| /* on windows socklen_t is in here */ |  | ||||||
| #ifdef _WIN32 |  | ||||||
| #  include <winsock2.h> |  | ||||||
| #  include <ws2tcpip.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef HAVE_SYS_SOCKET_H |  | ||||||
| #  include <sys/socket.h> | #  include <sys/socket.h> | ||||||
| #endif | #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 <sys/poll.h> | ||||||
|  | #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. */ | /* Data type definition of curl_socklen_t. */ | ||||||
| typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; | typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; | ||||||
|  |  | ||||||
| /* The size of `curl_socklen_t', as computed by sizeof. */ |  | ||||||
| #cmakedefine CURL_SIZEOF_CURL_SOCKLEN_T ${CURL_SIZEOF_CURL_SOCKLEN_T} |  | ||||||
|  |  | ||||||
| /* Signed integral data type used for curl_off_t. */ | /* Signed integral data type used for curl_off_t. */ | ||||||
| #cmakedefine CURL_TYPEOF_CURL_OFF_T ${CURL_TYPEOF_CURL_OFF_T} | #define CURL_TYPEOF_CURL_OFF_T ${CURL_TYPEOF_CURL_OFF_T} | ||||||
|  |  | ||||||
| /* Data type definition of curl_off_t. */ | /* Data type definition of curl_off_t. */ | ||||||
| typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; | typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; | ||||||
|  |  | ||||||
| /* curl_off_t formatting string directive without "%" conversion specifier. */ | /* curl_off_t formatting string directive without "%" conversion specifier. */ | ||||||
| #cmakedefine CURL_FORMAT_CURL_OFF_T "${CURL_FORMAT_CURL_OFF_T}" | #define CURL_FORMAT_CURL_OFF_T "${CURL_FORMAT_CURL_OFF_T}" | ||||||
|  |  | ||||||
| /* unsigned curl_off_t formatting string without "%" conversion specifier. */ | /* unsigned curl_off_t formatting string without "%" conversion specifier. */ | ||||||
| #cmakedefine CURL_FORMAT_CURL_OFF_TU "${CURL_FORMAT_CURL_OFF_TU}" | #define CURL_FORMAT_CURL_OFF_TU "${CURL_FORMAT_CURL_OFF_TU}" | ||||||
|  |  | ||||||
| /* curl_off_t formatting string directive with "%" conversion specifier. */ | /* curl_off_t formatting string directive with "%" conversion specifier. */ | ||||||
| #cmakedefine CURL_FORMAT_OFF_T "${CURL_FORMAT_OFF_T}" | #define CURL_FORMAT_OFF_T "${CURL_FORMAT_OFF_T}" | ||||||
|  |  | ||||||
| /* The size of `curl_off_t', as computed by sizeof. */ | /* The size of `curl_off_t', as computed by sizeof. */ | ||||||
| #cmakedefine CURL_SIZEOF_CURL_OFF_T ${CURL_SIZEOF_CURL_OFF_T} | #define CURL_SIZEOF_CURL_OFF_T ${CURL_SIZEOF_CURL_OFF_T} | ||||||
|  |  | ||||||
| /* curl_off_t constant suffix. */ | /* curl_off_t constant suffix. */ | ||||||
| #cmakedefine CURL_SUFFIX_CURL_OFF_T ${CURL_SUFFIX_CURL_OFF_T} | #define CURL_SUFFIX_CURL_OFF_T ${CURL_SUFFIX_CURL_OFF_T} | ||||||
|  |  | ||||||
| /* unsigned curl_off_t constant suffix. */ | /* unsigned curl_off_t constant suffix. */ | ||||||
| #cmakedefine CURL_SUFFIX_CURL_OFF_TU ${CURL_SUFFIX_CURL_OFF_TU} | #define CURL_SUFFIX_CURL_OFF_TU ${CURL_SUFFIX_CURL_OFF_TU} | ||||||
|  |  | ||||||
| #endif /* __CURL_CURLBUILD_H */ | #endif /* __CURL_CURLBUILD_H */ | ||||||
|   | |||||||
| @@ -30,12 +30,12 @@ | |||||||
|  |  | ||||||
| /* This is the version number of the libcurl package from which this header | /* This is the version number of the libcurl package from which this header | ||||||
|    file origins: */ |    file origins: */ | ||||||
| #define LIBCURL_VERSION "7.31.0-DEV" | #define LIBCURL_VERSION "7.34.0-DEV" | ||||||
|  |  | ||||||
| /* The numeric version number is also available "in parts" by using these | /* The numeric version number is also available "in parts" by using these | ||||||
|    defines: */ |    defines: */ | ||||||
| #define LIBCURL_VERSION_MAJOR 7 | #define LIBCURL_VERSION_MAJOR 7 | ||||||
| #define LIBCURL_VERSION_MINOR 31 | #define LIBCURL_VERSION_MINOR 34 | ||||||
| #define LIBCURL_VERSION_PATCH 0 | #define LIBCURL_VERSION_PATCH 0 | ||||||
|  |  | ||||||
| /* This is the numeric version of the libcurl version number, meant for easier | /* This is the numeric version of the libcurl version number, meant for easier | ||||||
| @@ -53,7 +53,7 @@ | |||||||
|    and it is always a greater number in a more recent release. It makes |    and it is always a greater number in a more recent release. It makes | ||||||
|    comparisons with greater than and less than work. |    comparisons with greater than and less than work. | ||||||
| */ | */ | ||||||
| #define LIBCURL_VERSION_NUM 0x071f00 | #define LIBCURL_VERSION_NUM 0x072200 | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * This is the date and time when the full source package was created. The |  * This is the date and time when the full source package was created. The | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -64,6 +64,8 @@ typedef enum { | |||||||
|   CURLM_INTERNAL_ERROR,  /* this is a libcurl bug */ |   CURLM_INTERNAL_ERROR,  /* this is a libcurl bug */ | ||||||
|   CURLM_BAD_SOCKET,      /* the passed in socket argument did not match */ |   CURLM_BAD_SOCKET,      /* the passed in socket argument did not match */ | ||||||
|   CURLM_UNKNOWN_OPTION,  /* curl_multi_setopt() with unsupported option */ |   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 |   CURLM_LAST | ||||||
| } CURLMcode; | } CURLMcode; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -264,6 +264,12 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, | |||||||
|    (option) == CURLOPT_RTSP_SESSION_ID ||                                     \ |    (option) == CURLOPT_RTSP_SESSION_ID ||                                     \ | ||||||
|    (option) == CURLOPT_RTSP_STREAM_URI ||                                     \ |    (option) == CURLOPT_RTSP_STREAM_URI ||                                     \ | ||||||
|    (option) == CURLOPT_RTSP_TRANSPORT ||                                      \ |    (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) |    0) | ||||||
|  |  | ||||||
| /* evaluates to true if option takes a curl_write_callback argument */ | /* evaluates to true if option takes a curl_write_callback argument */ | ||||||
|   | |||||||
| @@ -94,6 +94,10 @@ add_library( | |||||||
|   ${HHEADERS} ${CSOURCES} |   ${HHEADERS} ${CSOURCES} | ||||||
|   ) |   ) | ||||||
|  |  | ||||||
|  | if(MSVC AND CURL_STATICLIB) | ||||||
|  |   set_target_properties(${LIB_NAME} PROPERTIES STATIC_LIBRARY_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) | ||||||
|  | endif() | ||||||
|  |  | ||||||
| target_link_libraries(${LIB_NAME} ${CURL_LIBS}) | target_link_libraries(${LIB_NAME} ${CURL_LIBS}) | ||||||
|  |  | ||||||
| if(WIN32) | if(WIN32) | ||||||
| @@ -108,14 +112,6 @@ setup_curl_dependencies(${LIB_NAME}) | |||||||
| set_target_properties(${LIB_NAME} PROPERTIES PREFIX "") | set_target_properties(${LIB_NAME} PROPERTIES PREFIX "") | ||||||
| set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "") | set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "") | ||||||
|  |  | ||||||
| if(MSVC) |  | ||||||
|   if(NOT BUILD_RELEASE_DEBUG_DIRS) |  | ||||||
|     # Ugly workaround to remove the "/debug" or "/release" in each output |  | ||||||
|     set_target_properties(${LIB_NAME} PROPERTIES PREFIX "../") |  | ||||||
|     set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "../") |  | ||||||
|   endif() |  | ||||||
| endif() |  | ||||||
|  |  | ||||||
| if(WIN32) | if(WIN32) | ||||||
|   if(NOT CURL_STATICLIB) |   if(NOT CURL_STATICLIB) | ||||||
|     # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib" |     # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib" | ||||||
|   | |||||||
| @@ -141,7 +141,7 @@ libcurl_la_CFLAGS_EXTRA += $(CFLAG_CURL_SYMBOL_HIDING) | |||||||
| endif | endif | ||||||
|  |  | ||||||
| libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA) | libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA) | ||||||
| libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LIBCURL_LIBS) | libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS) | ||||||
| libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) | libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) | ||||||
|  |  | ||||||
| libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS | libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ LDFLAGS  = -q -lq -laa -tWD | |||||||
| SRCDIR   = . | SRCDIR   = . | ||||||
| OBJDIR   = .\BCC_objs | OBJDIR   = .\BCC_objs | ||||||
| INCDIRS  = -I.;..\include | INCDIRS  = -I.;..\include | ||||||
| LINKLIB  = $(BCCDIR)\lib\cw32mt.lib | LINKLIB  = $(BCCDIR)\lib\cw32mt.lib $(BCCDIR)\lib\ws2_32.lib | ||||||
| DEFINES  = -DNDEBUG -DWIN32 -DBUILDING_LIBCURL | DEFINES  = -DNDEBUG -DWIN32 -DBUILDING_LIBCURL | ||||||
|  |  | ||||||
| # By default SSPI support is enabled for BCC | # By default SSPI support is enabled for BCC | ||||||
| @@ -88,8 +88,24 @@ LINKLIB  = $(LINKLIB) $(OPENSSL_PATH)\out32\ssleay32.lib $(OPENSSL_PATH)\out32\l | |||||||
| # Makefile.inc provides the CSOURCES and HHEADERS defines | # Makefile.inc provides the CSOURCES and HHEADERS defines | ||||||
| !include Makefile.inc | !include Makefile.inc | ||||||
|  |  | ||||||
| OBJECTS = $(CSOURCES:.c=.obj) | # Borland's command line librarian program TLIB version 4.5 is not capable | ||||||
| PREPROCESSED = $(CSOURCES:.c=.int) | # of building a library when any of its objects contains an hypen in its | ||||||
|  | # name, due to a command line parsing bug. In order to workaround this, we | ||||||
|  | # build source files with hyphens in their name as objects with underscores | ||||||
|  | # using explicit compilation build rules instead of implicit ones. | ||||||
|  |  | ||||||
|  | NOHYPHEN = $(CSOURCES:-=_) | ||||||
|  |  | ||||||
|  | OBJECTS = $(NOHYPHEN:.c=.obj) | ||||||
|  | PREPROCESSED = $(NOHYPHEN:.c=.int) | ||||||
|  |  | ||||||
|  | # Borland's command line compiler (BCC32) version 5.5.1 integrated | ||||||
|  | # preprocessor has a bug which results in silently generating wrong | ||||||
|  | # definitions for libcurl macros such as CURL_OFF_T_C, on the other | ||||||
|  | # hand Borland's command line preprocessor (CPP32) version 5.5.1 does | ||||||
|  | # not have the bug and achieves proper results. In order to avoid the | ||||||
|  | # silent bug we first preprocess source files and later compile the | ||||||
|  | # preprocessed result. | ||||||
|  |  | ||||||
| .c.obj: | .c.obj: | ||||||
| 	@-$(RM) $(@R).int | 	@-$(RM) $(@R).int | ||||||
| @@ -98,6 +114,21 @@ PREPROCESSED = $(CSOURCES:.c=.int) | |||||||
|  |  | ||||||
| all:	$(OBJDIR) $(LIBCURL_LIB) $(LIBCURL_DLL) | all:	$(OBJDIR) $(LIBCURL_LIB) $(LIBCURL_DLL) | ||||||
|  |  | ||||||
|  | asyn_ares.obj: asyn-ares.c | ||||||
|  | 	@-$(RM) $(@R).int | ||||||
|  | 	$(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?) | ||||||
|  | 	$(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int | ||||||
|  |  | ||||||
|  | asyn_thread.obj: asyn-thread.c | ||||||
|  | 	@-$(RM) $(@R).int | ||||||
|  | 	$(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?) | ||||||
|  | 	$(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int | ||||||
|  |  | ||||||
|  | non_ascii.obj: non-ascii.c | ||||||
|  | 	@-$(RM) $(@R).int | ||||||
|  | 	$(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?) | ||||||
|  | 	$(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int | ||||||
|  |  | ||||||
| clean: | clean: | ||||||
| 	cd $(OBJDIR) | 	cd $(OBJDIR) | ||||||
| 	@-$(RM) $(OBJECTS) | 	@-$(RM) $(OBJECTS) | ||||||
| @@ -122,7 +153,10 @@ $(LIBCURL_LIB): $(OBJECTS) | |||||||
| $(LIBCURL_DLL) $(LIBCURL_IMPLIB): $(OBJECTS) $(LINKLIB) | $(LIBCURL_DLL) $(LIBCURL_IMPLIB): $(OBJECTS) $(LINKLIB) | ||||||
| 	@-$(RM) $(LIBCURL_DLL) | 	@-$(RM) $(LIBCURL_DLL) | ||||||
| 	@-$(RM) $(LIBCURL_IMPLIB) | 	@-$(RM) $(LIBCURL_IMPLIB) | ||||||
| 	$(LD) $(LDFLAGS) -e$(LIBCURL_DLL) $** | 	$(LD) $(LDFLAGS) -e$(LIBCURL_DLL) @&&! | ||||||
|  | $(**: = ^ | ||||||
|  | ) | ||||||
|  | ! | ||||||
| 	$(IMPLIB) $(LIBCURL_IMPLIB) $(LIBCURL_DLL) | 	$(IMPLIB) $(LIBCURL_IMPLIB) $(LIBCURL_DLL) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,10 +10,10 @@ | |||||||
| CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c	\ | CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c	\ | ||||||
|   cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c	\ |   cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c	\ | ||||||
|   ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c	\ |   ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c	\ | ||||||
|   netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c	\ |   netrc.c getinfo.c transfer.c strequal.c easy.c security.c      	\ | ||||||
|   curl_fnmatch.c fileinfo.c ftplistparser.c wildcard.c krb5.c		\ |   curl_fnmatch.c fileinfo.c ftplistparser.c wildcard.c krb5.c		\ | ||||||
|   memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c	\ |   memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c	\ | ||||||
|   content_encoding.c share.c http_digest.c md4.c md5.c curl_rand.c	\ |   content_encoding.c share.c http_digest.c md4.c md5.c	\ | ||||||
|   http_negotiate.c inet_pton.c strtoofft.c strerror.c amigaos.c		\ |   http_negotiate.c inet_pton.c strtoofft.c strerror.c amigaos.c		\ | ||||||
|   hostasyn.c hostip4.c hostip6.c hostsyn.c inet_ntop.c parsedate.c	\ |   hostasyn.c hostip4.c hostip6.c hostsyn.c inet_ntop.c parsedate.c	\ | ||||||
|   select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c	\ |   select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c	\ | ||||||
| @@ -25,12 +25,13 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c	\ | |||||||
|   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c	\ |   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c	\ | ||||||
|   curl_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_ntlm_msgs.c		\ |   curl_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_ntlm_msgs.c		\ | ||||||
|   curl_sasl.c curl_schannel.c curl_multibyte.c curl_darwinssl.c		\ |   curl_sasl.c curl_schannel.c curl_multibyte.c curl_darwinssl.c		\ | ||||||
|   hostcheck.c bundles.c conncache.c pipeline.c |   hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.c      \ | ||||||
|  |   gskit.c http2.c | ||||||
|  |  | ||||||
| HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h	\ | HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h	\ | ||||||
|   progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h	\ |   progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h	\ | ||||||
|   if2ip.h speedcheck.h urldata.h curl_ldap.h ssluse.h escape.h telnet.h	\ |   if2ip.h speedcheck.h urldata.h curl_ldap.h ssluse.h escape.h telnet.h	\ | ||||||
|   getinfo.h strequal.h krb4.h memdebug.h http_chunks.h curl_rand.h	\ |   getinfo.h strequal.h curl_sec.h memdebug.h http_chunks.h		\ | ||||||
|   curl_fnmatch.h wildcard.h fileinfo.h ftplistparser.h strtok.h		\ |   curl_fnmatch.h wildcard.h fileinfo.h ftplistparser.h strtok.h		\ | ||||||
|   connect.h llist.h hash.h content_encoding.h share.h curl_md4.h	\ |   connect.h llist.h hash.h content_encoding.h share.h curl_md4.h	\ | ||||||
|   curl_md5.h http_digest.h http_negotiate.h inet_pton.h amigaos.h	\ |   curl_md5.h http_digest.h http_negotiate.h inet_pton.h amigaos.h	\ | ||||||
| @@ -44,4 +45,5 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h	\ | |||||||
|   asyn.h curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h	\ |   asyn.h curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h	\ | ||||||
|   curl_ntlm_msgs.h curl_sasl.h curl_schannel.h curl_multibyte.h		\ |   curl_ntlm_msgs.h curl_sasl.h curl_schannel.h curl_multibyte.h		\ | ||||||
|   curl_darwinssl.h hostcheck.h bundles.h conncache.h curl_setup_once.h	\ |   curl_darwinssl.h hostcheck.h bundles.h conncache.h curl_setup_once.h	\ | ||||||
|   multihandle.h setup-vms.h pipeline.h |   multihandle.h setup-vms.h pipeline.h dotdot.h x509asn1.h gskit.h	\ | ||||||
|  |   http2.h sigpipe.h | ||||||
|   | |||||||
| @@ -103,23 +103,24 @@ WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK" | |||||||
| ############################################################# | ############################################################# | ||||||
| ## Nothing more to do below this line! | ## Nothing more to do below this line! | ||||||
|  |  | ||||||
| CCNODBG    = cl.exe /O2 /DNDEBUG | CCNODBG      = cl.exe /O2 /DNDEBUG | ||||||
| CCDEBUG    = cl.exe /Od /Gm /Zi /D_DEBUG /GZ | CCDEBUG      = cl.exe /Od /Gm /Zi /D_DEBUG /GZ | ||||||
| CFLAGSSSL  = /DUSE_SSLEAY /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl" | CFLAGSSSL    = /DUSE_SSLEAY /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl" | ||||||
| CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include" | CFLAGSWINSSL = /DUSE_SCHANNEL | ||||||
| CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)" | CFLAGSSSH2   = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include" | ||||||
| CFLAGS     = /I. /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1 | CFLAGSZLIB   = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)" | ||||||
| CFLAGSLIB  = /DCURL_STATICLIB | CFLAGS       = /I. /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1 | ||||||
| LNKDLL     = link.exe /DLL | CFLAGSLIB    = /DCURL_STATICLIB | ||||||
| LNKLIB     = link.exe /lib | LNKDLL       = link.exe /DLL | ||||||
| LFLAGS     = /nologo /machine:$(MACHINE) | LNKLIB       = link.exe /lib | ||||||
| SSLLIBS    = libeay32.lib ssleay32.lib | LFLAGS       = /nologo /machine:$(MACHINE) | ||||||
| ZLIBLIBSDLL= zdll.lib | SSLLIBS      = libeay32.lib ssleay32.lib | ||||||
| ZLIBLIBS   = zlib.lib | ZLIBLIBSDLL  = zdll.lib | ||||||
| WINLIBS    = ws2_32.lib wldap32.lib advapi32.lib | ZLIBLIBS     = zlib.lib | ||||||
| CFLAGS     = $(CFLAGS) | WINLIBS      = ws2_32.lib wldap32.lib advapi32.lib | ||||||
|  | CFLAGS       = $(CFLAGS) | ||||||
|  |  | ||||||
| CFGSET     = FALSE | CFGSET       = FALSE | ||||||
|  |  | ||||||
| !IFDEF WINDOWS_SSPI | !IFDEF WINDOWS_SSPI | ||||||
| CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include | CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include | ||||||
| @@ -189,6 +190,18 @@ CC       = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB) | |||||||
| CFGSET   = TRUE | CFGSET   = TRUE | ||||||
| !ENDIF | !ENDIF | ||||||
|  |  | ||||||
|  | ###################### | ||||||
|  | # release-winssl-zlib | ||||||
|  |  | ||||||
|  | !IF "$(CFG)" == "release-winssl-zlib" | ||||||
|  | TARGET   = $(LIBCURL_STA_LIB_REL) | ||||||
|  | DIROBJ   = $(CFG) | ||||||
|  | LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)" | ||||||
|  | LNK      = $(LNKLIB) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) | ||||||
|  | CC       = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSZLIB) $(CFLAGSLIB) | ||||||
|  | CFGSET   = TRUE | ||||||
|  | !ENDIF | ||||||
|  |  | ||||||
| ###################### | ###################### | ||||||
| # release-ssl-ssh2-zlib | # release-ssl-ssh2-zlib | ||||||
|  |  | ||||||
| @@ -515,7 +528,6 @@ X_OBJS= \ | |||||||
| 	$(DIROBJ)\curl_ntlm_core.obj \ | 	$(DIROBJ)\curl_ntlm_core.obj \ | ||||||
| 	$(DIROBJ)\curl_ntlm_msgs.obj \ | 	$(DIROBJ)\curl_ntlm_msgs.obj \ | ||||||
| 	$(DIROBJ)\curl_ntlm_wb.obj \ | 	$(DIROBJ)\curl_ntlm_wb.obj \ | ||||||
| 	$(DIROBJ)\curl_rand.obj \ |  | ||||||
| 	$(DIROBJ)\curl_rtmp.obj \ | 	$(DIROBJ)\curl_rtmp.obj \ | ||||||
| 	$(DIROBJ)\curl_sasl.obj \ | 	$(DIROBJ)\curl_sasl.obj \ | ||||||
| 	$(DIROBJ)\curl_schannel.obj \ | 	$(DIROBJ)\curl_schannel.obj \ | ||||||
| @@ -523,6 +535,7 @@ X_OBJS= \ | |||||||
| 	$(DIROBJ)\curl_threads.obj \ | 	$(DIROBJ)\curl_threads.obj \ | ||||||
| 	$(DIROBJ)\cyassl.obj \ | 	$(DIROBJ)\cyassl.obj \ | ||||||
| 	$(DIROBJ)\dict.obj \ | 	$(DIROBJ)\dict.obj \ | ||||||
|  | 	$(DIROBJ)\dotdot.obj \ | ||||||
| 	$(DIROBJ)\easy.obj \ | 	$(DIROBJ)\easy.obj \ | ||||||
| 	$(DIROBJ)\escape.obj \ | 	$(DIROBJ)\escape.obj \ | ||||||
| 	$(DIROBJ)\file.obj \ | 	$(DIROBJ)\file.obj \ | ||||||
| @@ -553,7 +566,6 @@ X_OBJS= \ | |||||||
| 	$(DIROBJ)\imap.obj \ | 	$(DIROBJ)\imap.obj \ | ||||||
| 	$(DIROBJ)\inet_ntop.obj \ | 	$(DIROBJ)\inet_ntop.obj \ | ||||||
| 	$(DIROBJ)\inet_pton.obj \ | 	$(DIROBJ)\inet_pton.obj \ | ||||||
| 	$(DIROBJ)\krb4.obj \ |  | ||||||
| 	$(DIROBJ)\krb5.obj \ | 	$(DIROBJ)\krb5.obj \ | ||||||
| 	$(DIROBJ)\ldap.obj \ | 	$(DIROBJ)\ldap.obj \ | ||||||
| 	$(DIROBJ)\llist.obj \ | 	$(DIROBJ)\llist.obj \ | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								lib/README.http2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/README.http2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  |  | ||||||
|  | HTTP2 with libcurl | ||||||
|  |  | ||||||
|  |  Spec: http://tools.ietf.org/html/draft-ietf-httpbis-http2-06 | ||||||
|  |  | ||||||
|  |  nghttp2 (https://github.com/tatsuhiro-t/nghttp2) | ||||||
|  |  | ||||||
|  |   We're depending on this 3rd party library for the actual low level protocol | ||||||
|  |   handling parts. The reason for this is that HTTP2 is much more complex at | ||||||
|  |   that layer than HTTP1.1 (which we implement on our own) and that nghttp2 is | ||||||
|  |   an already existing and well functional library. | ||||||
|  |  | ||||||
|  |  Over an http:// URL | ||||||
|  |  | ||||||
|  |   If CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_2, libcurl will include | ||||||
|  |   an upgrade header in the initial request to the host to allow upgrading to | ||||||
|  |   http2. Possibly introduce an option that will cause libcurl to fail if not | ||||||
|  |   possible to upgrade. Possibly introduce an option that makes libcurl use | ||||||
|  |   http2 at once over http:// | ||||||
|  |  | ||||||
|  |  Over an https:// URL | ||||||
|  |  | ||||||
|  |   If CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_2, libcurl will use ALPN | ||||||
|  |   (or NPN) to negotiate which protocol to continue with. Possibly introduce an | ||||||
|  |   option that will cause libcurl to fail if not possible to use http2. | ||||||
|  |  | ||||||
|  | To consider: | ||||||
|  |  | ||||||
|  |   - How to tell libcurl when using the multi interface that all or some of the | ||||||
|  |     handles are allowed to re-use the same physical connection. Can we just | ||||||
|  |     re-use existing pipelining logic? | ||||||
							
								
								
									
										133
									
								
								lib/asyn-ares.c
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								lib/asyn-ares.c
									
									
									
									
									
								
							| @@ -315,6 +315,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, | |||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct ResolverResults *res = (struct ResolverResults *) |   struct ResolverResults *res = (struct ResolverResults *) | ||||||
|     conn->async.os_specific; |     conn->async.os_specific; | ||||||
|  |   CURLcode rc = CURLE_OK; | ||||||
|  |  | ||||||
|   *dns = NULL; |   *dns = NULL; | ||||||
|  |  | ||||||
| @@ -325,19 +326,19 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, | |||||||
|     /* temp_ai ownership is moved to the connection, so we need not free-up |     /* temp_ai ownership is moved to the connection, so we need not free-up | ||||||
|        them */ |        them */ | ||||||
|     res->temp_ai = NULL; |     res->temp_ai = NULL; | ||||||
|     destroy_async_data(&conn->async); |  | ||||||
|     if(!conn->async.dns) { |     if(!conn->async.dns) { | ||||||
|       failf(data, "Could not resolve %s: %s (%s)", |       failf(data, "Could not resolve: %s (%s)", | ||||||
|             conn->bits.proxy?"proxy":"host", |             conn->async.hostname, ares_strerror(conn->async.status)); | ||||||
|             conn->host.dispname, |       rc = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: | ||||||
|             ares_strerror(conn->async.status)); |  | ||||||
|       return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: |  | ||||||
|         CURLE_COULDNT_RESOLVE_HOST; |         CURLE_COULDNT_RESOLVE_HOST; | ||||||
|     } |     } | ||||||
|     *dns = conn->async.dns; |     else | ||||||
|  |       *dns = conn->async.dns; | ||||||
|  |  | ||||||
|  |     destroy_async_data(&conn->async); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return rc; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -415,37 +416,12 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, | |||||||
|   if(entry) |   if(entry) | ||||||
|     *entry = conn->async.dns; |     *entry = conn->async.dns; | ||||||
|  |  | ||||||
|   if(!conn->async.dns) { |   if(rc) | ||||||
|     /* a name was not resolved */ |  | ||||||
|     if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) { |  | ||||||
|       if(conn->bits.proxy) { |  | ||||||
|         failf(data, "Resolving proxy timed out: %s", conn->proxy.dispname); |  | ||||||
|         rc = CURLE_COULDNT_RESOLVE_PROXY; |  | ||||||
|       } |  | ||||||
|       else { |  | ||||||
|         failf(data, "Resolving host timed out: %s", conn->host.dispname); |  | ||||||
|         rc = CURLE_COULDNT_RESOLVE_HOST; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     else if(conn->async.done) { |  | ||||||
|       if(conn->bits.proxy) { |  | ||||||
|         failf(data, "Could not resolve proxy: %s (%s)", conn->proxy.dispname, |  | ||||||
|               ares_strerror(conn->async.status)); |  | ||||||
|         rc = CURLE_COULDNT_RESOLVE_PROXY; |  | ||||||
|       } |  | ||||||
|       else { |  | ||||||
|         failf(data, "Could not resolve host: %s (%s)", conn->host.dispname, |  | ||||||
|               ares_strerror(conn->async.status)); |  | ||||||
|         rc = CURLE_COULDNT_RESOLVE_HOST; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|       rc = CURLE_OPERATION_TIMEDOUT; |  | ||||||
|  |  | ||||||
|     /* close the connection, since we can't return failure here without |     /* close the connection, since we can't return failure here without | ||||||
|        cleaning up this connection properly */ |        cleaning up this connection properly. | ||||||
|  |        TODO: remove this action from here, it is not a name resolver decision. | ||||||
|  |     */ | ||||||
|     conn->bits.close = TRUE; |     conn->bits.close = TRUE; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return rc; |   return rc; | ||||||
| } | } | ||||||
| @@ -614,8 +590,19 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data, | |||||||
|                               char *servers) |                               char *servers) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_NOT_BUILT_IN; |   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) | #if (ARES_VERSION >= 0x010704) | ||||||
|   int ares_result = ares_set_servers_csv(data->state.resolver, servers); |   ares_result = ares_set_servers_csv(data->state.resolver, servers); | ||||||
|   switch(ares_result) { |   switch(ares_result) { | ||||||
|   case ARES_SUCCESS: |   case ARES_SUCCESS: | ||||||
|     result = CURLE_OK; |     result = CURLE_OK; | ||||||
| @@ -632,8 +619,76 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data, | |||||||
|   } |   } | ||||||
| #else /* too old c-ares version! */ | #else /* too old c-ares version! */ | ||||||
|   (void)data; |   (void)data; | ||||||
|   (void)servers; |   (void)(ares_result); | ||||||
| #endif | #endif | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data, | ||||||
|  |                                 const char *local_ip6) | ||||||
|  | { | ||||||
|  | #if (ARES_VERSION >= 0x010704) | ||||||
|  |   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 */ | #endif /* CURLRES_ARES */ | ||||||
|   | |||||||
| @@ -265,7 +265,7 @@ static int getaddrinfo_complete(struct connectdata *conn) | |||||||
| static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) | static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) | ||||||
| { | { | ||||||
|   struct thread_sync_data *tsd = (struct thread_sync_data*)arg; |   struct thread_sync_data *tsd = (struct thread_sync_data*)arg; | ||||||
|   char   service [NI_MAXSERV]; |   char service[12]; | ||||||
|   int rc; |   int rc; | ||||||
|  |  | ||||||
|   snprintf(service, sizeof(service), "%d", tsd->port); |   snprintf(service, sizeof(service), "%d", tsd->port); | ||||||
| @@ -559,7 +559,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, | |||||||
|   struct in_addr in; |   struct in_addr in; | ||||||
|   Curl_addrinfo *res; |   Curl_addrinfo *res; | ||||||
|   int error; |   int error; | ||||||
|   char sbuf[NI_MAXSERV]; |   char sbuf[12]; | ||||||
|   int pf = PF_INET; |   int pf = PF_INET; | ||||||
| #ifdef CURLRES_IPV6 | #ifdef CURLRES_IPV6 | ||||||
|   struct in6_addr in6; |   struct in6_addr in6; | ||||||
| @@ -635,4 +635,28 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data, | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | CURLcode Curl_set_dns_interface(struct SessionHandle *data, | ||||||
|  |                                 const char *interf) | ||||||
|  | { | ||||||
|  |   (void)data; | ||||||
|  |   (void)interf; | ||||||
|  |   return CURLE_NOT_BUILT_IN; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data, | ||||||
|  |                                 const char *local_ip4) | ||||||
|  | { | ||||||
|  |   (void)data; | ||||||
|  |   (void)local_ip4; | ||||||
|  |   return CURLE_NOT_BUILT_IN; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 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 */ | #endif /* CURLRES_THREADED */ | ||||||
|   | |||||||
| @@ -164,7 +164,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) | |||||||
|   case CURL_SSLVERSION_TLSv1: |   case CURL_SSLVERSION_TLSv1: | ||||||
|     break; |     break; | ||||||
|   default: |   default: | ||||||
|     failf(data, "axTLS only supports TLSv1"); |     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; |     return CURLE_SSL_CONNECT_ERROR; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										109
									
								
								lib/base64.c
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								lib/base64.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -40,29 +40,45 @@ | |||||||
| static const char table64[]= | static const char table64[]= | ||||||
|   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||||||
|  |  | ||||||
| static void decodeQuantum(unsigned char *dest, const char *src) | static size_t decodeQuantum(unsigned char *dest, const char *src) | ||||||
| { | { | ||||||
|  |   size_t padding = 0; | ||||||
|   const char *s, *p; |   const char *s, *p; | ||||||
|   unsigned long i, v, x = 0; |   unsigned long i, v, x = 0; | ||||||
|  |  | ||||||
|   for(i = 0, s = src; i < 4; i++, s++) { |   for(i = 0, s = src; i < 4; i++, s++) { | ||||||
|     v = 0; |     v = 0; | ||||||
|     p = table64; |  | ||||||
|     while(*p && (*p != *s)) { |     if(*s == '=') { | ||||||
|       v++; |  | ||||||
|       p++; |  | ||||||
|     } |  | ||||||
|     if(*p == *s) |  | ||||||
|       x = (x << 6) + v; |  | ||||||
|     else if(*s == '=') |  | ||||||
|       x = (x << 6); |       x = (x << 6); | ||||||
|  |       padding++; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       p = table64; | ||||||
|  |  | ||||||
|  |       while(*p && (*p != *s)) { | ||||||
|  |         v++; | ||||||
|  |         p++; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if(*p == *s) | ||||||
|  |         x = (x << 6) + v; | ||||||
|  |       else | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   dest[2] = curlx_ultouc(x & 0xFFUL); |   if(padding < 1) | ||||||
|  |     dest[2] = curlx_ultouc(x & 0xFFUL); | ||||||
|  |  | ||||||
|   x >>= 8; |   x >>= 8; | ||||||
|   dest[1] = curlx_ultouc(x & 0xFFUL); |   if(padding < 2) | ||||||
|  |     dest[1] = curlx_ultouc(x & 0xFFUL); | ||||||
|  |  | ||||||
|   x >>= 8; |   x >>= 8; | ||||||
|   dest[0] = curlx_ultouc(x & 0xFFUL); |   dest[0] = curlx_ultouc(x & 0xFFUL); | ||||||
|  |  | ||||||
|  |   return 3 - padding; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -82,58 +98,71 @@ static void decodeQuantum(unsigned char *dest, const char *src) | |||||||
| CURLcode Curl_base64_decode(const char *src, | CURLcode Curl_base64_decode(const char *src, | ||||||
|                             unsigned char **outptr, size_t *outlen) |                             unsigned char **outptr, size_t *outlen) | ||||||
| { | { | ||||||
|  |   size_t srclen = 0; | ||||||
|   size_t length = 0; |   size_t length = 0; | ||||||
|   size_t equalsTerm = 0; |   size_t padding = 0; | ||||||
|   size_t i; |   size_t i; | ||||||
|  |   size_t result; | ||||||
|   size_t numQuantums; |   size_t numQuantums; | ||||||
|   unsigned char lastQuantum[3]; |  | ||||||
|   size_t rawlen = 0; |   size_t rawlen = 0; | ||||||
|  |   unsigned char *pos; | ||||||
|   unsigned char *newstr; |   unsigned char *newstr; | ||||||
|  |  | ||||||
|   *outptr = NULL; |   *outptr = NULL; | ||||||
|   *outlen = 0; |   *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]) |   while((src[length] != '=') && src[length]) | ||||||
|     length++; |     length++; | ||||||
|  |  | ||||||
|   /* A maximum of two = padding characters is allowed */ |   /* A maximum of two = padding characters is allowed */ | ||||||
|   if(src[length] == '=') { |   if(src[length] == '=') { | ||||||
|     equalsTerm++; |     padding++; | ||||||
|     if(src[length+equalsTerm] == '=') |     if(src[length + 1] == '=') | ||||||
|       equalsTerm++; |       padding++; | ||||||
|   } |   } | ||||||
|   numQuantums = (length + equalsTerm) / 4; |  | ||||||
|  |  | ||||||
|   /* Don't allocate a buffer if the decoded length is 0 */ |   /* Check the = padding characters weren't part way through the input */ | ||||||
|   if(numQuantums == 0) |   if(length + padding != srclen) | ||||||
|     return CURLE_OK; |     return CURLE_BAD_CONTENT_ENCODING; | ||||||
|  |  | ||||||
|   rawlen = (numQuantums * 3) - equalsTerm; |   /* Calculate the number of quantums */ | ||||||
|  |   numQuantums = srclen / 4; | ||||||
|  |  | ||||||
|   /* The buffer must be large enough to make room for the last quantum |   /* Calculate the size of the decoded string */ | ||||||
|   (which may be partially thrown out) and the zero terminator. */ |   rawlen = (numQuantums * 3) - padding; | ||||||
|   newstr = malloc(rawlen+4); |  | ||||||
|  |   /* Allocate our buffer including room for a zero terminator */ | ||||||
|  |   newstr = malloc(rawlen + 1); | ||||||
|   if(!newstr) |   if(!newstr) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   *outptr = newstr; |   pos = newstr; | ||||||
|  |  | ||||||
|   /* Decode all but the last quantum (which may not decode to a |   /* Decode the quantums */ | ||||||
|   multiple of 3 bytes) */ |   for(i = 0; i < numQuantums; i++) { | ||||||
|   for(i = 0; i < numQuantums - 1; i++) { |     result = decodeQuantum(pos, src); | ||||||
|     decodeQuantum(newstr, src); |     if(!result) { | ||||||
|     newstr += 3; src += 4; |       Curl_safefree(newstr); | ||||||
|  |  | ||||||
|  |       return CURLE_BAD_CONTENT_ENCODING; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pos += result; | ||||||
|  |     src += 4; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* This final decode may actually read slightly past the end of the buffer |   /* Zero terminate */ | ||||||
|   if the input string is missing pad bytes.  This will almost always be |   *pos = '\0'; | ||||||
|   harmless. */ |  | ||||||
|   decodeQuantum(lastQuantum, src); |  | ||||||
|   for(i = 0; i < 3 - equalsTerm; i++) |  | ||||||
|     newstr[i] = lastQuantum[i]; |  | ||||||
|  |  | ||||||
|   newstr[i] = '\0'; /* zero terminate */ |   /* Return the decoded data */ | ||||||
|  |   *outptr = newstr; | ||||||
|   *outlen = rawlen; /* return size of decoded data */ |   *outlen = rawlen; | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -277,21 +277,27 @@ | |||||||
| /* Define if you have the <stdlib.h> header file. */ | /* Define if you have the <stdlib.h> header file. */ | ||||||
| #define HAVE_STDLIB_H | #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. */ | /* Define if you have the `strcasecmp' function. */ | ||||||
| #undef HAVE_STRCASECMP | #undef HAVE_STRCASECMP | ||||||
|  |  | ||||||
| /* Define if you have the `strcmpi' function. */ | /* Define if you have the `strcmpi' function. */ | ||||||
| #undef HAVE_STRCMPI | #define HAVE_STRCMPI | ||||||
|  |  | ||||||
|  | /* Define if you have the `stricmp' function. */ | ||||||
|  | #define HAVE_STRICMP | ||||||
|  |  | ||||||
| /* Define if you have the `strdup' function. */ | /* Define if you have the `strdup' function. */ | ||||||
| #undef HAVE_STRDUP | #define HAVE_STRDUP | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Define if you have the `strftime' function. */ | /* Define if you have the `strftime' function. */ | ||||||
| #define HAVE_STRFTIME | #define HAVE_STRFTIME | ||||||
|  |  | ||||||
| /* Define if you have the `stricmp' function. */ |  | ||||||
| #undef HAVE_STRICMP |  | ||||||
|  |  | ||||||
| /* Define if you have the <strings.h> header file. */ | /* Define if you have the <strings.h> header file. */ | ||||||
| #define HAVE_STRINGS_H | #define HAVE_STRINGS_H | ||||||
|  |  | ||||||
| @@ -523,7 +529,10 @@ | |||||||
| #define SEND_TYPE_RETV int | #define SEND_TYPE_RETV int | ||||||
|  |  | ||||||
| /* Define to use the QsoSSL package. */ | /* Define to use the QsoSSL package. */ | ||||||
| #define USE_QSOSSL | #undef USE_QSOSSL | ||||||
|  |  | ||||||
|  | /* Define to use the GSKit package. */ | ||||||
|  | #define USE_GSKIT | ||||||
|  |  | ||||||
| /* Use the system keyring as the default CA bundle. */ | /* Use the system keyring as the default CA bundle. */ | ||||||
| #define CURL_CA_BUNDLE  "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB" | #define CURL_CA_BUNDLE  "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB" | ||||||
|   | |||||||
| @@ -390,21 +390,6 @@ | |||||||
| #  define SIZEOF_SIZE_T 4 | #  define SIZEOF_SIZE_T 4 | ||||||
| #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 |  | ||||||
|  |  | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| /*               BSD-style lwIP TCP/IP stack SPECIFIC               */ | /*               BSD-style lwIP TCP/IP stack SPECIFIC               */ | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| @@ -572,6 +557,25 @@ | |||||||
| #  endif | #  endif | ||||||
| #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                        */ | /*                        LARGE FILE SUPPORT                        */ | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
|   | |||||||
							
								
								
									
										368
									
								
								lib/connect.c
									
									
									
									
									
								
							
							
						
						
									
										368
									
								
								lib/connect.c
									
									
									
									
									
								
							| @@ -164,8 +164,7 @@ tcpkeepalive(struct SessionHandle *data, | |||||||
| static CURLcode | static CURLcode | ||||||
| singleipconnect(struct connectdata *conn, | singleipconnect(struct connectdata *conn, | ||||||
|                 const Curl_addrinfo *ai, /* start connecting to this */ |                 const Curl_addrinfo *ai, /* start connecting to this */ | ||||||
|                 curl_socket_t *sock, |                 curl_socket_t *sock); | ||||||
|                 bool *connected); |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Curl_timeleft() returns the amount of milliseconds left allowed for the |  * Curl_timeleft() returns the amount of milliseconds left allowed for the | ||||||
| @@ -233,45 +232,6 @@ long Curl_timeleft(struct SessionHandle *data, | |||||||
|   return timeout_ms; |   return timeout_ms; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * checkconnect() checks for a TCP connect on the given socket. |  | ||||||
|  * It returns: |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| enum chkconn_t { |  | ||||||
|   CHKCONN_SELECT_ERROR = -1, |  | ||||||
|   CHKCONN_CONNECTED    = 0, |  | ||||||
|   CHKCONN_IDLE         = 1, |  | ||||||
|   CHKCONN_FDSET_ERROR  = 2 |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static enum chkconn_t |  | ||||||
| checkconnect(curl_socket_t sockfd) |  | ||||||
| { |  | ||||||
|   int rc; |  | ||||||
| #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(sockfd, NULL); |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 0); |  | ||||||
|  |  | ||||||
|   if(-1 == rc) |  | ||||||
|     /* error, no connect here, try next */ |  | ||||||
|     return CHKCONN_SELECT_ERROR; |  | ||||||
|  |  | ||||||
|   else if(rc & CURL_CSELECT_ERR) |  | ||||||
|     /* error condition caught */ |  | ||||||
|     return CHKCONN_FDSET_ERROR; |  | ||||||
|  |  | ||||||
|   else if(rc) |  | ||||||
|     return CHKCONN_CONNECTED; |  | ||||||
|  |  | ||||||
|   return CHKCONN_IDLE; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static CURLcode bindlocal(struct connectdata *conn, | static CURLcode bindlocal(struct connectdata *conn, | ||||||
|                           curl_socket_t sockfd, int af) |                           curl_socket_t sockfd, int af) | ||||||
| { | { | ||||||
| @@ -573,42 +533,53 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) | |||||||
|    more address exists or error */ |    more address exists or error */ | ||||||
| static CURLcode trynextip(struct connectdata *conn, | static CURLcode trynextip(struct connectdata *conn, | ||||||
|                           int sockindex, |                           int sockindex, | ||||||
|                           bool *connected) |                           int tempindex) | ||||||
| { | { | ||||||
|   curl_socket_t sockfd; |   CURLcode rc = CURLE_COULDNT_CONNECT; | ||||||
|   Curl_addrinfo *ai; |  | ||||||
|  |  | ||||||
|   /* First clean up after the failed socket. |   /* First clean up after the failed socket. | ||||||
|      Don't close it yet to ensure that the next IP's socket gets a different |      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 |      file descriptor, which can prevent bugs when the curl_multi_socket_action | ||||||
|      interface is used with certain select() replacements such as kqueue. */ |      interface is used with certain select() replacements such as kqueue. */ | ||||||
|   curl_socket_t fd_to_close = conn->sock[sockindex]; |   curl_socket_t fd_to_close = conn->tempsock[tempindex]; | ||||||
|   conn->sock[sockindex] = CURL_SOCKET_BAD; |   conn->tempsock[tempindex] = CURL_SOCKET_BAD; | ||||||
|   *connected = FALSE; |  | ||||||
|  |  | ||||||
|   if(sockindex != FIRSTSOCKET) { |   if(sockindex == FIRSTSOCKET) { | ||||||
|     Curl_closesocket(conn, fd_to_close); |     Curl_addrinfo *ai; | ||||||
|     return CURLE_COULDNT_CONNECT; /* no next */ |     int family; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* try the next address */ |     if(conn->tempaddr[tempindex]) { | ||||||
|   ai = conn->ip_addr->ai_next; |       /* find next address in the same protocol family */ | ||||||
|  |       family = conn->tempaddr[tempindex]->ai_family; | ||||||
|   while(ai) { |       ai = conn->tempaddr[tempindex]->ai_next; | ||||||
|     CURLcode res = singleipconnect(conn, ai, &sockfd, connected); |     } | ||||||
|     if(res) |     else { | ||||||
|       return res; |       /* happy eyeballs - try the other protocol family */ | ||||||
|     if(sockfd != CURL_SOCKET_BAD) { |       int firstfamily = conn->tempaddr[0]->ai_family; | ||||||
|       /* store the new socket descriptor */ |       family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET; | ||||||
|       conn->sock[sockindex] = sockfd; |       ai = conn->tempaddr[0]->ai_next; | ||||||
|       conn->ip_addr = ai; |     } | ||||||
|       Curl_closesocket(conn, fd_to_close); |  | ||||||
|       return CURLE_OK; |     while(ai) { | ||||||
|  |       while(ai && ai->ai_family != family) | ||||||
|  |         ai = ai->ai_next; | ||||||
|  |  | ||||||
|  |       if(ai) { | ||||||
|  |         rc = singleipconnect(conn, ai, &conn->tempsock[tempindex]); | ||||||
|  |         conn->tempaddr[tempindex] = ai; | ||||||
|  |         if(rc == CURLE_COULDNT_CONNECT) { | ||||||
|  |           ai = ai->ai_next; | ||||||
|  |           continue; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|     } |     } | ||||||
|     ai = ai->ai_next; |  | ||||||
|   } |   } | ||||||
|   Curl_closesocket(conn, fd_to_close); |  | ||||||
|   return CURLE_COULDNT_CONNECT; |   if(fd_to_close != CURL_SOCKET_BAD) | ||||||
|  |     Curl_closesocket(conn, fd_to_close); | ||||||
|  |  | ||||||
|  |   return rc; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Copies connection info into the session handle to make it available | /* Copies connection info into the session handle to make it available | ||||||
| @@ -707,6 +678,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) | |||||||
|             error, Curl_strerror(conn, error)); |             error, Curl_strerror(conn, error)); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |     memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); | ||||||
|  |  | ||||||
|     if(!getaddressinfo((struct sockaddr*)&ssloc, |     if(!getaddressinfo((struct sockaddr*)&ssloc, | ||||||
|                        conn->local_ip, &conn->local_port)) { |                        conn->local_ip, &conn->local_port)) { | ||||||
| @@ -732,11 +704,11 @@ CURLcode Curl_is_connected(struct connectdata *conn, | |||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   CURLcode code = CURLE_OK; |   CURLcode code = CURLE_OK; | ||||||
|   curl_socket_t sockfd = conn->sock[sockindex]; |   long allow; | ||||||
|   long allow = DEFAULT_CONNECT_TIMEOUT; |  | ||||||
|   int error = 0; |   int error = 0; | ||||||
|   struct timeval now; |   struct timeval now; | ||||||
|   enum chkconn_t chk; |   int result; | ||||||
|  |   int i; | ||||||
|  |  | ||||||
|   DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); |   DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); | ||||||
|  |  | ||||||
| @@ -759,69 +731,104 @@ CURLcode Curl_is_connected(struct connectdata *conn, | |||||||
|     return CURLE_OPERATION_TIMEDOUT; |     return CURLE_OPERATION_TIMEDOUT; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* check socket for connect */ |   for(i=0; i<2; i++) { | ||||||
|   chk = checkconnect(sockfd); |     if(conn->tempsock[i] == CURL_SOCKET_BAD) | ||||||
|   if(CHKCONN_IDLE == chk) { |       continue; | ||||||
|     if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) { |  | ||||||
|       infof(data, "After %ldms connect time, move on!\n", | #ifdef mpeix | ||||||
|             conn->timeoutms_per_addr); |     /* Call this function once now, and ignore the results. We do this to | ||||||
|       goto next; |        "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 */ | ||||||
|  |     result = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0); | ||||||
|  |  | ||||||
|  |     if(result == 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(result == CURL_CSELECT_OUT) { | ||||||
|  |       if(verifyconnect(conn->tempsock[i], &error)) { | ||||||
|  |         /* we are connected with TCP, awesome! */ | ||||||
|  |         int other = i ^ 1; | ||||||
|  |  | ||||||
|     /* not an error, but also no connection yet */ |         /* use this socket from now on */ | ||||||
|     return code; |         conn->sock[sockindex] = conn->tempsock[i]; | ||||||
|   } |         conn->ip_addr = conn->tempaddr[i]; | ||||||
|  |         conn->tempsock[i] = CURL_SOCKET_BAD; | ||||||
|  |  | ||||||
|   if(CHKCONN_CONNECTED == chk) { |         /* close the other socket, if open */ | ||||||
|     if(verifyconnect(sockfd, &error)) { |         if(conn->tempsock[other] != CURL_SOCKET_BAD) { | ||||||
|       /* we are connected with TCP, awesome! */ |           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 */ |         /* see if we need to do any proxy magic first once we connected */ | ||||||
|       code = Curl_connected_proxy(conn); |         code = Curl_connected_proxy(conn, sockindex); | ||||||
|       if(code) |         if(code) | ||||||
|         return code; |           return code; | ||||||
|  |  | ||||||
|       conn->bits.tcpconnect[sockindex] = TRUE; |         conn->bits.tcpconnect[sockindex] = TRUE; | ||||||
|  |  | ||||||
|       *connected = TRUE; |         *connected = TRUE; | ||||||
|       if(sockindex == FIRSTSOCKET) |         if(sockindex == FIRSTSOCKET) | ||||||
|         Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ |           Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ | ||||||
|       Curl_verboseconnect(conn); |         Curl_updateconninfo(conn, conn->sock[sockindex]); | ||||||
|       Curl_updateconninfo(conn, sockfd); |         Curl_verboseconnect(conn); | ||||||
|  |  | ||||||
|       return CURLE_OK; |         return CURLE_OK; | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |         infof(data, "Connection failed\n"); | ||||||
|     } |     } | ||||||
|     /* nope, not connected for real */ |     else if(result & CURL_CSELECT_ERR) | ||||||
|   } |       (void)verifyconnect(conn->tempsock[i], &error); | ||||||
|   else { |  | ||||||
|     /* nope, not connected  */ |     /* | ||||||
|     if(CHKCONN_FDSET_ERROR == chk) { |      * The connection failed here, we should attempt to connect to the "next | ||||||
|       (void)verifyconnect(sockfd, &error); |      * address" for the given host. But first remember the latest error. | ||||||
|       infof(data, "%s\n",Curl_strerror(conn, error)); |      */ | ||||||
|  |     if(error) { | ||||||
|  |       char ipaddress[MAX_IPADR_LEN]; | ||||||
|  |       data->state.os_errno = error; | ||||||
|  |       SET_SOCKERRNO(error); | ||||||
|  |       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; | ||||||
|  |  | ||||||
|  |       code = trynextip(conn, sockindex, i); | ||||||
|     } |     } | ||||||
|     else |  | ||||||
|       infof(data, "Connection failed\n"); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* |  | ||||||
|    * 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); |  | ||||||
|   } |  | ||||||
|   next: |  | ||||||
|  |  | ||||||
|   conn->timeoutms_per_addr = conn->ip_addr->ai_next == NULL ? |  | ||||||
|                              allow : allow / 2; |  | ||||||
|   code = trynextip(conn, sockindex, connected); |  | ||||||
|  |  | ||||||
|   if(code) { |   if(code) { | ||||||
|     error = SOCKERRNO; |     /* no more addresses to try */ | ||||||
|     data->state.os_errno = error; |  | ||||||
|     failf(data, "Failed connect to %s:%ld; %s", |     /* if the first address family runs out of addresses to try before | ||||||
|           conn->host.name, conn->port, Curl_strerror(conn, error)); |        the happy eyeball timeout, go ahead and try the next family now */ | ||||||
|  |     if(conn->tempaddr[1] == NULL) { | ||||||
|  |       int rc; | ||||||
|  |       rc = trynextip(conn, sockindex, 1); | ||||||
|  |       if(rc == CURLE_OK) | ||||||
|  |         return CURLE_OK; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     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 code; |   return code; | ||||||
| @@ -938,8 +945,7 @@ void Curl_sndbufset(curl_socket_t sockfd) | |||||||
| static CURLcode | static CURLcode | ||||||
| singleipconnect(struct connectdata *conn, | singleipconnect(struct connectdata *conn, | ||||||
|                 const Curl_addrinfo *ai, |                 const Curl_addrinfo *ai, | ||||||
|                 curl_socket_t *sockp, |                 curl_socket_t *sockp) | ||||||
|                 bool *connected) |  | ||||||
| { | { | ||||||
|   struct Curl_sockaddr_ex addr; |   struct Curl_sockaddr_ex addr; | ||||||
|   int rc; |   int rc; | ||||||
| @@ -948,9 +954,10 @@ singleipconnect(struct connectdata *conn, | |||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   curl_socket_t sockfd; |   curl_socket_t sockfd; | ||||||
|   CURLcode res = CURLE_OK; |   CURLcode res = CURLE_OK; | ||||||
|  |   char ipaddress[MAX_IPADR_LEN]; | ||||||
|  |   long port; | ||||||
|  |  | ||||||
|   *sockp = CURL_SOCKET_BAD; |   *sockp = CURL_SOCKET_BAD; | ||||||
|   *connected = FALSE; /* default is not connected */ |  | ||||||
|  |  | ||||||
|   res = Curl_socket(conn, ai, &addr, &sockfd); |   res = Curl_socket(conn, ai, &addr, &sockfd); | ||||||
|   if(res) |   if(res) | ||||||
| @@ -961,7 +968,7 @@ singleipconnect(struct connectdata *conn, | |||||||
|  |  | ||||||
|   /* store remote address and port used in this connection attempt */ |   /* store remote address and port used in this connection attempt */ | ||||||
|   if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, |   if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, | ||||||
|                      conn->primary_ip, &conn->primary_port)) { |                      ipaddress, &port)) { | ||||||
|     /* malformed address or bug in inet_ntop, try next address */ |     /* malformed address or bug in inet_ntop, try next address */ | ||||||
|     error = ERRNO; |     error = ERRNO; | ||||||
|     failf(data, "sa_addr inet_ntop() failed with errno %d: %s", |     failf(data, "sa_addr inet_ntop() failed with errno %d: %s", | ||||||
| @@ -969,10 +976,7 @@ singleipconnect(struct connectdata *conn, | |||||||
|     Curl_closesocket(conn, sockfd); |     Curl_closesocket(conn, sockfd); | ||||||
|     return CURLE_OK; |     return CURLE_OK; | ||||||
|   } |   } | ||||||
|   memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); |   infof(data, "  Trying %s...\n", ipaddress); | ||||||
|   infof(data, "  Trying %s...\n", conn->ip_addr_str); |  | ||||||
|  |  | ||||||
|   Curl_persistconninfo(conn); |  | ||||||
|  |  | ||||||
|   if(data->set.tcp_nodelay) |   if(data->set.tcp_nodelay) | ||||||
|     tcpnodelay(conn, sockfd); |     tcpnodelay(conn, sockfd); | ||||||
| @@ -1033,7 +1037,7 @@ singleipconnect(struct connectdata *conn, | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   if(-1 == rc) { |   if(-1 == rc) { | ||||||
|     switch (error) { |     switch(error) { | ||||||
|     case EINPROGRESS: |     case EINPROGRESS: | ||||||
|     case EWOULDBLOCK: |     case EWOULDBLOCK: | ||||||
| #if defined(EAGAIN) | #if defined(EAGAIN) | ||||||
| @@ -1045,25 +1049,25 @@ singleipconnect(struct connectdata *conn, | |||||||
|     case EAGAIN: |     case EAGAIN: | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|       *sockp = sockfd; |       res = CURLE_OK; | ||||||
|       return CURLE_OK; |       break; | ||||||
|  |  | ||||||
|     default: |     default: | ||||||
|       /* unknown error, fallthrough and try another address! */ |       /* unknown error, fallthrough and try another address! */ | ||||||
|       failf(data, "Failed to connect to %s: %s", |       infof(data, "Immediate connect fail for %s: %s\n", | ||||||
|             conn->ip_addr_str, Curl_strerror(conn,error)); |             ipaddress, Curl_strerror(conn,error)); | ||||||
|       data->state.os_errno = error; |       data->state.os_errno = error; | ||||||
|  |  | ||||||
|       /* connect failed */ |       /* connect failed */ | ||||||
|       Curl_closesocket(conn, sockfd); |       Curl_closesocket(conn, sockfd); | ||||||
|  |       res = CURLE_COULDNT_CONNECT; | ||||||
|       break; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   else |  | ||||||
|  |   if(!res) | ||||||
|     *sockp = sockfd; |     *sockp = sockfd; | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -1073,29 +1077,13 @@ singleipconnect(struct connectdata *conn, | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| CURLcode Curl_connecthost(struct connectdata *conn,  /* context */ | CURLcode Curl_connecthost(struct connectdata *conn,  /* context */ | ||||||
|                           const struct Curl_dns_entry *remotehost, |                           const struct Curl_dns_entry *remotehost) | ||||||
|                           curl_socket_t *sockconn,   /* the connected socket */ |  | ||||||
|                           Curl_addrinfo **addr,      /* the one we used */ |  | ||||||
|                           bool *connected)           /* really connected? */ |  | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   curl_socket_t sockfd = CURL_SOCKET_BAD; |  | ||||||
|   Curl_addrinfo *ai; |  | ||||||
|   Curl_addrinfo *curr_addr; |  | ||||||
|  |  | ||||||
|   struct timeval after; |  | ||||||
|   struct timeval before = Curl_tvnow(); |   struct timeval before = Curl_tvnow(); | ||||||
|  |   CURLcode res; | ||||||
|  |  | ||||||
|   /************************************************************* |   long timeout_ms = Curl_timeleft(data, &before, TRUE); | ||||||
|    * Figure out what maximum time we have left |  | ||||||
|    *************************************************************/ |  | ||||||
|   long timeout_ms; |  | ||||||
|  |  | ||||||
|   DEBUGASSERT(sockconn); |  | ||||||
|   *connected = FALSE; /* default to not connected */ |  | ||||||
|  |  | ||||||
|   /* get the timeout left */ |  | ||||||
|   timeout_ms = Curl_timeleft(data, &before, TRUE); |  | ||||||
|  |  | ||||||
|   if(timeout_ms < 0) { |   if(timeout_ms < 0) { | ||||||
|     /* a precaution, no need to continue if time already is up */ |     /* a precaution, no need to continue if time already is up */ | ||||||
| @@ -1104,57 +1092,27 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   conn->num_addr = Curl_num_addresses(remotehost->addr); |   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 + (MULTI_TIMEOUT_INACCURACY/1000)); | ||||||
|  |  | ||||||
|   ai = remotehost->addr; |   /* Max time for the next connection attempt */ | ||||||
|  |   conn->timeoutms_per_addr = | ||||||
|  |     conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2; | ||||||
|  |  | ||||||
|   /* Below is the loop that attempts to connect to all IP-addresses we |   /* start connecting to first IP */ | ||||||
|    * know for the given host. One by one until one IP succeeds. |   res = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0])); | ||||||
|    */ |   while(res != CURLE_OK && | ||||||
|  |         conn->tempaddr[0] && | ||||||
|  |         conn->tempaddr[0]->ai_next && | ||||||
|  |         conn->tempsock[0] == CURL_SOCKET_BAD) | ||||||
|  |     res = trynextip(conn, FIRSTSOCKET, 0); | ||||||
|  |  | ||||||
|   /* |   if(conn->tempsock[0] == CURL_SOCKET_BAD) | ||||||
|    * Connecting with a Curl_addrinfo chain |     return res; | ||||||
|    */ |  | ||||||
|   for(curr_addr = ai; curr_addr; curr_addr = curr_addr->ai_next) { |  | ||||||
|     CURLcode res; |  | ||||||
|  |  | ||||||
|     /* Max time for the next address */ |  | ||||||
|     conn->timeoutms_per_addr = curr_addr->ai_next == NULL ? |  | ||||||
|                                timeout_ms : timeout_ms / 2; |  | ||||||
|  |  | ||||||
|     /* start connecting to the IP curr_addr points to */ |  | ||||||
|     res = singleipconnect(conn, curr_addr, |  | ||||||
|                           &sockfd, connected); |  | ||||||
|     if(res) |  | ||||||
|       return res; |  | ||||||
|  |  | ||||||
|     if(sockfd != CURL_SOCKET_BAD) |  | ||||||
|       break; |  | ||||||
|  |  | ||||||
|     /* get a new timeout for next attempt */ |  | ||||||
|     after = Curl_tvnow(); |  | ||||||
|     timeout_ms -= Curl_tvdiff(after, before); |  | ||||||
|     if(timeout_ms < 0) { |  | ||||||
|       failf(data, "connect() timed out!"); |  | ||||||
|       return CURLE_OPERATION_TIMEDOUT; |  | ||||||
|     } |  | ||||||
|     before = after; |  | ||||||
|   }  /* end of connect-to-each-address loop */ |  | ||||||
|  |  | ||||||
|   *sockconn = sockfd;    /* the socket descriptor we've connected */ |  | ||||||
|  |  | ||||||
|   if(sockfd == CURL_SOCKET_BAD) { |  | ||||||
|     /* no good connect was made */ |  | ||||||
|     failf(data, "couldn't connect to %s at %s:%d", |  | ||||||
|           conn->bits.proxy?"proxy":"host", |  | ||||||
|           conn->bits.proxy?conn->proxy.name:conn->host.name, conn->port); |  | ||||||
|     return CURLE_COULDNT_CONNECT; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* leave the socket in non-blocking mode */ |  | ||||||
|  |  | ||||||
|   /* store the address we use */ |  | ||||||
|   if(addr) |  | ||||||
|     *addr = curr_addr; |  | ||||||
|  |  | ||||||
|   data->info.numconnects++; /* to track the number of connections made */ |   data->info.numconnects++; /* to track the number of connections made */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -31,11 +31,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, | |||||||
|                            bool *connected); |                            bool *connected); | ||||||
|  |  | ||||||
| CURLcode Curl_connecthost(struct connectdata *conn, | CURLcode Curl_connecthost(struct connectdata *conn, | ||||||
|                           const struct Curl_dns_entry *host, /* connect to |                           const struct Curl_dns_entry *host); | ||||||
|                                                                 this */ |  | ||||||
|                           curl_socket_t *sockconn, /* not set if error */ |  | ||||||
|                           Curl_addrinfo **addr, /* the one we used */ |  | ||||||
|                           bool *connected); /* truly connected? */ |  | ||||||
|  |  | ||||||
| /* generic function that returns how much time there's left to run, according | /* generic function that returns how much time there's left to run, according | ||||||
|    to the timeouts set */ |    to the timeouts set */ | ||||||
| @@ -44,6 +40,8 @@ long Curl_timeleft(struct SessionHandle *data, | |||||||
|                    bool duringconnect); |                    bool duringconnect); | ||||||
|  |  | ||||||
| #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ | #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 |  * Used to extract socket and connectdata struct for the most recent | ||||||
|   | |||||||
							
								
								
									
										42
									
								
								lib/cookie.c
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								lib/cookie.c
									
									
									
									
									
								
							| @@ -89,6 +89,7 @@ Example set of cookies: | |||||||
| #include "strequal.h" | #include "strequal.h" | ||||||
| #include "strtok.h" | #include "strtok.h" | ||||||
| #include "sendf.h" | #include "sendf.h" | ||||||
|  | #include "slist.h" | ||||||
| #include "curl_memory.h" | #include "curl_memory.h" | ||||||
| #include "share.h" | #include "share.h" | ||||||
| #include "strtoofft.h" | #include "strtoofft.h" | ||||||
| @@ -289,6 +290,34 @@ static void strstore(char **str, const char *newstr) | |||||||
|   *str = strdup(newstr); |   *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; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| /**************************************************************************** | /**************************************************************************** | ||||||
|  * |  * | ||||||
| @@ -699,6 +728,9 @@ Curl_cookie_add(struct SessionHandle *data, | |||||||
|      superceeds an already existing cookie, which it may if the previous have |      superceeds an already existing cookie, which it may if the previous have | ||||||
|      the same domain and path as this */ |      the same domain and path as this */ | ||||||
|  |  | ||||||
|  |   /* at first, remove expired cookies */ | ||||||
|  |   remove_expired(c); | ||||||
|  |  | ||||||
|   clist = c->cookies; |   clist = c->cookies; | ||||||
|   replace_old = FALSE; |   replace_old = FALSE; | ||||||
|   while(clist) { |   while(clist) { | ||||||
| @@ -930,6 +962,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, | |||||||
|   if(!c || !c->cookies) |   if(!c || !c->cookies) | ||||||
|     return NULL; /* no cookie struct or no cookies in the struct */ |     return NULL; /* no cookie struct or no cookies in the struct */ | ||||||
|  |  | ||||||
|  |   /* at first, remove expired cookies */ | ||||||
|  |   remove_expired(c); | ||||||
|  |  | ||||||
|   co = c->cookies; |   co = c->cookies; | ||||||
|  |  | ||||||
|   while(co) { |   while(co) { | ||||||
| @@ -1172,6 +1207,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) | |||||||
|        destination file */ |        destination file */ | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|  |   /* at first, remove expired cookies */ | ||||||
|  |   remove_expired(c); | ||||||
|  |  | ||||||
|   if(strequal("-", dumphere)) { |   if(strequal("-", dumphere)) { | ||||||
|     /* use stdout */ |     /* use stdout */ | ||||||
|     out = stdout; |     out = stdout; | ||||||
| @@ -1232,9 +1270,9 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data) | |||||||
|       curl_slist_free_all(list); |       curl_slist_free_all(list); | ||||||
|       return NULL; |       return NULL; | ||||||
|     } |     } | ||||||
|     beg = curl_slist_append(list, line); |     beg = Curl_slist_append_nodup(list, line); | ||||||
|     free(line); |  | ||||||
|     if(!beg) { |     if(!beg) { | ||||||
|  |       free(line); | ||||||
|       curl_slist_free_all(list); |       curl_slist_free_all(list); | ||||||
|       return NULL; |       return NULL; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -38,9 +38,58 @@ | |||||||
| #include <Security/SecureTransport.h> | #include <Security/SecureTransport.h> | ||||||
| #include <CoreFoundation/CoreFoundation.h> | #include <CoreFoundation/CoreFoundation.h> | ||||||
| #include <CommonCrypto/CommonDigest.h> | #include <CommonCrypto/CommonDigest.h> | ||||||
|  |  | ||||||
|  | /* 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 (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 | ||||||
|  |  | ||||||
|  | #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 <sys/sysctl.h> | #include <sys/sysctl.h> | ||||||
| #endif | #endif /* CURL_BUILD_MAC */ | ||||||
|  |  | ||||||
| #include "urldata.h" | #include "urldata.h" | ||||||
| #include "sendf.h" | #include "sendf.h" | ||||||
| @@ -61,16 +110,6 @@ | |||||||
| #define ioErr -36 | #define ioErr -36 | ||||||
| #define paramErr -50 | #define paramErr -50 | ||||||
|  |  | ||||||
| /* In Mountain Lion and iOS 5, Apple made some changes to the API. They |  | ||||||
|    added TLS 1.1 and 1.2 support, and deprecated and replaced some |  | ||||||
|    functions. You need to build against the Mountain Lion or iOS 5 SDK |  | ||||||
|    or later to get TLS 1.1 or 1.2 support working in cURL. We'll weak-link |  | ||||||
|    to the newer functions and use them if present in the user's OS. |  | ||||||
|  |  | ||||||
|    Builders: If you want TLS 1.1 and 1.2 but still want to retain support |  | ||||||
|    for older cats, don't forget to set the MACOSX_DEPLOYMENT_TARGET |  | ||||||
|    environmental variable prior to building cURL. */ |  | ||||||
|  |  | ||||||
| /* The following two functions were ripped from Apple sample code, | /* The following two functions were ripped from Apple sample code, | ||||||
|  * with some modifications: */ |  * with some modifications: */ | ||||||
| static OSStatus SocketRead(SSLConnectionRef connection, | static OSStatus SocketRead(SSLConnectionRef connection, | ||||||
| @@ -361,7 +400,7 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { | |||||||
|     case TLS_DH_anon_WITH_AES_256_CBC_SHA: |     case TLS_DH_anon_WITH_AES_256_CBC_SHA: | ||||||
|       return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; |       return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; | ||||||
|       break; |       break; | ||||||
| #if defined(__MAC_10_6) || defined(__IPHONE_5_0) | #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS | ||||||
|     /* TLS 1.0 with ECDSA (RFC 4492) */ |     /* TLS 1.0 with ECDSA (RFC 4492) */ | ||||||
|     case TLS_ECDH_ECDSA_WITH_NULL_SHA: |     case TLS_ECDH_ECDSA_WITH_NULL_SHA: | ||||||
|       return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; |       return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; | ||||||
| @@ -438,8 +477,8 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { | |||||||
|     case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: |     case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: | ||||||
|       return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; |       return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; | ||||||
|       break; |       break; | ||||||
| #endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */ | #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ | ||||||
| #if defined(__MAC_10_8) || defined(__IPHONE_5_0) | #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS | ||||||
|     /* TLS 1.2 (RFC 5246) */ |     /* TLS 1.2 (RFC 5246) */ | ||||||
|     case TLS_RSA_WITH_NULL_MD5: |     case TLS_RSA_WITH_NULL_MD5: | ||||||
|       return "TLS_RSA_WITH_NULL_MD5"; |       return "TLS_RSA_WITH_NULL_MD5"; | ||||||
| @@ -624,12 +663,116 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { | |||||||
|     case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: |     case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: | ||||||
|       return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; |       return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; | ||||||
|       break; |       break; | ||||||
| #endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */ | #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"; |   return "TLS_NULL_WITH_NULL_NULL"; | ||||||
| } | } | ||||||
|  |  | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_BUILD_MAC | ||||||
| CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) | CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) | ||||||
| { | { | ||||||
|   int mib[2]; |   int mib[2]; | ||||||
| @@ -658,7 +801,7 @@ CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) | |||||||
|   *minor = atoi(os_version_minor); |   *minor = atoi(os_version_minor); | ||||||
|   free(os_version); |   free(os_version); | ||||||
| } | } | ||||||
| #endif | #endif /* CURL_BUILD_MAC */ | ||||||
|  |  | ||||||
| /* Apple provides a myriad of ways of getting information about a certificate | /* 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 |    into a string. Some aren't available under iOS or newer cats. So here's | ||||||
| @@ -668,37 +811,36 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert) | |||||||
| { | { | ||||||
|   CFStringRef server_cert_summary = CFSTR("(null)"); |   CFStringRef server_cert_summary = CFSTR("(null)"); | ||||||
|  |  | ||||||
| #if (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) | #if CURL_BUILD_IOS | ||||||
|   /* iOS: There's only one way to do this. */ |   /* iOS: There's only one way to do this. */ | ||||||
|   server_cert_summary = SecCertificateCopySubjectSummary(cert); |   server_cert_summary = SecCertificateCopySubjectSummary(cert); | ||||||
| #else | #else | ||||||
| #if defined(__MAC_10_7) | #if CURL_BUILD_MAC_10_7 | ||||||
|   /* Lion & later: Get the long description if we can. */ |   /* Lion & later: Get the long description if we can. */ | ||||||
|   if(SecCertificateCopyLongDescription != NULL) |   if(SecCertificateCopyLongDescription != NULL) | ||||||
|     server_cert_summary = |     server_cert_summary = | ||||||
|       SecCertificateCopyLongDescription(NULL, cert, NULL); |       SecCertificateCopyLongDescription(NULL, cert, NULL); | ||||||
|   else |   else | ||||||
| #endif /* defined(__MAC_10_7) */ | #endif /* CURL_BUILD_MAC_10_7 */ | ||||||
| #if defined(__MAC_10_6) | #if CURL_BUILD_MAC_10_6 | ||||||
|   /* Snow Leopard: Get the certificate summary. */ |   /* Snow Leopard: Get the certificate summary. */ | ||||||
|   if(SecCertificateCopySubjectSummary != NULL) |   if(SecCertificateCopySubjectSummary != NULL) | ||||||
|     server_cert_summary = SecCertificateCopySubjectSummary(cert); |     server_cert_summary = SecCertificateCopySubjectSummary(cert); | ||||||
|   else |   else | ||||||
| #endif /* defined(__MAC_10_6) */ | #endif /* CURL_BUILD_MAC_10_6 */ | ||||||
|   /* Leopard is as far back as we go... */ |   /* Leopard is as far back as we go... */ | ||||||
|   (void)SecCertificateCopyCommonName(cert, &server_cert_summary); |   (void)SecCertificateCopyCommonName(cert, &server_cert_summary); | ||||||
| #endif /* (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) */ | #endif /* CURL_BUILD_IOS */ | ||||||
|   return server_cert_summary; |   return server_cert_summary; | ||||||
| } | } | ||||||
|  |  | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #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, | static OSStatus CopyIdentityWithLabelOldSchool(char *label, | ||||||
|                                                SecIdentityRef *out_c_a_k) |                                                SecIdentityRef *out_c_a_k) | ||||||
| { | { | ||||||
|   OSStatus status = errSecItemNotFound; |   OSStatus status = errSecItemNotFound; | ||||||
| /* The SecKeychainSearch API was deprecated in Lion, and using it will raise |  | ||||||
|    deprecation warnings, so let's not compile this unless it's necessary: */ |  | ||||||
| #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 |  | ||||||
|   SecKeychainAttributeList attr_list; |   SecKeychainAttributeList attr_list; | ||||||
|   SecKeychainAttribute attr; |   SecKeychainAttribute attr; | ||||||
|   SecKeychainSearchRef search = NULL; |   SecKeychainSearchRef search = NULL; | ||||||
| @@ -730,22 +872,20 @@ static OSStatus CopyIdentityWithLabelOldSchool(char *label, | |||||||
|  |  | ||||||
|   if(search) |   if(search) | ||||||
|     CFRelease(search); |     CFRelease(search); | ||||||
| #else |  | ||||||
| #pragma unused(label, out_c_a_k) |  | ||||||
| #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 */ |  | ||||||
|   return status; |   return status; | ||||||
| } | } | ||||||
| #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ | #endif /* CURL_SUPPORT_MAC_10_6 */ | ||||||
|  |  | ||||||
| static OSStatus CopyIdentityWithLabel(char *label, | static OSStatus CopyIdentityWithLabel(char *label, | ||||||
|                                       SecIdentityRef *out_cert_and_key) |                                       SecIdentityRef *out_cert_and_key) | ||||||
| { | { | ||||||
|   OSStatus status = errSecItemNotFound; |   OSStatus status = errSecItemNotFound; | ||||||
|  |  | ||||||
| #if defined(__MAC_10_6) || defined(__IPHONE_2_0) | #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS | ||||||
|   /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. If it |   /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. | ||||||
|      exists, let's use that to find the certificate. */ |      kSecClassIdentity was introduced in Lion. If both exist, let's use them | ||||||
|   if(SecItemCopyMatching != NULL) { |      to find the certificate. */ | ||||||
|  |   if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { | ||||||
|     CFTypeRef keys[4]; |     CFTypeRef keys[4]; | ||||||
|     CFTypeRef values[4]; |     CFTypeRef values[4]; | ||||||
|     CFDictionaryRef query_dict; |     CFDictionaryRef query_dict; | ||||||
| @@ -774,18 +914,83 @@ static OSStatus CopyIdentityWithLabel(char *label, | |||||||
|     CFRelease(query_dict); |     CFRelease(query_dict); | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_SUPPORT_MAC_10_6 | ||||||
|     /* On Leopard, fall back to SecKeychainSearch. */ |     /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */ | ||||||
|     status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key); |     status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key); | ||||||
| #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ | #endif /* CURL_SUPPORT_MAC_10_7 */ | ||||||
|   } |   } | ||||||
| #elif (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #elif CURL_SUPPORT_MAC_10_6 | ||||||
|   /* For developers building on Leopard, we have no choice but to fall back. */ |   /* For developers building on older cats, we have no choice but to fall back | ||||||
|  |      to SecKeychainSearch. */ | ||||||
|   status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key); |   status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key); | ||||||
| #endif /* defined(__MAC_10_6) || defined(__IPHONE_2_0) */ | #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ | ||||||
|   return status; |   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) { | ||||||
|  |       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; | ||||||
|  |       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, | static CURLcode darwinssl_connect_step1(struct connectdata *conn, | ||||||
|                                         int sockindex) |                                         int sockindex) | ||||||
| { | { | ||||||
| @@ -796,19 +1001,19 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|   struct in6_addr addr; |   struct in6_addr addr; | ||||||
| #else | #else | ||||||
|   struct in_addr addr; |   struct in_addr addr; | ||||||
| #endif | #endif /* ENABLE_IPV6 */ | ||||||
|   size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; |   size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; | ||||||
|   SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; |   SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; | ||||||
|   char *ssl_sessionid; |   char *ssl_sessionid; | ||||||
|   size_t ssl_sessionid_len; |   size_t ssl_sessionid_len; | ||||||
|   OSStatus err = noErr; |   OSStatus err = noErr; | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_BUILD_MAC | ||||||
|   int darwinver_maj = 0, darwinver_min = 0; |   int darwinver_maj = 0, darwinver_min = 0; | ||||||
|  |  | ||||||
|   GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); |   GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); | ||||||
| #endif | #endif /* CURL_BUILD_MAC */ | ||||||
|  |  | ||||||
| #if defined(__MAC_10_8) || defined(__IPHONE_5_0) | #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS | ||||||
|   if(SSLCreateContext != NULL) {  /* use the newer API if avaialble */ |   if(SSLCreateContext != NULL) {  /* use the newer API if avaialble */ | ||||||
|     if(connssl->ssl_ctx) |     if(connssl->ssl_ctx) | ||||||
|       CFRelease(connssl->ssl_ctx); |       CFRelease(connssl->ssl_ctx); | ||||||
| @@ -820,7 +1025,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|   /* The old ST API does not exist under iOS, so don't compile it: */ |   /* The old ST API does not exist under iOS, so don't compile it: */ | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_SUPPORT_MAC_10_8 | ||||||
|     if(connssl->ssl_ctx) |     if(connssl->ssl_ctx) | ||||||
|       (void)SSLDisposeContext(connssl->ssl_ctx); |       (void)SSLDisposeContext(connssl->ssl_ctx); | ||||||
|     err = SSLNewContext(false, &(connssl->ssl_ctx)); |     err = SSLNewContext(false, &(connssl->ssl_ctx)); | ||||||
| @@ -828,7 +1033,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|       failf(data, "SSL: couldn't create a context: OSStatus %d", err); |       failf(data, "SSL: couldn't create a context: OSStatus %d", err); | ||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
|     } |     } | ||||||
| #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ | #endif /* CURL_SUPPORT_MAC_10_8 */ | ||||||
|   } |   } | ||||||
| #else | #else | ||||||
|   if(connssl->ssl_ctx) |   if(connssl->ssl_ctx) | ||||||
| @@ -838,11 +1043,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|     failf(data, "SSL: couldn't create a context: OSStatus %d", err); |     failf(data, "SSL: couldn't create a context: OSStatus %d", err); | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|   } |   } | ||||||
| #endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */ | #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ | ||||||
|   connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */ |   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 */ |   /* check to see if we've been told to use an explicit SSL/TLS version */ | ||||||
| #if defined(__MAC_10_8) || defined(__IPHONE_5_0) | #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS | ||||||
|   if(SSLSetProtocolVersionMax != NULL) { |   if(SSLSetProtocolVersionMax != NULL) { | ||||||
|     switch(data->set.ssl.version) { |     switch(data->set.ssl.version) { | ||||||
|       case CURL_SSLVERSION_DEFAULT: default: |       case CURL_SSLVERSION_DEFAULT: default: | ||||||
| @@ -853,17 +1058,33 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|         (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); |         (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); | ||||||
|         (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); |         (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); | ||||||
|         break; |         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: |       case CURL_SSLVERSION_SSLv3: | ||||||
|         (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); |         (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); | ||||||
|         (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); |         (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); | ||||||
|         break; |         break; | ||||||
|       case CURL_SSLVERSION_SSLv2: |       case CURL_SSLVERSION_SSLv2: | ||||||
|         (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); |         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); |         (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_SUPPORT_MAC_10_8 | ||||||
|     (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, |     (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, | ||||||
|                                        kSSLProtocolAll, |                                        kSSLProtocolAll, | ||||||
|                                        false); |                                        false); | ||||||
| @@ -893,18 +1114,37 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|                                            kTLSProtocol12, |                                            kTLSProtocol12, | ||||||
|                                            true); |                                            true); | ||||||
|         break; |         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: |       case CURL_SSLVERSION_SSLv3: | ||||||
|         (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, |         (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, | ||||||
|                                            kSSLProtocol3, |                                            kSSLProtocol3, | ||||||
|                                            true); |                                            true); | ||||||
|         break; |         break; | ||||||
|       case CURL_SSLVERSION_SSLv2: |       case CURL_SSLVERSION_SSLv2: | ||||||
|         (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, |         err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, | ||||||
|                                            kSSLProtocol2, |                                            kSSLProtocol2, | ||||||
|                                            true); |                                            true); | ||||||
|  |         if(err != noErr) { | ||||||
|  |           failf(data, "Your version of the OS does not support SSLv2"); | ||||||
|  |           return CURLE_SSL_CONNECT_ERROR; | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| #endif  /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ | #endif  /* CURL_SUPPORT_MAC_10_8 */ | ||||||
|   } |   } | ||||||
| #else | #else | ||||||
|   (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); |   (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); | ||||||
| @@ -919,14 +1159,25 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|                                          true); |                                          true); | ||||||
|       break; |       break; | ||||||
|     case CURL_SSLVERSION_TLSv1: |     case CURL_SSLVERSION_TLSv1: | ||||||
|  |     case CURL_SSLVERSION_TLSv1_0: | ||||||
|       (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, |       (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, | ||||||
|                                          kTLSProtocol1, |                                          kTLSProtocol1, | ||||||
|                                          true); |                                          true); | ||||||
|       break; |       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: |     case CURL_SSLVERSION_SSLv2: | ||||||
|       (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, |       err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, | ||||||
|                                          kSSLProtocol2, |                                          kSSLProtocol2, | ||||||
|                                          true); |                                          true); | ||||||
|  |       if(err != noErr) { | ||||||
|  |         failf(data, "Your version of the OS does not support SSLv2"); | ||||||
|  |         return CURLE_SSL_CONNECT_ERROR; | ||||||
|  |       } | ||||||
|       break; |       break; | ||||||
|     case CURL_SSLVERSION_SSLv3: |     case CURL_SSLVERSION_SSLv3: | ||||||
|       (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, |       (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, | ||||||
| @@ -934,18 +1185,36 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|                                          true); |                                          true); | ||||||
|       break; |       break; | ||||||
|   } |   } | ||||||
| #endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */ | #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ | ||||||
|  |  | ||||||
|   if(data->set.str[STRING_KEY]) { |   if(data->set.str[STRING_KEY]) { | ||||||
|     infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " |     infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " | ||||||
|                 "Transport. The private key must be in the Keychain."); |                 "Transport. The private key must be in the Keychain.\n"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(data->set.str[STRING_CERT]) { |   if(data->set.str[STRING_CERT]) { | ||||||
|     SecIdentityRef cert_and_key = NULL; |     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); | ||||||
|  |  | ||||||
|     /* User wants to authenticate with a client cert. Look for it: */ |  | ||||||
|     err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key); |  | ||||||
|     if(err == noErr) { |     if(err == noErr) { | ||||||
|       SecCertificateRef cert = NULL; |       SecCertificateRef cert = NULL; | ||||||
|       CFTypeRef certs_c[1]; |       CFTypeRef certs_c[1]; | ||||||
| @@ -982,8 +1251,29 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|       CFRelease(cert_and_key); |       CFRelease(cert_and_key); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       failf(data, "SSL: Can't find the certificate \"%s\" and its private key " |       switch(err) { | ||||||
|                   "in the Keychain.", data->set.str[STRING_CERT]); |         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 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; |       return CURLE_SSL_CERTPROBLEM; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -992,7 +1282,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|    * fail to connect if the verification fails, or if it should continue |    * 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 |    * anyway. In the latter case the result of the verification is checked with | ||||||
|    * SSL_get_verify_result() below. */ |    * SSL_get_verify_result() below. */ | ||||||
| #if defined(__MAC_10_6) || defined(__IPHONE_5_0) | #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS | ||||||
|   /* Snow Leopard introduced the SSLSetSessionOption() function, but due to |   /* Snow Leopard introduced the SSLSetSessionOption() function, but due to | ||||||
|      a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag |      a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag | ||||||
|      works, it doesn't work as expected under Snow Leopard or Lion. |      works, it doesn't work as expected under Snow Leopard or Lion. | ||||||
| @@ -1001,11 +1291,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|      (SecureTransport will always validate the certificate chain by |      (SecureTransport will always validate the certificate chain by | ||||||
|      default.) */ |      default.) */ | ||||||
|   /* (Note: Darwin 12.x.x is Mountain Lion.) */ |   /* (Note: Darwin 12.x.x is Mountain Lion.) */ | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_BUILD_MAC | ||||||
|   if(SSLSetSessionOption != NULL && darwinver_maj >= 12) { |   if(SSLSetSessionOption != NULL && darwinver_maj >= 12) { | ||||||
| #else | #else | ||||||
|   if(SSLSetSessionOption != NULL) { |   if(SSLSetSessionOption != NULL) { | ||||||
| #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ | #endif /* CURL_BUILD_MAC */ | ||||||
|     err = SSLSetSessionOption(connssl->ssl_ctx, |     err = SSLSetSessionOption(connssl->ssl_ctx, | ||||||
|                               kSSLSessionOptionBreakOnServerAuth, |                               kSSLSessionOptionBreakOnServerAuth, | ||||||
|                               data->set.ssl.verifypeer?false:true); |                               data->set.ssl.verifypeer?false:true); | ||||||
| @@ -1015,14 +1305,14 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_SUPPORT_MAC_10_8 | ||||||
|     err = SSLSetEnableCertVerify(connssl->ssl_ctx, |     err = SSLSetEnableCertVerify(connssl->ssl_ctx, | ||||||
|                                  data->set.ssl.verifypeer?true:false); |                                  data->set.ssl.verifypeer?true:false); | ||||||
|     if(err != noErr) { |     if(err != noErr) { | ||||||
|       failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); |       failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); | ||||||
|       return CURLE_SSL_CONNECT_ERROR; |       return CURLE_SSL_CONNECT_ERROR; | ||||||
|     } |     } | ||||||
| #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ | #endif /* CURL_SUPPORT_MAC_10_8 */ | ||||||
|   } |   } | ||||||
| #else | #else | ||||||
|   err = SSLSetEnableCertVerify(connssl->ssl_ctx, |   err = SSLSetEnableCertVerify(connssl->ssl_ctx, | ||||||
| @@ -1031,7 +1321,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|     failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); |     failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); | ||||||
|     return CURLE_SSL_CONNECT_ERROR; |     return CURLE_SSL_CONNECT_ERROR; | ||||||
|   } |   } | ||||||
| #endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */ | #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ | ||||||
|  |  | ||||||
|   /* If this is a domain name and not an IP address, then configure SNI. |   /* If this is a domain name and not an IP address, then configure SNI. | ||||||
|    * Also: the verifyhost setting influences SNI usage */ |    * Also: the verifyhost setting influences SNI usage */ | ||||||
| @@ -1044,7 +1334,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|     err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name, |     err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name, | ||||||
|                                strlen(conn->host.name)); |                                strlen(conn->host.name)); | ||||||
|     if(err != noErr) { |     if(err != noErr) { | ||||||
|       infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d", |       infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", | ||||||
|             err); |             err); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -1061,7 +1351,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|      SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers, |      SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers, | ||||||
|        &all_ciphers_count) == noErr) { |        &all_ciphers_count) == noErr) { | ||||||
|     for(i = 0UL ; i < all_ciphers_count ; i++) { |     for(i = 0UL ; i < all_ciphers_count ; i++) { | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_BUILD_MAC | ||||||
|      /* There's a known bug in early versions of Mountain Lion where ST's ECC |      /* 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. |         ciphers (cipher suite 0xC001 through 0xC032) simply do not work. | ||||||
|         Work around the problem here by disabling those ciphers if we are |         Work around the problem here by disabling those ciphers if we are | ||||||
| @@ -1070,17 +1360,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|          all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { |          all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { | ||||||
|            continue; |            continue; | ||||||
|       } |       } | ||||||
| #endif | #endif /* CURL_BUILD_MAC */ | ||||||
|       switch(all_ciphers[i]) { |       switch(all_ciphers[i]) { | ||||||
|         /* Disable NULL ciphersuites: */ |         /* Disable NULL ciphersuites: */ | ||||||
|         case SSL_NULL_WITH_NULL_NULL: |         case SSL_NULL_WITH_NULL_NULL: | ||||||
|         case SSL_RSA_WITH_NULL_MD5: |         case SSL_RSA_WITH_NULL_MD5: | ||||||
|         case SSL_RSA_WITH_NULL_SHA: |         case SSL_RSA_WITH_NULL_SHA: | ||||||
|  |         case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ | ||||||
|         case SSL_FORTEZZA_DMS_WITH_NULL_SHA: |         case SSL_FORTEZZA_DMS_WITH_NULL_SHA: | ||||||
|         case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ |         case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ | ||||||
|         case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ |         case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ | ||||||
|         case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ |         case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ | ||||||
|         case 0xC010: /* TLS_ECDHE_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: */ |         /* Disable anonymous ciphersuites: */ | ||||||
|         case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: |         case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: | ||||||
|         case SSL_DH_anon_WITH_RC4_128_MD5: |         case SSL_DH_anon_WITH_RC4_128_MD5: | ||||||
| @@ -1136,6 +1436,14 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|   Curl_safefree(all_ciphers); |   Curl_safefree(all_ciphers); | ||||||
|   Curl_safefree(allowed_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); | ||||||
|  | #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ | ||||||
|  |  | ||||||
|   /* Check if there's a cached ID we can/should use here! */ |   /* Check if there's a cached ID we can/should use here! */ | ||||||
|   if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, |   if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, | ||||||
|     &ssl_sessionid_len)) { |     &ssl_sessionid_len)) { | ||||||
| @@ -1303,7 +1611,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) | |||||||
|         infof(data, "TLS 1.0 connection using %s\n", |         infof(data, "TLS 1.0 connection using %s\n", | ||||||
|               TLSCipherNameForNumber(cipher)); |               TLSCipherNameForNumber(cipher)); | ||||||
|         break; |         break; | ||||||
| #if defined(__MAC_10_8) || defined(__IPHONE_5_0) | #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS | ||||||
|       case kTLSProtocol11: |       case kTLSProtocol11: | ||||||
|         infof(data, "TLS 1.1 connection using %s\n", |         infof(data, "TLS 1.1 connection using %s\n", | ||||||
|               TLSCipherNameForNumber(cipher)); |               TLSCipherNameForNumber(cipher)); | ||||||
| @@ -1330,20 +1638,22 @@ darwinssl_connect_step3(struct connectdata *conn, | |||||||
|   struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |   struct ssl_connect_data *connssl = &conn->ssl[sockindex]; | ||||||
|   CFStringRef server_cert_summary; |   CFStringRef server_cert_summary; | ||||||
|   char server_cert_summary_c[128]; |   char server_cert_summary_c[128]; | ||||||
|   CFArrayRef server_certs; |   CFArrayRef server_certs = NULL; | ||||||
|   SecCertificateRef server_cert; |   SecCertificateRef server_cert; | ||||||
|   OSStatus err; |   OSStatus err; | ||||||
|   CFIndex i, count; |   CFIndex i, count; | ||||||
|   SecTrustRef trust; |   SecTrustRef trust = NULL; | ||||||
|  |  | ||||||
|   /* There is no step 3! |   /* There is no step 3! | ||||||
|    * Well, okay, if verbose mode is on, let's print the details of the |    * Well, okay, if verbose mode is on, let's print the details of the | ||||||
|    * server certificates. */ |    * server certificates. */ | ||||||
| #if defined(__MAC_10_7) || defined(__IPHONE_5_0) | #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS | ||||||
| #if (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) | #if CURL_BUILD_IOS | ||||||
| #pragma unused(server_certs) | #pragma unused(server_certs) | ||||||
|   err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust); |   err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust); | ||||||
|   if(err == noErr) { |   /* 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); |     count = SecTrustGetCertificateCount(trust); | ||||||
|     for(i = 0L ; i < count ; i++) { |     for(i = 0L ; i < count ; i++) { | ||||||
|       server_cert = SecTrustGetCertificateAtIndex(trust, i); |       server_cert = SecTrustGetCertificateAtIndex(trust, i); | ||||||
| @@ -1369,7 +1679,9 @@ darwinssl_connect_step3(struct connectdata *conn, | |||||||
|   if(SecTrustEvaluateAsync != NULL) { |   if(SecTrustEvaluateAsync != NULL) { | ||||||
| #pragma unused(server_certs) | #pragma unused(server_certs) | ||||||
|     err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust); |     err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust); | ||||||
|     if(err == noErr) { |     /* 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); |       count = SecTrustGetCertificateCount(trust); | ||||||
|       for(i = 0L ; i < count ; i++) { |       for(i = 0L ; i < count ; i++) { | ||||||
|         server_cert = SecTrustGetCertificateAtIndex(trust, i); |         server_cert = SecTrustGetCertificateAtIndex(trust, i); | ||||||
| @@ -1387,8 +1699,10 @@ darwinssl_connect_step3(struct connectdata *conn, | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|  | #if CURL_SUPPORT_MAC_10_8 | ||||||
|     err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); |     err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); | ||||||
|     if(err == noErr) { |     /* Just in case SSLCopyPeerCertificates() returns null too... */ | ||||||
|  |     if(err == noErr && server_certs) { | ||||||
|       count = CFArrayGetCount(server_certs); |       count = CFArrayGetCount(server_certs); | ||||||
|       for(i = 0L ; i < count ; i++) { |       for(i = 0L ; i < count ; i++) { | ||||||
|         server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, |         server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, | ||||||
| @@ -1406,8 +1720,9 @@ darwinssl_connect_step3(struct connectdata *conn, | |||||||
|       } |       } | ||||||
|       CFRelease(server_certs); |       CFRelease(server_certs); | ||||||
|     } |     } | ||||||
|  | #endif /* CURL_SUPPORT_MAC_10_8 */ | ||||||
|   } |   } | ||||||
| #endif /* (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) */ | #endif /* CURL_BUILD_IOS */ | ||||||
| #else | #else | ||||||
| #pragma unused(trust) | #pragma unused(trust) | ||||||
|   err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); |   err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); | ||||||
| @@ -1427,7 +1742,7 @@ darwinssl_connect_step3(struct connectdata *conn, | |||||||
|     } |     } | ||||||
|     CFRelease(server_certs); |     CFRelease(server_certs); | ||||||
|   } |   } | ||||||
| #endif /* defined(__MAC_10_7) || defined(__IPHONE_5_0) */ | #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ | ||||||
|  |  | ||||||
|   connssl->connecting_state = ssl_connect_done; |   connssl->connecting_state = ssl_connect_done; | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| @@ -1579,16 +1894,16 @@ void Curl_darwinssl_close(struct connectdata *conn, int sockindex) | |||||||
|  |  | ||||||
|   if(connssl->ssl_ctx) { |   if(connssl->ssl_ctx) { | ||||||
|     (void)SSLClose(connssl->ssl_ctx); |     (void)SSLClose(connssl->ssl_ctx); | ||||||
| #if defined(__MAC_10_8) || defined(__IPHONE_5_0) | #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS | ||||||
|     if(SSLCreateContext != NULL) |     if(SSLCreateContext != NULL) | ||||||
|       CFRelease(connssl->ssl_ctx); |       CFRelease(connssl->ssl_ctx); | ||||||
| #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | #if CURL_SUPPORT_MAC_10_8 | ||||||
|     else |     else | ||||||
|       (void)SSLDisposeContext(connssl->ssl_ctx); |       (void)SSLDisposeContext(connssl->ssl_ctx); | ||||||
| #endif  /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ | #endif  /* CURL_SUPPORT_MAC_10_8 */ | ||||||
| #else | #else | ||||||
|     (void)SSLDisposeContext(connssl->ssl_ctx); |     (void)SSLDisposeContext(connssl->ssl_ctx); | ||||||
| #endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */ | #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ | ||||||
|     connssl->ssl_ctx = NULL; |     connssl->ssl_ctx = NULL; | ||||||
|   } |   } | ||||||
|   connssl->ssl_sockfd = 0; |   connssl->ssl_sockfd = 0; | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2012, Nick Zitzmann, <nickzman@gmail.com>. |  * Copyright (C) 2012 - 2013, Nick Zitzmann, <nickzman@gmail.com>. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -52,6 +52,10 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ | |||||||
|                            unsigned char *md5sum, /* output */ |                            unsigned char *md5sum, /* output */ | ||||||
|                            size_t md5len); |                            size_t md5len); | ||||||
|  |  | ||||||
|  | /* this backend provides these functions: */ | ||||||
|  | #define have_curlssl_random 1 | ||||||
|  | #define have_curlssl_md5sum 1 | ||||||
|  |  | ||||||
| /* API setup for SecureTransport */ | /* API setup for SecureTransport */ | ||||||
| #define curlssl_init() (1) | #define curlssl_init() (1) | ||||||
| #define curlssl_cleanup() Curl_nop_stmt | #define curlssl_cleanup() Curl_nop_stmt | ||||||
|   | |||||||
| @@ -87,6 +87,9 @@ extern curl_free_callback Curl_cfree; | |||||||
| extern curl_realloc_callback Curl_crealloc; | extern curl_realloc_callback Curl_crealloc; | ||||||
| extern curl_strdup_callback Curl_cstrdup; | extern curl_strdup_callback Curl_cstrdup; | ||||||
| extern curl_calloc_callback Curl_ccalloc; | extern curl_calloc_callback Curl_ccalloc; | ||||||
|  | #if defined(WIN32) && defined(UNICODE) | ||||||
|  | extern curl_wcsdup_callback Curl_cwcsdup; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifndef CURLDEBUG | #ifndef CURLDEBUG | ||||||
|  |  | ||||||
| @@ -110,6 +113,20 @@ extern curl_calloc_callback Curl_ccalloc; | |||||||
| #undef free | #undef free | ||||||
| #define free(ptr) Curl_cfree(ptr) | #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 */ | #endif /* CURLDEBUG */ | ||||||
|  |  | ||||||
| #else /* CURLX_NO_MEMORY_CALLBACKS */ | #else /* CURLX_NO_MEMORY_CALLBACKS */ | ||||||
|   | |||||||
| @@ -77,10 +77,6 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, | |||||||
|  |  | ||||||
|   ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; |   ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; | ||||||
|  |  | ||||||
|   /* skip initial whitespaces */ |  | ||||||
|   while(*header && ISSPACE(*header)) |  | ||||||
|     header++; |  | ||||||
|  |  | ||||||
|   if(checkprefix("NTLM", header)) { |   if(checkprefix("NTLM", header)) { | ||||||
|     header += strlen("NTLM"); |     header += strlen("NTLM"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -356,7 +356,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, | |||||||
|     conn->response_header = NULL; |     conn->response_header = NULL; | ||||||
|     break; |     break; | ||||||
|   case NTLMSTATE_TYPE2: |   case NTLMSTATE_TYPE2: | ||||||
|     input = aprintf("TT %s", conn->challenge_header); |     input = aprintf("TT %s\n", conn->challenge_header); | ||||||
|     if(!input) |     if(!input) | ||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
|     res = ntlm_wb_response(conn, input, ntlm->state); |     res = ntlm_wb_response(conn, input, ntlm->state); | ||||||
|   | |||||||
							
								
								
									
										312
									
								
								lib/curl_sasl.c
									
									
									
									
									
								
							
							
						
						
									
										312
									
								
								lib/curl_sasl.c
									
									
									
									
									
								
							| @@ -22,6 +22,8 @@ | |||||||
|  * RFC2831 DIGEST-MD5 authentication |  * RFC2831 DIGEST-MD5 authentication | ||||||
|  * RFC4422 Simple Authentication and Security Layer (SASL) |  * RFC4422 Simple Authentication and Security Layer (SASL) | ||||||
|  * RFC4616 PLAIN authentication |  * RFC4616 PLAIN authentication | ||||||
|  |  * RFC6749 OAuth 2.0 Authorization Framework | ||||||
|  |  * Draft   LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt> | ||||||
|  * |  * | ||||||
|  ***************************************************************************/ |  ***************************************************************************/ | ||||||
|  |  | ||||||
| @@ -32,13 +34,17 @@ | |||||||
|  |  | ||||||
| #include "curl_base64.h" | #include "curl_base64.h" | ||||||
| #include "curl_md5.h" | #include "curl_md5.h" | ||||||
| #include "curl_rand.h" | #include "sslgen.h" | ||||||
| #include "curl_hmac.h" | #include "curl_hmac.h" | ||||||
| #include "curl_ntlm_msgs.h" | #include "curl_ntlm_msgs.h" | ||||||
| #include "curl_sasl.h" | #include "curl_sasl.h" | ||||||
| #include "warnless.h" | #include "warnless.h" | ||||||
| #include "curl_memory.h" | #include "curl_memory.h" | ||||||
|  |  | ||||||
|  | #ifdef USE_NSS | ||||||
|  | #include "nssg.h" /* for Curl_nss_force_init() */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
|  |  | ||||||
| @@ -49,7 +55,7 @@ | |||||||
| /* Retrieves the value for a corresponding key from the challenge string | /* 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 |  * returns TRUE if the key could be found, FALSE if it does not exists | ||||||
|  */ |  */ | ||||||
| static bool sasl_digest_get_key_value(const unsigned char *chlg, | static bool sasl_digest_get_key_value(const char *chlg, | ||||||
|                                       const char *key, |                                       const char *key, | ||||||
|                                       char *value, |                                       char *value, | ||||||
|                                       size_t max_val_len, |                                       size_t max_val_len, | ||||||
| @@ -58,7 +64,7 @@ static bool sasl_digest_get_key_value(const unsigned char *chlg, | |||||||
|   char *find_pos; |   char *find_pos; | ||||||
|   size_t i; |   size_t i; | ||||||
|  |  | ||||||
|   find_pos = strstr((const char *) chlg, key); |   find_pos = strstr(chlg, key); | ||||||
|   if(!find_pos) |   if(!find_pos) | ||||||
|     return FALSE; |     return FALSE; | ||||||
|  |  | ||||||
| @@ -94,18 +100,18 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data, | |||||||
|                                         const char *passwdp, |                                         const char *passwdp, | ||||||
|                                         char **outptr, size_t *outlen) |                                         char **outptr, size_t *outlen) | ||||||
| { | { | ||||||
|   char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH]; |   CURLcode result; | ||||||
|  |   char *plainauth; | ||||||
|   size_t ulen; |   size_t ulen; | ||||||
|   size_t plen; |   size_t plen; | ||||||
|  |  | ||||||
|   ulen = strlen(userp); |   ulen = strlen(userp); | ||||||
|   plen = strlen(passwdp); |   plen = strlen(passwdp); | ||||||
|  |  | ||||||
|   if(2 * ulen + plen + 2 > sizeof(plainauth)) { |   plainauth = malloc(2 * ulen + plen + 2); | ||||||
|  |   if(!plainauth) { | ||||||
|     *outlen = 0; |     *outlen = 0; | ||||||
|     *outptr = NULL; |     *outptr = NULL; | ||||||
|  |  | ||||||
|     /* Plainauth too small */ |  | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -117,8 +123,10 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data, | |||||||
|   memcpy(plainauth + 2 * ulen + 2, passwdp, plen); |   memcpy(plainauth + 2 * ulen + 2, passwdp, plen); | ||||||
|  |  | ||||||
|   /* Base64 encode the reply */ |   /* Base64 encode the reply */ | ||||||
|   return Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr, |   result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr, | ||||||
|                             outlen); |                               outlen); | ||||||
|  |   Curl_safefree(plainauth); | ||||||
|  |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -160,7 +168,37 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data, | |||||||
| } | } | ||||||
|  |  | ||||||
| #ifndef CURL_DISABLE_CRYPTO_AUTH | #ifndef CURL_DISABLE_CRYPTO_AUTH | ||||||
| /* |  /* | ||||||
|  |  * Curl_sasl_decode_cram_md5_message() | ||||||
|  |  * | ||||||
|  |  * This is used to decode an already encoded CRAM-MD5 challenge message. | ||||||
|  |  * | ||||||
|  |  * Parameters: | ||||||
|  |  * | ||||||
|  |  * chlg64  [in]     - Pointer to the base64 encoded challenge message. | ||||||
|  |  * outptr  [in/out] - The address where a pointer to newly allocated memory | ||||||
|  |  *                    holding the result will be stored upon completion. | ||||||
|  |  * outlen  [out]    - The length of the output message. | ||||||
|  |  * | ||||||
|  |  * Returns CURLE_OK on success. | ||||||
|  |  */ | ||||||
|  | CURLcode Curl_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; | ||||||
|  |  } | ||||||
|  |  | ||||||
|  |  /* | ||||||
|  * Curl_sasl_create_cram_md5_message() |  * Curl_sasl_create_cram_md5_message() | ||||||
|  * |  * | ||||||
|  * This is used to generate an already encoded CRAM-MD5 response message ready |  * This is used to generate an already encoded CRAM-MD5 response message ready | ||||||
| @@ -169,7 +207,7 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data, | |||||||
|  * Parameters: |  * Parameters: | ||||||
|  * |  * | ||||||
|  * data    [in]     - The session handle. |  * data    [in]     - The session handle. | ||||||
|  * chlg64  [in]     - Pointer to the base64 encoded challenge buffer. |  * chlg    [in]     - The challenge. | ||||||
|  * userp   [in]     - The user name. |  * userp   [in]     - The user name. | ||||||
|  * passdwp [in]     - The user's password. |  * passdwp [in]     - The user's password. | ||||||
|  * outptr  [in/out] - The address where a pointer to newly allocated memory |  * outptr  [in/out] - The address where a pointer to newly allocated memory | ||||||
| @@ -179,55 +217,110 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data, | |||||||
|  * Returns CURLE_OK on success. |  * Returns CURLE_OK on success. | ||||||
|  */ |  */ | ||||||
| CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, | CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, | ||||||
|                                            const char *chlg64, |                                            const char *chlg, | ||||||
|                                            const char *userp, |                                            const char *userp, | ||||||
|                                            const char *passwdp, |                                            const char *passwdp, | ||||||
|                                            char **outptr, size_t *outlen) |                                            char **outptr, size_t *outlen) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   size_t chlg64len = strlen(chlg64); |  | ||||||
|   unsigned char *chlg = (unsigned char *) NULL; |  | ||||||
|   size_t chlglen = 0; |   size_t chlglen = 0; | ||||||
|   HMAC_context *ctxt; |   HMAC_context *ctxt; | ||||||
|   unsigned char digest[MD5_DIGEST_LEN]; |   unsigned char digest[MD5_DIGEST_LEN]; | ||||||
|   char response[MAX_CURL_USER_LENGTH + 2 * MD5_DIGEST_LEN + 1]; |   char *response; | ||||||
|  |  | ||||||
|   /* Decode the challenge if necessary */ |   if(chlg) | ||||||
|   if(chlg64len && *chlg64 != '=') { |     chlglen = strlen(chlg); | ||||||
|     result = Curl_base64_decode(chlg64, &chlg, &chlglen); |  | ||||||
|  |  | ||||||
|     if(result) |  | ||||||
|       return result; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* Compute the digest using the password as the key */ |   /* Compute the digest using the password as the key */ | ||||||
|   ctxt = Curl_HMAC_init(Curl_HMAC_MD5, |   ctxt = Curl_HMAC_init(Curl_HMAC_MD5, | ||||||
|                         (const unsigned char *) passwdp, |                         (const unsigned char *) passwdp, | ||||||
|                         curlx_uztoui(strlen(passwdp))); |                         curlx_uztoui(strlen(passwdp))); | ||||||
|  |   if(!ctxt) | ||||||
|   if(!ctxt) { |  | ||||||
|     Curl_safefree(chlg); |  | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* Update the digest with the given challenge */ |   /* Update the digest with the given challenge */ | ||||||
|   if(chlglen > 0) |   if(chlglen > 0) | ||||||
|     Curl_HMAC_update(ctxt, chlg, curlx_uztoui(chlglen)); |     Curl_HMAC_update(ctxt, (const unsigned char *) chlg, | ||||||
|  |                      curlx_uztoui(chlglen)); | ||||||
|   Curl_safefree(chlg); |  | ||||||
|  |  | ||||||
|   /* Finalise the digest */ |   /* Finalise the digest */ | ||||||
|   Curl_HMAC_final(ctxt, digest); |   Curl_HMAC_final(ctxt, digest); | ||||||
|  |  | ||||||
|   /* Prepare the response */ |   /* Generate the response */ | ||||||
|   snprintf(response, sizeof(response), |   response = aprintf( | ||||||
|       "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", |       "%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], |            userp, digest[0], digest[1], digest[2], digest[3], digest[4], | ||||||
|            digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], |            digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], | ||||||
|            digest[11], digest[12], digest[13], digest[14], digest[15]); |            digest[11], digest[12], digest[13], digest[14], digest[15]); | ||||||
|  |   if(!response) | ||||||
|  |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   /* Base64 encode the reply */ |   /* Base64 encode the response */ | ||||||
|   return Curl_base64_encode(data, response, 0, outptr, outlen); |   result = Curl_base64_encode(data, response, 0, outptr, outlen); | ||||||
|  |  | ||||||
|  |   Curl_safefree(response); | ||||||
|  |  | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Curl_sasl_decode_digest_md5_message() | ||||||
|  |  * | ||||||
|  |  * This is used to decode an already encoded DIGEST-MD5 challenge message. | ||||||
|  |  * | ||||||
|  |  * Parameters: | ||||||
|  |  * | ||||||
|  |  * chlg64  [in]     - Pointer to 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. | ||||||
|  |  * | ||||||
|  |  * Returns CURLE_OK on success. | ||||||
|  |  */ | ||||||
|  | CURLcode Curl_sasl_decode_digest_md5_message(const char *chlg64, | ||||||
|  |                                              char *nonce, size_t nlen, | ||||||
|  |                                              char *realm, size_t rlen, | ||||||
|  |                                              char *alg, size_t alen) | ||||||
|  | { | ||||||
|  |   CURLcode result = CURLE_OK; | ||||||
|  |   unsigned char *chlg = NULL; | ||||||
|  |   size_t chlglen = 0; | ||||||
|  |   size_t chlg64len = strlen(chlg64); | ||||||
|  |  | ||||||
|  |   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, '\"')) { | ||||||
|  |     Curl_safefree(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, ',')) { | ||||||
|  |     Curl_safefree(chlg); | ||||||
|  |     return CURLE_BAD_CONTENT_ENCODING; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(chlg); | ||||||
|  |  | ||||||
|  |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -239,10 +332,11 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, | |||||||
|  * Parameters: |  * Parameters: | ||||||
|  * |  * | ||||||
|  * data    [in]     - The session handle. |  * data    [in]     - The session handle. | ||||||
|  * chlg64  [in]     - Pointer to the base64 encoded challenge buffer. |  * nonce   [in]     - The nonce. | ||||||
|  |  * realm   [in]     - The realm. | ||||||
|  * userp   [in]     - The user name. |  * userp   [in]     - The user name. | ||||||
|  * passdwp [in]     - The user's password. |  * passdwp [in]     - The user's password. | ||||||
|  * service [in]     - The service type such as www, smtp or pop |  * service [in]     - The service type such as www, smtp, pop or imap. | ||||||
|  * outptr  [in/out] - The address where a pointer to newly allocated memory |  * outptr  [in/out] - The address where a pointer to newly allocated memory | ||||||
|  *                    holding the result will be stored upon completion. |  *                    holding the result will be stored upon completion. | ||||||
|  * outlen  [out]    - The length of the output message. |  * outlen  [out]    - The length of the output message. | ||||||
| @@ -250,71 +344,36 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, | |||||||
|  * Returns CURLE_OK on success. |  * Returns CURLE_OK on success. | ||||||
|  */ |  */ | ||||||
| CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, | CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, | ||||||
|                                              const char *chlg64, |                                              const char *nonce, | ||||||
|  |                                              const char *realm, | ||||||
|                                              const char *userp, |                                              const char *userp, | ||||||
|                                              const char *passwdp, |                                              const char *passwdp, | ||||||
|                                              const char *service, |                                              const char *service, | ||||||
|                                              char **outptr, size_t *outlen) |                                              char **outptr, size_t *outlen) | ||||||
| { | { | ||||||
|  | #ifndef DEBUGBUILD | ||||||
|   static const char table16[] = "0123456789abcdef"; |   static const char table16[] = "0123456789abcdef"; | ||||||
|  | #endif | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   unsigned char *chlg = (unsigned char *) NULL; |  | ||||||
|   size_t chlglen = 0; |  | ||||||
|   size_t i; |   size_t i; | ||||||
|   MD5_context *ctxt; |   MD5_context *ctxt; | ||||||
|  |   char *response = NULL; | ||||||
|   unsigned char digest[MD5_DIGEST_LEN]; |   unsigned char digest[MD5_DIGEST_LEN]; | ||||||
|   char HA1_hex[2 * MD5_DIGEST_LEN + 1]; |   char HA1_hex[2 * MD5_DIGEST_LEN + 1]; | ||||||
|   char HA2_hex[2 * MD5_DIGEST_LEN + 1]; |   char HA2_hex[2 * MD5_DIGEST_LEN + 1]; | ||||||
|   char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; |   char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; | ||||||
|  |  | ||||||
|   char nonce[64]; |  | ||||||
|   char realm[128]; |  | ||||||
|   char alg[64]; |  | ||||||
|   char nonceCount[] = "00000001"; |   char nonceCount[] = "00000001"; | ||||||
|   char cnonce[]     = "12345678"; /* will be changed */ |   char cnonce[]     = "12345678"; /* will be changed */ | ||||||
|   char method[]     = "AUTHENTICATE"; |   char method[]     = "AUTHENTICATE"; | ||||||
|   char qop[]        = "auth"; |   char qop[]        = "auth"; | ||||||
|   char uri[128]; |   char uri[128]; | ||||||
|   char response[512]; |  | ||||||
|  |  | ||||||
|   result = Curl_base64_decode(chlg64, &chlg, &chlglen); |  | ||||||
|  |  | ||||||
|   if(result) |  | ||||||
|     return result; |  | ||||||
|  |  | ||||||
|   if(!chlg) |  | ||||||
|     return CURLE_LOGIN_DENIED; |  | ||||||
|  |  | ||||||
|   /* Retrieve nonce string from the challenge */ |  | ||||||
|   if(!sasl_digest_get_key_value(chlg, "nonce=\"", nonce, |  | ||||||
|                                 sizeof(nonce), '\"')) { |  | ||||||
|     Curl_safefree(chlg); |  | ||||||
|     return CURLE_LOGIN_DENIED; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* Retrieve realm string from the challenge */ |  | ||||||
|   if(!sasl_digest_get_key_value(chlg, "realm=\"", realm, |  | ||||||
|                                 sizeof(realm), '\"')) { |  | ||||||
|     /* 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(chlg, "algorithm=", alg, sizeof(alg), ',')) { |  | ||||||
|     Curl_safefree(chlg); |  | ||||||
|     return CURLE_LOGIN_DENIED; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   Curl_safefree(chlg); |  | ||||||
|  |  | ||||||
|   /* We do not support other algorithms */ |  | ||||||
|   if(strcmp(alg, "md5-sess") != 0) |  | ||||||
|     return CURLE_LOGIN_DENIED; |  | ||||||
|  |  | ||||||
|  | #ifndef DEBUGBUILD | ||||||
|   /* Generate 64 bits of random data */ |   /* Generate 64 bits of random data */ | ||||||
|   for(i = 0; i < 8; i++) |   for(i = 0; i < 8; i++) | ||||||
|     cnonce[i] = table16[Curl_rand()%16]; |     cnonce[i] = table16[Curl_rand(data)%16]; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ |   /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ | ||||||
|   ctxt = Curl_MD5_init(Curl_DIGEST_MD5); |   ctxt = Curl_MD5_init(Curl_DIGEST_MD5); | ||||||
| @@ -393,14 +452,20 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, | |||||||
|   for(i = 0; i < MD5_DIGEST_LEN; i++) |   for(i = 0; i < MD5_DIGEST_LEN; i++) | ||||||
|     snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); |     snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); | ||||||
|  |  | ||||||
|   snprintf(response, sizeof(response), |   /* Generate the response */ | ||||||
|            "username=\"%s\",realm=\"%s\",nonce=\"%s\"," |   response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\"," | ||||||
|            "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s", |                      "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s", | ||||||
|            userp, realm, nonce, |                      userp, realm, nonce, | ||||||
|            cnonce, nonceCount, uri, resp_hash_hex); |                      cnonce, nonceCount, uri, resp_hash_hex); | ||||||
|  |   if(!response) | ||||||
|  |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   /* Base64 encode the reply */ |   /* Base64 encode the response */ | ||||||
|   return Curl_base64_encode(data, response, 0, outptr, outlen); |   result = Curl_base64_encode(data, response, 0, outptr, outlen); | ||||||
|  |  | ||||||
|  |   Curl_safefree(response); | ||||||
|  |  | ||||||
|  |   return result; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -430,8 +495,36 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp, | |||||||
|                                              struct ntlmdata *ntlm, |                                              struct ntlmdata *ntlm, | ||||||
|                                              char **outptr, size_t *outlen) |                                              char **outptr, size_t *outlen) | ||||||
| { | { | ||||||
|   return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr, |   return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr, outlen); | ||||||
|                                         outlen); | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Curl_sasl_decode_ntlm_type2_message() | ||||||
|  |  * | ||||||
|  |  * This is used to decode an already encoded NTLM type-2 message. | ||||||
|  |  * | ||||||
|  |  * Parameters: | ||||||
|  |  * | ||||||
|  |  * data     [in]     - Pointer to session handle. | ||||||
|  |  * type2msg [in]     - Pointer to 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) | ||||||
|  | { | ||||||
|  | #ifdef USE_NSS | ||||||
|  |   CURLcode result; | ||||||
|  |  | ||||||
|  |   /* make sure the crypto backend is initialized */ | ||||||
|  |   result = Curl_nss_force_init(data); | ||||||
|  |   if(result) | ||||||
|  |     return result; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   return Curl_ntlm_decode_type2_message(data, type2msg, ntlm); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -443,7 +536,6 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp, | |||||||
|  * Parameters: |  * Parameters: | ||||||
|  * |  * | ||||||
|  * data    [in]     - Pointer to session handle. |  * data    [in]     - Pointer to session handle. | ||||||
|  * header  [in]     - Pointer to the base64 encoded type-2 message buffer. |  | ||||||
|  * userp   [in]     - The user name in the format User or Domain\User. |  * userp   [in]     - The user name in the format User or Domain\User. | ||||||
|  * passdwp [in]     - The user's password. |  * passdwp [in]     - The user's password. | ||||||
|  * ntlm    [in/out] - The ntlm data struct being used and modified. |  * ntlm    [in/out] - The ntlm data struct being used and modified. | ||||||
| @@ -454,21 +546,53 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp, | |||||||
|  * Returns CURLE_OK on success. |  * Returns CURLE_OK on success. | ||||||
|  */ |  */ | ||||||
| CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, | CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, | ||||||
|                                              const char *header, |  | ||||||
|                                              const char *userp, |                                              const char *userp, | ||||||
|                                              const char *passwdp, |                                              const char *passwdp, | ||||||
|                                              struct ntlmdata *ntlm, |                                              struct ntlmdata *ntlm, | ||||||
|                                              char **outptr, size_t *outlen) |                                              char **outptr, size_t *outlen) | ||||||
| { | { | ||||||
|   CURLcode result = Curl_ntlm_decode_type2_message(data, header, ntlm); |   return Curl_ntlm_create_type3_message(data, userp, passwdp, ntlm, outptr, | ||||||
|  |                                         outlen); | ||||||
|  | } | ||||||
|  | #endif /* USE_NTLM */ | ||||||
|  |  | ||||||
|   if(!result) | /* | ||||||
|     result = Curl_ntlm_create_type3_message(data, userp, passwdp, ntlm, |  * Curl_sasl_create_xoauth2_message() | ||||||
|                                             outptr, outlen); |  * | ||||||
|  |  * 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. | ||||||
|  |  */ | ||||||
|  | CURLcode Curl_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); | ||||||
|  |  | ||||||
|  |   Curl_safefree(xoauth); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| #endif /* USE_NTLM */ |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Curl_sasl_cleanup() |  * Curl_sasl_cleanup() | ||||||
|   | |||||||
| @@ -24,18 +24,34 @@ | |||||||
|  |  | ||||||
| #include "pingpong.h" | #include "pingpong.h" | ||||||
|  |  | ||||||
| /* 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) |  | ||||||
|  |  | ||||||
| /* Authentication mechanism values */ | /* Authentication mechanism values */ | ||||||
| #define SASL_AUTH_NONE          0 | #define SASL_AUTH_NONE          0 | ||||||
| #define SASL_AUTH_ANY           ~0 | #define SASL_AUTH_ANY           ~0U | ||||||
|  |  | ||||||
|  | /* 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 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" | ||||||
|  |  | ||||||
|  | /* 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 generate a base64 encoded PLAIN authentication message */ | /* This is used to generate a base64 encoded PLAIN authentication message */ | ||||||
| CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data, | CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data, | ||||||
| @@ -50,16 +66,27 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data, | |||||||
|                                         size_t *outlen); |                                         size_t *outlen); | ||||||
|  |  | ||||||
| #ifndef CURL_DISABLE_CRYPTO_AUTH | #ifndef CURL_DISABLE_CRYPTO_AUTH | ||||||
|  | /* This is used to decode a base64 encoded CRAM-MD5 challange message */ | ||||||
|  | CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr, | ||||||
|  |                                            size_t *outlen); | ||||||
|  |  | ||||||
| /* This is used to generate a base64 encoded CRAM-MD5 response message */ | /* This is used to generate a base64 encoded CRAM-MD5 response message */ | ||||||
| CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, | CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, | ||||||
|                                            const char *chlg64, |                                            const char *chlg, | ||||||
|                                            const char *user, |                                            const char *user, | ||||||
|                                            const char *passwdp, |                                            const char *passwdp, | ||||||
|                                            char **outptr, size_t *outlen); |                                            char **outptr, size_t *outlen); | ||||||
|  |  | ||||||
|  | /* This is used to decode a base64 encoded DIGEST-MD5 challange message */ | ||||||
|  | CURLcode Curl_sasl_decode_digest_md5_message(const char *chlg64, | ||||||
|  |                                              char *nonce, size_t nlen, | ||||||
|  |                                              char *realm, size_t rlen, | ||||||
|  |                                              char *alg, size_t alen); | ||||||
|  |  | ||||||
| /* This is used to generate a base64 encoded DIGEST-MD5 response message */ | /* This is used to generate a base64 encoded DIGEST-MD5 response message */ | ||||||
| CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, | CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, | ||||||
|                                              const char *chlg64, |                                              const char *nonce, | ||||||
|  |                                              const char *realm, | ||||||
|                                              const char *user, |                                              const char *user, | ||||||
|                                              const char *passwdp, |                                              const char *passwdp, | ||||||
|                                              const char *service, |                                              const char *service, | ||||||
| @@ -74,10 +101,13 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp, | |||||||
|                                              char **outptr, |                                              char **outptr, | ||||||
|                                              size_t *outlen); |                                              size_t *outlen); | ||||||
|  |  | ||||||
| /* This is used to decode an incoming NTLM type-2 message and generate a | /* This is used to decode a base64 encoded NTLM type-2 message */ | ||||||
|    base64 encoded type-3 response */ | CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data, | ||||||
|  |                                              const char *type2msg, | ||||||
|  |                                              struct ntlmdata *ntlm); | ||||||
|  |  | ||||||
|  | /* This is used to generate a base64 encoded NTLM type-3 message */ | ||||||
| CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, | CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, | ||||||
|                                              const char *header, |  | ||||||
|                                              const char *userp, |                                              const char *userp, | ||||||
|                                              const char *passwdp, |                                              const char *passwdp, | ||||||
|                                              struct ntlmdata *ntlm, |                                              struct ntlmdata *ntlm, | ||||||
| @@ -85,6 +115,13 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, | |||||||
|  |  | ||||||
| #endif /* USE_NTLM */ | #endif /* USE_NTLM */ | ||||||
|  |  | ||||||
|  | /* This is used to generate a base64 encoded XOAUTH2 authentication message | ||||||
|  |    containing the user name and bearer token */ | ||||||
|  | CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data, | ||||||
|  |                                           const char *user, | ||||||
|  |                                           const char *bearer, | ||||||
|  |                                           char **outptr, size_t *outlen); | ||||||
|  |  | ||||||
| /* This is used to cleanup any libraries or curl modules used by the sasl | /* This is used to cleanup any libraries or curl modules used by the sasl | ||||||
|    functions */ |    functions */ | ||||||
| void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); | void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); | ||||||
|   | |||||||
| @@ -180,6 +180,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) | |||||||
|                                               SP_PROT_TLS1_1_CLIENT | |                                               SP_PROT_TLS1_1_CLIENT | | ||||||
|                                               SP_PROT_TLS1_2_CLIENT; |                                               SP_PROT_TLS1_2_CLIENT; | ||||||
|         break; |         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: |       case CURL_SSLVERSION_SSLv3: | ||||||
|         schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; |         schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; | ||||||
|         break; |         break; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| #ifndef HEADER_CURL_KRB4_H | #ifndef HEADER_CURL_SECURITY_H | ||||||
| #define HEADER_CURL_KRB4_H | #define HEADER_CURL_SECURITY_H | ||||||
| /***************************************************************************
 | /***************************************************************************
 | ||||||
|  *                                  _   _ ____  _ |  *                                  _   _ ____  _ | ||||||
|  *  Project                     ___| | | |  _ \| | |  *  Project                     ___| | | |  _ \| | | ||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -34,24 +34,18 @@ struct Curl_sec_client_mech { | |||||||
|   int (*decode)(void *, void*, int, int, struct connectdata *); |   int (*decode)(void *, void*, int, int, struct connectdata *); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #define AUTH_OK         0 | #define AUTH_OK         0 | ||||||
| #define AUTH_CONTINUE   1 | #define AUTH_CONTINUE   1 | ||||||
| #define AUTH_ERROR      2 | #define AUTH_ERROR      2 | ||||||
| 
 | 
 | ||||||
| #ifdef HAVE_KRB4 |  | ||||||
| extern struct Curl_sec_client_mech Curl_krb4_client_mech; |  | ||||||
| #endif |  | ||||||
| #ifdef HAVE_GSSAPI | #ifdef HAVE_GSSAPI | ||||||
| extern struct Curl_sec_client_mech Curl_krb5_client_mech; |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| CURLcode Curl_krb_kauth(struct connectdata *conn); |  | ||||||
| int Curl_sec_read_msg (struct connectdata *conn, char *, | int Curl_sec_read_msg (struct connectdata *conn, char *, | ||||||
|                        enum protection_level); |                        enum protection_level); | ||||||
| void Curl_sec_end (struct connectdata *); | void Curl_sec_end (struct connectdata *); | ||||||
| CURLcode Curl_sec_login (struct connectdata *); | CURLcode Curl_sec_login (struct connectdata *); | ||||||
| int Curl_sec_request_prot (struct connectdata *conn, const char *level); | int Curl_sec_request_prot (struct connectdata *conn, const char *level); | ||||||
| 
 | 
 | ||||||
| #endif /* HEADER_CURL_KRB4_H */ | extern struct Curl_sec_client_mech Curl_krb5_client_mech; | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|  | #endif /* HEADER_CURL_SECURITY_H */ | ||||||
| @@ -270,6 +270,9 @@ | |||||||
| #    endif | #    endif | ||||||
| #  endif | #  endif | ||||||
| #  include <tchar.h> | #  include <tchar.h> | ||||||
|  | #  ifdef UNICODE | ||||||
|  |      typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str); | ||||||
|  | #  endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -617,7 +620,7 @@ int netware_init(void); | |||||||
| #if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || \ | #if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || \ | ||||||
|     defined(USE_QSOSSL) || defined(USE_POLARSSL) || defined(USE_AXTLS) || \ |     defined(USE_QSOSSL) || defined(USE_POLARSSL) || defined(USE_AXTLS) || \ | ||||||
|     defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ |     defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ | ||||||
|     defined(USE_DARWINSSL) |     defined(USE_DARWINSSL) || defined(USE_GSKIT) | ||||||
| #define USE_SSL    /* SSL support has been enabled */ | #define USE_SSL    /* SSL support has been enabled */ | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -440,7 +440,7 @@ typedef int sig_atomic_t; | |||||||
|  * (or equivalent) on this platform to hide platform details to code using it. |  * (or equivalent) on this platform to hide platform details to code using it. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifdef WIN32 | #if defined(WIN32) && !defined(USE_LWIPSOCK) | ||||||
| #define ERRNO         ((int)GetLastError()) | #define ERRNO         ((int)GetLastError()) | ||||||
| #define SET_ERRNO(x)  (SetLastError((DWORD)(x))) | #define SET_ERRNO(x)  (SetLastError((DWORD)(x))) | ||||||
| #else | #else | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								lib/cyassl.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								lib/cyassl.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -98,8 +98,19 @@ cyassl_connect_step1(struct connectdata *conn, | |||||||
|     req_method = SSLv23_client_method(); |     req_method = SSLv23_client_method(); | ||||||
|     break; |     break; | ||||||
|   case CURL_SSLVERSION_TLSv1: |   case CURL_SSLVERSION_TLSv1: | ||||||
|  |     infof(data, "CyaSSL cannot be configured to use TLS 1.0-1.2, " | ||||||
|  |           "TLS 1.0 is used exclusively\n"); | ||||||
|     req_method = TLSv1_client_method(); |     req_method = TLSv1_client_method(); | ||||||
|     break; |     break; | ||||||
|  |   case CURL_SSLVERSION_TLSv1_0: | ||||||
|  |     req_method = TLSv1_client_method(); | ||||||
|  |     break; | ||||||
|  |   case CURL_SSLVERSION_TLSv1_1: | ||||||
|  |     req_method = TLSv1_1_client_method(); | ||||||
|  |     break; | ||||||
|  |   case CURL_SSLVERSION_TLSv1_2: | ||||||
|  |     req_method = TLSv1_2_client_method(); | ||||||
|  |     break; | ||||||
|   case CURL_SSLVERSION_SSLv3: |   case CURL_SSLVERSION_SSLv3: | ||||||
|     req_method = SSLv3_client_method(); |     req_method = SSLv3_client_method(); | ||||||
|     break; |     break; | ||||||
|   | |||||||
							
								
								
									
										170
									
								
								lib/dotdot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								lib/dotdot.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | |||||||
|  | /*************************************************************************** | ||||||
|  |  *                                  _   _ ____  _ | ||||||
|  |  *  Project                     ___| | | |  _ \| | | ||||||
|  |  *                             / __| | | | |_) | | | ||||||
|  |  *                            | (__| |_| |  _ <| |___ | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  |  * This software is licensed as described in the file COPYING, which | ||||||
|  |  * you should have received as part of this distribution. The terms | ||||||
|  |  * are also available at http://curl.haxx.se/docs/copyright.html. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the COPYING file. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "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 | ||||||
|  |  */ | ||||||
|  | char *Curl_dedotdotify(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; | ||||||
|  | } | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| #ifndef HEADER_CURL_RAND_H | #ifndef HEADER_CURL_DOTDOT_H | ||||||
| #define HEADER_CURL_RAND_H | #define HEADER_CURL_DOTDOT_H | ||||||
| /***************************************************************************
 | /***************************************************************************
 | ||||||
|  *                                  _   _ ____  _ |  *                                  _   _ ____  _ | ||||||
|  *  Project                     ___| | | |  _ \| | |  *  Project                     ___| | | |  _ \| | | ||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -21,9 +21,5 @@ | |||||||
|  * KIND, either express or implied. |  * KIND, either express or implied. | ||||||
|  * |  * | ||||||
|  ***************************************************************************/ |  ***************************************************************************/ | ||||||
| 
 | char *Curl_dedotdotify(char *input); | ||||||
| void Curl_srand(void); | #endif | ||||||
| 
 |  | ||||||
| unsigned int Curl_rand(void); |  | ||||||
| 
 |  | ||||||
| #endif /* HEADER_CURL_RAND_H */ |  | ||||||
							
								
								
									
										471
									
								
								lib/easy.c
									
									
									
									
									
								
							
							
						
						
									
										471
									
								
								lib/easy.c
									
									
									
									
									
								
							| @@ -69,11 +69,11 @@ | |||||||
| #include "connect.h" /* for Curl_getconnectinfo */ | #include "connect.h" /* for Curl_getconnectinfo */ | ||||||
| #include "slist.h" | #include "slist.h" | ||||||
| #include "amigaos.h" | #include "amigaos.h" | ||||||
| #include "curl_rand.h" |  | ||||||
| #include "non-ascii.h" | #include "non-ascii.h" | ||||||
| #include "warnless.h" | #include "warnless.h" | ||||||
| #include "conncache.h" | #include "conncache.h" | ||||||
| #include "multiif.h" | #include "multiif.h" | ||||||
|  | #include "sigpipe.h" | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
| @@ -198,6 +198,9 @@ curl_free_callback Curl_cfree = (curl_free_callback)free; | |||||||
| curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; | curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; | ||||||
| curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; | curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; | ||||||
| curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; | 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 | #else | ||||||
| /* | /* | ||||||
|  * Symbian OS doesn't support initialization to code in writeable static data. |  * Symbian OS doesn't support initialization to code in writeable static data. | ||||||
| @@ -229,6 +232,9 @@ CURLcode curl_global_init(long flags) | |||||||
|   Curl_crealloc = (curl_realloc_callback)realloc; |   Curl_crealloc = (curl_realloc_callback)realloc; | ||||||
|   Curl_cstrdup = (curl_strdup_callback)system_strdup; |   Curl_cstrdup = (curl_strdup_callback)system_strdup; | ||||||
|   Curl_ccalloc = (curl_calloc_callback)calloc; |   Curl_ccalloc = (curl_calloc_callback)calloc; | ||||||
|  | #if defined(WIN32) && defined(UNICODE) | ||||||
|  |   Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   if(flags & CURL_GLOBAL_SSL) |   if(flags & CURL_GLOBAL_SSL) | ||||||
|     if(!Curl_ssl_init()) { |     if(!Curl_ssl_init()) { | ||||||
| @@ -276,10 +282,6 @@ CURLcode curl_global_init(long flags) | |||||||
|  |  | ||||||
|   init_flags  = flags; |   init_flags  = flags; | ||||||
|  |  | ||||||
|   /* Preset pseudo-random number sequence. */ |  | ||||||
|  |  | ||||||
|   Curl_srand(); |  | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -397,67 +399,275 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...) | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | #ifdef CURLDEBUG | ||||||
|  * curl_easy_perform() is the external interface that performs a blocking |  | ||||||
|  * transfer as previously setup. | 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 | ||||||
|  * |  * | ||||||
|  * CONCEPT: This function creates a multi handle, adds the easy handle to it, |  * Callback that gets called with a new value when the timeout should be | ||||||
|  * runs curl_multi_perform() until the transfer is done, then detaches the |  * updated. | ||||||
|  * 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. |  | ||||||
|  */ |  */ | ||||||
| CURLcode curl_easy_perform(CURL *easy) |  | ||||||
|  | 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; | ||||||
|  |   (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) | ||||||
| { | { | ||||||
|   CURLM *multi; |  | ||||||
|   CURLMcode mcode; |  | ||||||
|   CURLcode code = CURLE_OK; |  | ||||||
|   CURLMsg *msg; |  | ||||||
|   bool done = FALSE; |   bool done = FALSE; | ||||||
|   int rc; |   CURLMcode mcode; | ||||||
|   struct SessionHandle *data = easy; |   CURLcode rc = 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); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |     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) { | ||||||
|  |       rc = msg->data.result; | ||||||
|  |       done = TRUE; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return rc; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* 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 code = CURLE_OK; | ||||||
|  |   struct timeval before; | ||||||
|   int without_fds = 0;  /* count number of consecutive returns from |   int without_fds = 0;  /* count number of consecutive returns from | ||||||
|                            curl_multi_wait() without any filedescriptors */ |                            curl_multi_wait() without any filedescriptors */ | ||||||
|   struct timeval before; |  | ||||||
|  |  | ||||||
|   if(!easy) |  | ||||||
|     return CURLE_BAD_FUNCTION_ARGUMENT; |  | ||||||
|  |  | ||||||
|   if(data->multi) { |  | ||||||
|     failf(data, "easy handled 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, easy); |  | ||||||
|   if(mcode) { |  | ||||||
|     curl_multi_cleanup(multi); |  | ||||||
|     if(mcode == CURLM_OUT_OF_MEMORY) |  | ||||||
|       return CURLE_OUT_OF_MEMORY; |  | ||||||
|     else |  | ||||||
|       return CURLE_FAILED_INIT; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* assign this after curl_multi_add_handle() since that function checks for |  | ||||||
|      it and rejects this handle otherwise */ |  | ||||||
|   data->multi = multi; |  | ||||||
|  |  | ||||||
|   while(!done && !mcode) { |   while(!done && !mcode) { | ||||||
|     int still_running; |     int still_running; | ||||||
| @@ -480,9 +690,7 @@ CURLcode curl_easy_perform(CURL *easy) | |||||||
|         if(curlx_tvdiff(after, before) <= 10) { |         if(curlx_tvdiff(after, before) <= 10) { | ||||||
|           without_fds++; |           without_fds++; | ||||||
|           if(without_fds > 2) { |           if(without_fds > 2) { | ||||||
|             int sleep_ms = without_fds * 50; |             int sleep_ms = without_fds < 10 ? (1 << (without_fds-1)): 1000; | ||||||
|             if(sleep_ms > 1000) |  | ||||||
|               sleep_ms = 1000; |  | ||||||
|             Curl_wait_ms(sleep_ms); |             Curl_wait_ms(sleep_ms); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @@ -499,22 +707,114 @@ CURLcode curl_easy_perform(CURL *easy) | |||||||
|  |  | ||||||
|     /* only read 'still_running' if curl_multi_perform() return OK */ |     /* only read 'still_running' if curl_multi_perform() return OK */ | ||||||
|     if((mcode == CURLM_OK) && !still_running) { |     if((mcode == CURLM_OK) && !still_running) { | ||||||
|       msg = curl_multi_info_read(multi, &rc); |       int rc; | ||||||
|  |       CURLMsg *msg = curl_multi_info_read(multi, &rc); | ||||||
|       if(msg) { |       if(msg) { | ||||||
|         code = msg->data.result; |         code = msg->data.result; | ||||||
|         done = TRUE; |         done = TRUE; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   return code; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * 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 code = CURLE_OK; | ||||||
|  |   SIGPIPE_VARIABLE(pipe_st); | ||||||
|  |  | ||||||
|  |   if(!data) | ||||||
|  |     return CURLE_BAD_FUNCTION_ARGUMENT; | ||||||
|  |  | ||||||
|  |   if(data->multi) { | ||||||
|  |     failf(data, "easy handled 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 */ | ||||||
|  |   code = events ? easy_events(multi) : easy_transfer(multi); | ||||||
|  |  | ||||||
|   /* ignoring the return code isn't nice, but atm we can't really handle |   /* ignoring the return code isn't nice, but atm we can't really handle | ||||||
|      a failure here, room for future improvement! */ |      a failure here, room for future improvement! */ | ||||||
|   (void)curl_multi_remove_handle(multi, easy); |   (void)curl_multi_remove_handle(multi, data); | ||||||
|  |  | ||||||
|  |   sigpipe_restore(&pipe_st); | ||||||
|  |  | ||||||
|   /* The multi handle is kept alive, owned by the easy handle */ |   /* The multi handle is kept alive, owned by the easy handle */ | ||||||
|   return code; |   return code; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * 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 |  * curl_easy_cleanup() is the external interface to cleaning/freeing the given | ||||||
|  * easy handle. |  * easy handle. | ||||||
| @@ -522,27 +822,14 @@ CURLcode curl_easy_perform(CURL *easy) | |||||||
| void curl_easy_cleanup(CURL *curl) | void curl_easy_cleanup(CURL *curl) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = (struct SessionHandle *)curl; |   struct SessionHandle *data = (struct SessionHandle *)curl; | ||||||
|  |   SIGPIPE_VARIABLE(pipe_st); | ||||||
|  |  | ||||||
|   if(!data) |   if(!data) | ||||||
|     return; |     return; | ||||||
|  |  | ||||||
|  |   sigpipe_ignore(data, &pipe_st); | ||||||
|   Curl_close(data); |   Curl_close(data); | ||||||
| } |   sigpipe_restore(&pipe_st); | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Store a pointed to the multi handle within the easy handle's data struct. |  | ||||||
|  */ |  | ||||||
| void Curl_easy_addmulti(struct SessionHandle *data, |  | ||||||
|                         void *multi) |  | ||||||
| { |  | ||||||
|   data->multi = multi; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void Curl_easy_initHandleData(struct SessionHandle *data) |  | ||||||
| { |  | ||||||
|     memset(&data->req, 0, sizeof(struct SingleRequest)); |  | ||||||
|  |  | ||||||
|     data->req.maxdownload = -1; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -554,12 +841,16 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) | |||||||
| { | { | ||||||
|   va_list arg; |   va_list arg; | ||||||
|   void *paramp; |   void *paramp; | ||||||
|  |   CURLcode ret; | ||||||
|   struct SessionHandle *data = (struct SessionHandle *)curl; |   struct SessionHandle *data = (struct SessionHandle *)curl; | ||||||
|  |  | ||||||
|   va_start(arg, info); |   va_start(arg, info); | ||||||
|   paramp = va_arg(arg, void *); |   paramp = va_arg(arg, void *); | ||||||
|  |  | ||||||
|   return Curl_getinfo(data, info, paramp); |   ret = Curl_getinfo(data, info, paramp); | ||||||
|  |  | ||||||
|  |   va_end(arg); | ||||||
|  |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -637,8 +928,6 @@ CURL *curl_easy_duphandle(CURL *incurl) | |||||||
|  |  | ||||||
|   Curl_convert_setup(outcurl); |   Curl_convert_setup(outcurl); | ||||||
|  |  | ||||||
|   Curl_easy_initHandleData(outcurl); |  | ||||||
|  |  | ||||||
|   outcurl->magic = CURLEASY_MAGIC_NUMBER; |   outcurl->magic = CURLEASY_MAGIC_NUMBER; | ||||||
|  |  | ||||||
|   /* we reach this point and thus we are OK */ |   /* we reach this point and thus we are OK */ | ||||||
| @@ -672,7 +961,7 @@ void curl_easy_reset(CURL *curl) | |||||||
|  |  | ||||||
|   data->state.path = NULL; |   data->state.path = NULL; | ||||||
|  |  | ||||||
|   Curl_safefree(data->state.proto.generic); |   Curl_free_request_state(data); | ||||||
|  |  | ||||||
|   /* zero out UserDefined data: */ |   /* zero out UserDefined data: */ | ||||||
|   Curl_freeset(data); |   Curl_freeset(data); | ||||||
| @@ -682,9 +971,6 @@ void curl_easy_reset(CURL *curl) | |||||||
|   /* zero out Progress data: */ |   /* zero out Progress data: */ | ||||||
|   memset(&data->progress, 0, sizeof(struct Progress)); |   memset(&data->progress, 0, sizeof(struct Progress)); | ||||||
|  |  | ||||||
|   /* init Handle data */ |  | ||||||
|   Curl_easy_initHandleData(data); |  | ||||||
|  |  | ||||||
|   data->progress.flags |= PGRS_HIDE; |   data->progress.flags |= PGRS_HIDE; | ||||||
|   data->state.current_speed = -1; /* init to negative == impossible */ |   data->state.current_speed = -1; /* init to negative == impossible */ | ||||||
| } | } | ||||||
| @@ -746,7 +1032,7 @@ CURLcode curl_easy_pause(CURL *curl, int action) | |||||||
|     do { |     do { | ||||||
|       chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize; |       chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize; | ||||||
|  |  | ||||||
|       result = Curl_client_write(data->state.current_conn, |       result = Curl_client_write(data->easy_conn, | ||||||
|                                  temptype, tempwrite, chunklen); |                                  temptype, tempwrite, chunklen); | ||||||
|       if(result) |       if(result) | ||||||
|         /* failures abort the loop at once */ |         /* failures abort the loop at once */ | ||||||
| @@ -788,6 +1074,13 @@ CURLcode curl_easy_pause(CURL *curl, int action) | |||||||
|     free(freewrite); /* this is unconditionally no longer used */ |     free(freewrite); /* this is unconditionally no longer used */ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /* 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; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -25,9 +25,9 @@ | |||||||
| /* | /* | ||||||
|  * Prototypes for library-wide functions provided by easy.c |  * Prototypes for library-wide functions provided by easy.c | ||||||
|  */ |  */ | ||||||
| void Curl_easy_addmulti(struct SessionHandle *data, void *multi); | #ifdef CURLDEBUG | ||||||
|  | CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy); | ||||||
| void Curl_easy_initHandleData(struct SessionHandle *data); | #endif | ||||||
|  |  | ||||||
| #endif /* HEADER_CURL_EASYIF_H */ | #endif /* HEADER_CURL_EASYIF_H */ | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								lib/file.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								lib/file.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -90,7 +90,7 @@ static CURLcode file_done(struct connectdata *conn, | |||||||
| static CURLcode file_connect(struct connectdata *conn, bool *done); | static CURLcode file_connect(struct connectdata *conn, bool *done); | ||||||
| static CURLcode file_disconnect(struct connectdata *conn, | static CURLcode file_disconnect(struct connectdata *conn, | ||||||
|                                 bool dead_connection); |                                 bool dead_connection); | ||||||
|  | static CURLcode file_setup_connection(struct connectdata *conn); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * FILE scheme handler. |  * FILE scheme handler. | ||||||
| @@ -98,7 +98,7 @@ static CURLcode file_disconnect(struct connectdata *conn, | |||||||
|  |  | ||||||
| const struct Curl_handler Curl_handler_file = { | const struct Curl_handler Curl_handler_file = { | ||||||
|   "FILE",                               /* scheme */ |   "FILE",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   file_setup_connection,                /* setup_connection */ | ||||||
|   file_do,                              /* do_it */ |   file_do,                              /* do_it */ | ||||||
|   file_done,                            /* done */ |   file_done,                            /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -117,6 +117,16 @@ const struct Curl_handler Curl_handler_file = { | |||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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 |   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 |   properly. This code is copied from the FTP implementation and might as | ||||||
| @@ -179,39 +189,17 @@ static CURLcode file_connect(struct connectdata *conn, bool *done) | |||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   char *real_path; |   char *real_path; | ||||||
|   struct FILEPROTO *file; |   struct FILEPROTO *file = data->req.protop; | ||||||
|   int fd; |   int fd; | ||||||
| #ifdef DOS_FILESYSTEM | #ifdef DOS_FILESYSTEM | ||||||
|   int i; |   int i; | ||||||
|   char *actual_path; |   char *actual_path; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   /* If there already is a protocol-specific struct allocated for this |  | ||||||
|      sessionhandle, deal with it */ |  | ||||||
|   Curl_reset_reqproto(conn); |  | ||||||
|  |  | ||||||
|   real_path = curl_easy_unescape(data, data->state.path, 0, NULL); |   real_path = curl_easy_unescape(data, data->state.path, 0, NULL); | ||||||
|   if(!real_path) |   if(!real_path) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   if(!data->state.proto.file) { |  | ||||||
|     file = calloc(1, sizeof(struct FILEPROTO)); |  | ||||||
|     if(!file) { |  | ||||||
|       free(real_path); |  | ||||||
|       return CURLE_OUT_OF_MEMORY; |  | ||||||
|     } |  | ||||||
|     data->state.proto.file = file; |  | ||||||
|   } |  | ||||||
|   else { |  | ||||||
|     /* file is not a protocol that can deal with "persistancy" */ |  | ||||||
|     file = data->state.proto.file; |  | ||||||
|     Curl_safefree(file->freepath); |  | ||||||
|     file->path = NULL; |  | ||||||
|     if(file->fd != -1) |  | ||||||
|       close(file->fd); |  | ||||||
|     file->fd = -1; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| #ifdef DOS_FILESYSTEM | #ifdef DOS_FILESYSTEM | ||||||
|   /* If the first character is a slash, and there's |   /* If the first character is a slash, and there's | ||||||
|      something that looks like a drive at the beginning of |      something that looks like a drive at the beginning of | ||||||
| @@ -262,7 +250,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done) | |||||||
| static CURLcode file_done(struct connectdata *conn, | static CURLcode file_done(struct connectdata *conn, | ||||||
|                                CURLcode status, bool premature) |                                CURLcode status, bool premature) | ||||||
| { | { | ||||||
|   struct FILEPROTO *file = conn->data->state.proto.file; |   struct FILEPROTO *file = conn->data->req.protop; | ||||||
|   (void)status; /* not used */ |   (void)status; /* not used */ | ||||||
|   (void)premature; /* not used */ |   (void)premature; /* not used */ | ||||||
|  |  | ||||||
| @@ -280,7 +268,7 @@ static CURLcode file_done(struct connectdata *conn, | |||||||
| static CURLcode file_disconnect(struct connectdata *conn, | static CURLcode file_disconnect(struct connectdata *conn, | ||||||
|                                 bool dead_connection) |                                 bool dead_connection) | ||||||
| { | { | ||||||
|   struct FILEPROTO *file = conn->data->state.proto.file; |   struct FILEPROTO *file = conn->data->req.protop; | ||||||
|   (void)dead_connection; /* not used */ |   (void)dead_connection; /* not used */ | ||||||
|  |  | ||||||
|   if(file) { |   if(file) { | ||||||
| @@ -302,7 +290,7 @@ static CURLcode file_disconnect(struct connectdata *conn, | |||||||
|  |  | ||||||
| static CURLcode file_upload(struct connectdata *conn) | static CURLcode file_upload(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct FILEPROTO *file = conn->data->state.proto.file; |   struct FILEPROTO *file = conn->data->req.protop; | ||||||
|   const char *dir = strchr(file->path, DIRSEP); |   const char *dir = strchr(file->path, DIRSEP); | ||||||
|   int fd; |   int fd; | ||||||
|   int mode; |   int mode; | ||||||
| @@ -440,6 +428,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done) | |||||||
|   curl_off_t bytecount = 0; |   curl_off_t bytecount = 0; | ||||||
|   int fd; |   int fd; | ||||||
|   struct timeval now = Curl_tvnow(); |   struct timeval now = Curl_tvnow(); | ||||||
|  |   struct FILEPROTO *file; | ||||||
|  |  | ||||||
|   *done = TRUE; /* unconditionally */ |   *done = TRUE; /* unconditionally */ | ||||||
|  |  | ||||||
| @@ -449,8 +438,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done) | |||||||
|   if(data->set.upload) |   if(data->set.upload) | ||||||
|     return file_upload(conn); |     return file_upload(conn); | ||||||
|  |  | ||||||
|  |   file = conn->data->req.protop; | ||||||
|  |  | ||||||
|   /* get the fd from the connection phase */ |   /* get the fd from the connection phase */ | ||||||
|   fd = conn->data->state.proto.file->fd; |   fd = file->fd; | ||||||
|  |  | ||||||
|   /* VMS: This only works reliable for STREAMLF files */ |   /* VMS: This only works reliable for STREAMLF files */ | ||||||
|   if(-1 != fstat(fd, &statbuf)) { |   if(-1 != fstat(fd, &statbuf)) { | ||||||
|   | |||||||
							
								
								
									
										147
									
								
								lib/formdata.c
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								lib/formdata.c
									
									
									
									
									
								
							| @@ -24,9 +24,6 @@ | |||||||
|  |  | ||||||
| #include <curl/curl.h> | #include <curl/curl.h> | ||||||
|  |  | ||||||
| /* Length of the random boundary string. */ |  | ||||||
| #define BOUNDARY_LENGTH 40 |  | ||||||
|  |  | ||||||
| #if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) | #if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) | ||||||
|  |  | ||||||
| #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) | #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) | ||||||
| @@ -35,7 +32,7 @@ | |||||||
|  |  | ||||||
| #include "urldata.h" /* for struct SessionHandle */ | #include "urldata.h" /* for struct SessionHandle */ | ||||||
| #include "formdata.h" | #include "formdata.h" | ||||||
| #include "curl_rand.h" | #include "sslgen.h" | ||||||
| #include "strequal.h" | #include "strequal.h" | ||||||
| #include "curl_memory.h" | #include "curl_memory.h" | ||||||
| #include "sendf.h" | #include "sendf.h" | ||||||
| @@ -56,7 +53,7 @@ static char *Curl_basename(char *path); | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| static size_t readfromfile(struct Form *form, char *buffer, size_t size); | static size_t readfromfile(struct Form *form, char *buffer, size_t size); | ||||||
| static char *formboundary(void); | static char *formboundary(struct SessionHandle *data); | ||||||
|  |  | ||||||
| /* What kind of Content-Type to use on un-specified files with unrecognized | /* What kind of Content-Type to use on un-specified files with unrecognized | ||||||
|    extensions. */ |    extensions. */ | ||||||
| @@ -171,8 +168,8 @@ static FormInfo * AddFormInfo(char *value, | |||||||
|  * Returns some valid contenttype for filename. |  * Returns some valid contenttype for filename. | ||||||
|  * |  * | ||||||
|  ***************************************************************************/ |  ***************************************************************************/ | ||||||
| static const char * ContentTypeForFilename (const char *filename, | static const char *ContentTypeForFilename(const char *filename, | ||||||
|                                             const char *prevtype) |                                           const char *prevtype) | ||||||
| { | { | ||||||
|   const char *contenttype = NULL; |   const char *contenttype = NULL; | ||||||
|   unsigned int i; |   unsigned int i; | ||||||
| @@ -181,7 +178,7 @@ static const char * ContentTypeForFilename (const char *filename, | |||||||
|    * extensions and pick the first we match! |    * extensions and pick the first we match! | ||||||
|    */ |    */ | ||||||
|   struct ContentType { |   struct ContentType { | ||||||
|     char extension[6]; |     const char *extension; | ||||||
|     const char *type; |     const char *type; | ||||||
|   }; |   }; | ||||||
|   static const struct ContentType ctts[]={ |   static const struct ContentType ctts[]={ | ||||||
| @@ -429,7 +426,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, | |||||||
|  |  | ||||||
|       /* Get contents from a given file name */ |       /* Get contents from a given file name */ | ||||||
|     case CURLFORM_FILECONTENT: |     case CURLFORM_FILECONTENT: | ||||||
|       if(current_form->flags != 0) |       if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE)) | ||||||
|         return_value = CURL_FORMADD_OPTION_TWICE; |         return_value = CURL_FORMADD_OPTION_TWICE; | ||||||
|       else { |       else { | ||||||
|         const char *filename = array_state? |         const char *filename = array_state? | ||||||
| @@ -670,9 +667,11 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, | |||||||
|         if(((form->flags & HTTPPOST_FILENAME) || |         if(((form->flags & HTTPPOST_FILENAME) || | ||||||
|             (form->flags & HTTPPOST_BUFFER)) && |             (form->flags & HTTPPOST_BUFFER)) && | ||||||
|            !form->contenttype ) { |            !form->contenttype ) { | ||||||
|  |           char *f = form->flags & HTTPPOST_BUFFER? | ||||||
|  |             form->showfilename : form->value; | ||||||
|  |  | ||||||
|           /* our contenttype is missing */ |           /* our contenttype is missing */ | ||||||
|           form->contenttype |           form->contenttype = strdup(ContentTypeForFilename(f, prevtype)); | ||||||
|             = strdup(ContentTypeForFilename(form->value, prevtype)); |  | ||||||
|           if(!form->contenttype) { |           if(!form->contenttype) { | ||||||
|             return_value = CURL_FORMADD_MEMORY; |             return_value = CURL_FORMADD_MEMORY; | ||||||
|             break; |             break; | ||||||
| @@ -777,6 +776,70 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost, | |||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifdef __VMS | ||||||
|  | #include <fabdef.h> | ||||||
|  | /* | ||||||
|  |  * 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. |  * AddFormData() adds a chunk of data to the FormData linked list. | ||||||
|  * |  * | ||||||
| @@ -832,7 +895,7 @@ static CURLcode AddFormData(struct FormData **formp, | |||||||
|       if(!strequal("-", newform->line)) { |       if(!strequal("-", newform->line)) { | ||||||
|         struct_stat file; |         struct_stat file; | ||||||
|         if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode)) |         if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode)) | ||||||
|           *size += file.st_size; |           *size += filesize(newform->line, file); | ||||||
|         else |         else | ||||||
|           return CURLE_BAD_FUNCTION_ARGUMENT; |           return CURLE_BAD_FUNCTION_ARGUMENT; | ||||||
|       } |       } | ||||||
| @@ -1101,7 +1164,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data, | |||||||
|   if(!post) |   if(!post) | ||||||
|     return result; /* no input => no output! */ |     return result; /* no input => no output! */ | ||||||
|  |  | ||||||
|   boundary = formboundary(); |   boundary = formboundary(data); | ||||||
|   if(!boundary) |   if(!boundary) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
| @@ -1157,7 +1220,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data, | |||||||
|          the magic to include several files with the same field name */ |          the magic to include several files with the same field name */ | ||||||
|  |  | ||||||
|       Curl_safefree(fileboundary); |       Curl_safefree(fileboundary); | ||||||
|       fileboundary = formboundary(); |       fileboundary = formboundary(data); | ||||||
|       if(!fileboundary) { |       if(!fileboundary) { | ||||||
|         result = CURLE_OUT_OF_MEMORY; |         result = CURLE_OUT_OF_MEMORY; | ||||||
|         break; |         break; | ||||||
| @@ -1343,6 +1406,36 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata ) | |||||||
|   return 0; |   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() |  * readfromfile() | ||||||
|  * |  * | ||||||
| @@ -1365,7 +1458,7 @@ static size_t readfromfile(struct Form *form, char *buffer, | |||||||
|   else { |   else { | ||||||
|     if(!form->fp) { |     if(!form->fp) { | ||||||
|       /* this file hasn't yet been opened */ |       /* this file hasn't yet been opened */ | ||||||
|       form->fp = fopen(form->data->line, "rb"); /* b is for binary */ |       form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */ | ||||||
|       if(!form->fp) |       if(!form->fp) | ||||||
|         return (size_t)-1; /* failure */ |         return (size_t)-1; /* failure */ | ||||||
|     } |     } | ||||||
| @@ -1464,28 +1557,12 @@ char *Curl_formpostheader(void *formp, size_t *len) | |||||||
|  * formboundary() creates a suitable boundary string and returns an allocated |  * formboundary() creates a suitable boundary string and returns an allocated | ||||||
|  * one. |  * one. | ||||||
|  */ |  */ | ||||||
| static char *formboundary(void) | static char *formboundary(struct SessionHandle *data) | ||||||
| { | { | ||||||
|   char *retstring; |   /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615) | ||||||
|   size_t i; |  | ||||||
|  |  | ||||||
|   static const char table16[]="0123456789abcdef"; |  | ||||||
|  |  | ||||||
|   retstring = malloc(BOUNDARY_LENGTH+1); |  | ||||||
|  |  | ||||||
|   if(!retstring) |  | ||||||
|     return NULL; /* failed */ |  | ||||||
|  |  | ||||||
|   strcpy(retstring, "----------------------------"); |  | ||||||
|  |  | ||||||
|   for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++) |  | ||||||
|     retstring[i] = table16[Curl_rand()%16]; |  | ||||||
|  |  | ||||||
|   /* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416) |  | ||||||
|      combinations */ |      combinations */ | ||||||
|   retstring[BOUNDARY_LENGTH]=0; /* zero terminate */ |   return aprintf("------------------------%08x%08x", | ||||||
|  |                  Curl_rand(data), Curl_rand(data)); | ||||||
|   return retstring; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #else  /* CURL_DISABLE_HTTP */ | #else  /* CURL_DISABLE_HTTP */ | ||||||
|   | |||||||
| @@ -147,6 +147,12 @@ struct ftp_conn { | |||||||
|   curl_off_t known_filesize; /* file size is different from -1, if wildcard |   curl_off_t known_filesize; /* file size is different from -1, if wildcard | ||||||
|                                 LIST parsing was done and wc_statemach set |                                 LIST parsing was done and wc_statemach set | ||||||
|                                 it */ |                                 it */ | ||||||
|  |   /* newhost must be able to hold a full IP-style address in ASCII, which | ||||||
|  |      in the IPv6 case means 5*8-1 = 39 letters */ | ||||||
|  | #define NEWHOST_BUFSIZE 48 | ||||||
|  |   char newhost[NEWHOST_BUFSIZE]; /* this is the pair to connect the DATA... */ | ||||||
|  |   unsigned short newport;        /* connection to */ | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define DEFAULT_ACCEPT_TIMEOUT   60000 /* milliseconds == one minute */ | #define DEFAULT_ACCEPT_TIMEOUT   60000 /* milliseconds == one minute */ | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -53,9 +53,9 @@ CURLcode Curl_initinfo(struct SessionHandle *data) | |||||||
|   pro->t_redirect = 0; |   pro->t_redirect = 0; | ||||||
|  |  | ||||||
|   info->httpcode = 0; |   info->httpcode = 0; | ||||||
|   info->httpversion=0; |   info->httpversion = 0; | ||||||
|   info->filetime=-1; /* -1 is an illegal time and thus means unknown */ |   info->filetime = -1; /* -1 is an illegal time and thus means unknown */ | ||||||
|   info->timecond=0; |   info->timecond = FALSE; | ||||||
|  |  | ||||||
|   if(info->contenttype) |   if(info->contenttype) | ||||||
|     free(info->contenttype); |     free(info->contenttype); | ||||||
| @@ -186,7 +186,7 @@ static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info, | |||||||
|     break; |     break; | ||||||
|   case CURLINFO_CONDITION_UNMET: |   case CURLINFO_CONDITION_UNMET: | ||||||
|     /* return if the condition prevented the document to get transferred */ |     /* return if the condition prevented the document to get transferred */ | ||||||
|     *param_longp = data->info.timecond; |     *param_longp = data->info.timecond ? 1L : 0L; | ||||||
|     break; |     break; | ||||||
|   case CURLINFO_RTSP_CLIENT_CSEQ: |   case CURLINFO_RTSP_CLIENT_CSEQ: | ||||||
|     *param_longp = data->state.rtsp_next_client_CSeq; |     *param_longp = data->state.rtsp_next_client_CSeq; | ||||||
| @@ -277,7 +277,57 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info, | |||||||
|     ptr.to_certinfo = &data->info.certs; |     ptr.to_certinfo = &data->info.certs; | ||||||
|     *param_slistp = ptr.to_slist; |     *param_slistp = ptr.to_slist; | ||||||
|     break; |     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; | ||||||
|  |  | ||||||
|  |       *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_SSLEAY | ||||||
|  |       tsi->backend = CURLSSLBACKEND_OPENSSL; | ||||||
|  |       tsi->internals = conn->ssl[sockindex].ctx; | ||||||
|  | #endif | ||||||
|  | #ifdef USE_GNUTLS | ||||||
|  |       tsi->backend = CURLSSLBACKEND_GNUTLS; | ||||||
|  |       tsi->internals = conn->ssl[sockindex].session; | ||||||
|  | #endif | ||||||
|  | #ifdef USE_NSS | ||||||
|  |       tsi->backend = CURLSSLBACKEND_NSS; | ||||||
|  |       tsi->internals = conn->ssl[sockindex].handle; | ||||||
|  | #endif | ||||||
|  | #ifdef USE_QSOSSL | ||||||
|  |       tsi->backend = CURLSSLBACKEND_QSOSSL; | ||||||
|  |       tsi->internals = conn->ssl[sockindex].handle; | ||||||
|  | #endif | ||||||
|  | #ifdef USE_GSKIT | ||||||
|  |       tsi->backend = CURLSSLBACKEND_GSKIT; | ||||||
|  |       tsi->internals = conn->ssl[sockindex].handle; | ||||||
|  | #endif | ||||||
|  |       /* 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; | ||||||
|  |     } | ||||||
|  |     break; | ||||||
|   default: |   default: | ||||||
|     return CURLE_BAD_FUNCTION_ARGUMENT; |     return CURLE_BAD_FUNCTION_ARGUMENT; | ||||||
|   } |   } | ||||||
|   | |||||||
							
								
								
									
										1053
									
								
								lib/gskit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1053
									
								
								lib/gskit.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										64
									
								
								lib/gskit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								lib/gskit.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | #ifndef HEADER_CURL_GSKIT_H | ||||||
|  | #define HEADER_CURL_GSKIT_H | ||||||
|  | /*************************************************************************** | ||||||
|  |  *                                  _   _ ____  _ | ||||||
|  |  *  Project                     ___| | | |  _ \| | | ||||||
|  |  *                             / __| | | | |_) | | | ||||||
|  |  *                            | (__| |_| |  _ <| |___ | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  |  * This software is licensed as described in the file COPYING, which | ||||||
|  |  * you should have received as part of this distribution. The terms | ||||||
|  |  * are also available at http://curl.haxx.se/docs/copyright.html. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the COPYING file. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  ***************************************************************************/ | ||||||
|  | #include "curl_setup.h" | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This header should only be needed to get included by sslgen.c and gskit.c | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "urldata.h" | ||||||
|  |  | ||||||
|  | #ifdef USE_GSKIT | ||||||
|  | int Curl_gskit_init(void); | ||||||
|  | void Curl_gskit_cleanup(void); | ||||||
|  | CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex); | ||||||
|  | CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn, | ||||||
|  |                                         int sockindex, bool * done); | ||||||
|  | void Curl_gskit_close(struct connectdata *conn, int sockindex); | ||||||
|  | int Curl_gskit_close_all(struct SessionHandle * data); | ||||||
|  | int Curl_gskit_shutdown(struct connectdata * conn, int sockindex); | ||||||
|  |  | ||||||
|  | size_t Curl_gskit_version(char * buffer, size_t size); | ||||||
|  | int Curl_gskit_check_cxn(struct connectdata * cxn); | ||||||
|  |  | ||||||
|  | /* 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 Curl_gskit_close_all | ||||||
|  | #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 | ||||||
|  | #endif /* USE_GSKIT */ | ||||||
|  |  | ||||||
|  | #endif /* HEADER_CURL_GSKIT_H */ | ||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -633,10 +633,8 @@ gtls_connect_step3(struct connectdata *conn, | |||||||
|     else |     else | ||||||
|       infof(data, "\t server certificate verification OK\n"); |       infof(data, "\t server certificate verification OK\n"); | ||||||
|   } |   } | ||||||
|   else { |   else | ||||||
|     infof(data, "\t server certificate verification SKIPPED\n"); |     infof(data, "\t server certificate verification SKIPPED\n"); | ||||||
|     goto after_server_cert_verification; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* initialize an X.509 certificate structure. */ |   /* initialize an X.509 certificate structure. */ | ||||||
|   gnutls_x509_crt_init(&x509_cert); |   gnutls_x509_crt_init(&x509_cert); | ||||||
| @@ -766,8 +764,6 @@ gtls_connect_step3(struct connectdata *conn, | |||||||
|  |  | ||||||
|   gnutls_x509_crt_deinit(x509_cert); |   gnutls_x509_crt_deinit(x509_cert); | ||||||
|  |  | ||||||
| after_server_cert_verification: |  | ||||||
|  |  | ||||||
|   /* compression algorithm (if any) */ |   /* compression algorithm (if any) */ | ||||||
|   ptr = gnutls_compression_get_name(gnutls_compression_get(session)); |   ptr = gnutls_compression_get_name(gnutls_compression_get(session)); | ||||||
|   /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ |   /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -55,6 +55,10 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */ | |||||||
|                       unsigned char *md5sum, /* output */ |                       unsigned char *md5sum, /* output */ | ||||||
|                       size_t md5len); |                       size_t md5len); | ||||||
|  |  | ||||||
|  | /* this backend provides these functions: */ | ||||||
|  | #define have_curlssl_random 1 | ||||||
|  | #define have_curlssl_md5sum 1 | ||||||
|  |  | ||||||
| /* API setup for GnuTLS */ | /* API setup for GnuTLS */ | ||||||
| #define curlssl_init Curl_gtls_init | #define curlssl_init Curl_gtls_init | ||||||
| #define curlssl_cleanup Curl_gtls_cleanup | #define curlssl_cleanup Curl_gtls_cleanup | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -391,7 +391,7 @@ void Curl_hash_print(struct curl_hash *h, | |||||||
|     if(func) |     if(func) | ||||||
|       func(he->ptr); |       func(he->ptr); | ||||||
|     else |     else | ||||||
|       fprintf(stderr, " [%p]", he->ptr); |       fprintf(stderr, " [%p]", (void *)he->ptr); | ||||||
|  |  | ||||||
|     he = Curl_hash_next_element(&iter); |     he = Curl_hash_next_element(&iter); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -22,8 +22,9 @@ | |||||||
|  |  | ||||||
| #include "curl_setup.h" | #include "curl_setup.h" | ||||||
|  |  | ||||||
| #if defined(USE_SSLEAY) || defined(USE_AXTLS) | #if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \ | ||||||
| /* these two backends use functions from this file */ |     defined(USE_GSKIT) || defined(USE_NSS) | ||||||
|  | /* these backends use functions from this file */ | ||||||
|  |  | ||||||
| #include "hostcheck.h" | #include "hostcheck.h" | ||||||
| #include "rawstr.h" | #include "rawstr.h" | ||||||
| @@ -93,4 +94,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname) | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif /* SSLEAY or AXTLS */ | #endif /* SSLEAY or AXTLS or QSOSSL or GSKIT or NSS */ | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								lib/hostip.c
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								lib/hostip.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -140,6 +140,10 @@ struct curl_hash *Curl_global_host_cache_init(void) | |||||||
| void Curl_global_host_cache_dtor(void) | void Curl_global_host_cache_dtor(void) | ||||||
| { | { | ||||||
|   if(host_cache_initialized) { |   if(host_cache_initialized) { | ||||||
|  |     /* first make sure that any custom "CURLOPT_RESOLVE" names are | ||||||
|  |        cleared off */ | ||||||
|  |     Curl_hostcache_clean(NULL, &hostname_cache); | ||||||
|  |     /* then free the remaining hash completely */ | ||||||
|     Curl_hash_clean(&hostname_cache); |     Curl_hash_clean(&hostname_cache); | ||||||
|     host_cache_initialized = 0; |     host_cache_initialized = 0; | ||||||
|   } |   } | ||||||
| @@ -287,9 +291,10 @@ remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns) | |||||||
| { | { | ||||||
|   struct hostcache_prune_data user; |   struct hostcache_prune_data user; | ||||||
|  |  | ||||||
|   if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache) |   if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache || | ||||||
|     /* cache forever means never prune, and NULL hostcache means |      dns->inuse) | ||||||
|        we can't do it */ |     /* cache forever means never prune, and NULL hostcache means we can't do | ||||||
|  |        it, if it still is in use then we leave it */ | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   time(&user.now); |   time(&user.now); | ||||||
| @@ -424,9 +429,13 @@ int Curl_resolv(struct connectdata *conn, | |||||||
|   /* free the allocated entry_id again */ |   /* free the allocated entry_id again */ | ||||||
|   free(entry_id); |   free(entry_id); | ||||||
|  |  | ||||||
|  |   infof(data, "Hostname was %sfound in DNS cache\n", dns?"":"NOT "); | ||||||
|  |  | ||||||
|   /* See whether the returned entry is stale. Done before we release lock */ |   /* See whether the returned entry is stale. Done before we release lock */ | ||||||
|   if(remove_entry_if_stale(data, dns)) |   if(remove_entry_if_stale(data, dns)) { | ||||||
|  |     infof(data, "Hostname in DNS cache was stale, zapped\n"); | ||||||
|     dns = NULL; /* the memory deallocation is being handled by the hash */ |     dns = NULL; /* the memory deallocation is being handled by the hash */ | ||||||
|  |   } | ||||||
|  |  | ||||||
|   if(dns) { |   if(dns) { | ||||||
|     dns->inuse++; /* we use it! */ |     dns->inuse++; /* we use it! */ | ||||||
| @@ -681,12 +690,14 @@ clean_up: | |||||||
|  * Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been |  * 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 |  * made, the struct may be destroyed due to pruning. It is important that only | ||||||
|  * one unlock is made for each Curl_resolv() call. |  * one unlock is made for each Curl_resolv() call. | ||||||
|  |  * | ||||||
|  |  * May be called with 'data' == NULL for global cache. | ||||||
|  */ |  */ | ||||||
| void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns) | void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns) | ||||||
| { | { | ||||||
|   DEBUGASSERT(dns && (dns->inuse>0)); |   DEBUGASSERT(dns && (dns->inuse>0)); | ||||||
|  |  | ||||||
|   if(data->share) |   if(data && data->share) | ||||||
|     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); |     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); | ||||||
|  |  | ||||||
|   dns->inuse--; |   dns->inuse--; | ||||||
| @@ -697,7 +708,7 @@ void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns) | |||||||
|     free(dns); |     free(dns); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(data->share) |   if(data && data->share) | ||||||
|     Curl_share_unlock(data, CURL_LOCK_DATA_DNS); |     Curl_share_unlock(data, CURL_LOCK_DATA_DNS); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -734,22 +745,23 @@ static int hostcache_inuse(void *data, void *hc) | |||||||
|   return 1; /* free all entries */ |   return 1; /* free all entries */ | ||||||
| } | } | ||||||
|  |  | ||||||
| void Curl_hostcache_clean(struct SessionHandle *data) | /* | ||||||
|  |  * Curl_hostcache_clean() | ||||||
|  |  * | ||||||
|  |  * This _can_ be called with 'data' == NULL but then of course no locking | ||||||
|  |  * can be done! | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | void Curl_hostcache_clean(struct SessionHandle *data, | ||||||
|  |                           struct curl_hash *hash) | ||||||
| { | { | ||||||
|   /* Entries added to the hostcache with the CURLOPT_RESOLVE function are |   /* Entries added to the hostcache with the CURLOPT_RESOLVE function are | ||||||
|    * still present in the cache with the inuse counter set to 1. Detect them |    * still present in the cache with the inuse counter set to 1. Detect them | ||||||
|    * and cleanup! |    * and cleanup! | ||||||
|    */ |    */ | ||||||
|   Curl_hash_clean_with_criterium(data->dns.hostcache, data, hostcache_inuse); |   Curl_hash_clean_with_criterium(hash, data, hostcache_inuse); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Curl_hostcache_destroy(struct SessionHandle *data) |  | ||||||
| { |  | ||||||
|   Curl_hostcache_clean(data); |  | ||||||
|   Curl_hash_destroy(data->dns.hostcache); |  | ||||||
|   data->dns.hostcachetype = HCACHE_NONE; |  | ||||||
|   data->dns.hostcache = NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| CURLcode Curl_loadhostpairs(struct SessionHandle *data) | CURLcode Curl_loadhostpairs(struct SessionHandle *data) | ||||||
| { | { | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								lib/hostip.h
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								lib/hostip.h
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -200,10 +200,31 @@ extern sigjmp_buf curl_jmpenv; | |||||||
|  */ |  */ | ||||||
| CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers); | 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 | ||||||
|  |  */ | ||||||
|  | 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 | ||||||
|  |  */ | ||||||
|  | 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 | ||||||
|  |  */ | ||||||
|  | CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data, | ||||||
|  |                                 const char *local_ip6); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Clean off entries from the cache |  * Clean off entries from the cache | ||||||
|  */ |  */ | ||||||
| void Curl_hostcache_clean(struct SessionHandle *data); | void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Destroy the hostcache of this handle. |  * Destroy the hostcache of this handle. | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -140,7 +140,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, | |||||||
| #if defined(HAVE_GETADDRINFO_THREADSAFE) | #if defined(HAVE_GETADDRINFO_THREADSAFE) | ||||||
|   else { |   else { | ||||||
|     struct addrinfo hints; |     struct addrinfo hints; | ||||||
|     char sbuf[NI_MAXSERV]; |     char sbuf[12]; | ||||||
|     char *sbufptr = NULL; |     char *sbufptr = NULL; | ||||||
|  |  | ||||||
|     memset(&hints, 0, sizeof(hints)); |     memset(&hints, 0, sizeof(hints)); | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -168,7 +168,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, | |||||||
|   struct addrinfo hints; |   struct addrinfo hints; | ||||||
|   Curl_addrinfo *res; |   Curl_addrinfo *res; | ||||||
|   int error; |   int error; | ||||||
|   char sbuf[NI_MAXSERV]; |   char sbuf[12]; | ||||||
|   char *sbufptr = NULL; |   char *sbufptr = NULL; | ||||||
|   char addrbuf[128]; |   char addrbuf[128]; | ||||||
|   int pf; |   int pf; | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -72,4 +72,40 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data, | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Function provided by the resolver backend to set | ||||||
|  |  * outgoing interface to use for DNS requests | ||||||
|  |  */ | ||||||
|  | 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 | ||||||
|  |  */ | ||||||
|  | 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 | ||||||
|  |  */ | ||||||
|  | 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 */ | #endif /* truly sync */ | ||||||
|   | |||||||
							
								
								
									
										171
									
								
								lib/http.c
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								lib/http.c
									
									
									
									
									
								
							| @@ -75,6 +75,7 @@ | |||||||
| #include "non-ascii.h" | #include "non-ascii.h" | ||||||
| #include "bundles.h" | #include "bundles.h" | ||||||
| #include "pipeline.h" | #include "pipeline.h" | ||||||
|  | #include "http2.h" | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
| @@ -105,7 +106,7 @@ static int https_getsock(struct connectdata *conn, | |||||||
|  */ |  */ | ||||||
| const struct Curl_handler Curl_handler_http = { | const struct Curl_handler Curl_handler_http = { | ||||||
|   "HTTP",                               /* scheme */ |   "HTTP",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -129,7 +130,7 @@ const struct Curl_handler Curl_handler_http = { | |||||||
|  */ |  */ | ||||||
| const struct Curl_handler Curl_handler_https = { | const struct Curl_handler Curl_handler_https = { | ||||||
|   "HTTPS",                              /* scheme */ |   "HTTPS",                              /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -149,6 +150,19 @@ const struct Curl_handler Curl_handler_https = { | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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 |  * checkheaders() checks the linked list of custom HTTP headers for a | ||||||
|  * particular header (prefix). |  * particular header (prefix). | ||||||
| @@ -173,25 +187,25 @@ char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader) | |||||||
|  * case of allocation failure. Returns an empty string if the header value |  * case of allocation failure. Returns an empty string if the header value | ||||||
|  * consists entirely of whitespace. |  * consists entirely of whitespace. | ||||||
|  */ |  */ | ||||||
| static char *copy_header_value(const char *h) | char *Curl_copy_header_value(const char *header) | ||||||
| { | { | ||||||
|   const char *start; |   const char *start; | ||||||
|   const char *end; |   const char *end; | ||||||
|   char *value; |   char *value; | ||||||
|   size_t len; |   size_t len; | ||||||
|  |  | ||||||
|   DEBUGASSERT(h); |   DEBUGASSERT(header); | ||||||
|  |  | ||||||
|   /* Find the end of the header name */ |   /* Find the end of the header name */ | ||||||
|   while(*h && (*h != ':')) |   while(*header && (*header != ':')) | ||||||
|     ++h; |     ++header; | ||||||
|  |  | ||||||
|   if(*h) |   if(*header) | ||||||
|     /* Skip over colon */ |     /* Skip over colon */ | ||||||
|     ++h; |     ++header; | ||||||
|  |  | ||||||
|   /* Find the first non-space letter */ |   /* Find the first non-space letter */ | ||||||
|   start = h; |   start = header; | ||||||
|   while(*start && ISSPACE(*start)) |   while(*start && ISSPACE(*start)) | ||||||
|     start++; |     start++; | ||||||
|  |  | ||||||
| @@ -210,7 +224,7 @@ static char *copy_header_value(const char *h) | |||||||
|     end--; |     end--; | ||||||
|  |  | ||||||
|   /* get length of the type */ |   /* get length of the type */ | ||||||
|   len = end-start+1; |   len = end - start + 1; | ||||||
|  |  | ||||||
|   value = malloc(len + 1); |   value = malloc(len + 1); | ||||||
|   if(!value) |   if(!value) | ||||||
| @@ -330,7 +344,7 @@ static bool pickoneauth(struct auth *pick) | |||||||
| static CURLcode http_perhapsrewind(struct connectdata *conn) | static CURLcode http_perhapsrewind(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct HTTP *http = data->state.proto.http; |   struct HTTP *http = data->req.protop; | ||||||
|   curl_off_t bytessent; |   curl_off_t bytessent; | ||||||
|   curl_off_t expectsend = -1; /* default is unknown */ |   curl_off_t expectsend = -1; /* default is unknown */ | ||||||
|  |  | ||||||
| @@ -685,9 +699,8 @@ Curl_http_output_auth(struct connectdata *conn, | |||||||
|  * proxy CONNECT loop. |  * proxy CONNECT loop. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| CURLcode Curl_http_input_auth(struct connectdata *conn, | CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, | ||||||
|                               int httpcode, |                               const char *auth) /* the first non-space */ | ||||||
|                               const char *header) /* the first non-space */ |  | ||||||
| { | { | ||||||
|   /* |   /* | ||||||
|    * This resource requires authentication |    * This resource requires authentication | ||||||
| @@ -695,24 +708,17 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|  |  | ||||||
|   unsigned long *availp; |   unsigned long *availp; | ||||||
|   const char *start; |  | ||||||
|   struct auth *authp; |   struct auth *authp; | ||||||
|  |  | ||||||
|   if(httpcode == 407) { |   if(proxy) { | ||||||
|     start = header+strlen("Proxy-authenticate:"); |  | ||||||
|     availp = &data->info.proxyauthavail; |     availp = &data->info.proxyauthavail; | ||||||
|     authp = &data->state.authproxy; |     authp = &data->state.authproxy; | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     start = header+strlen("WWW-Authenticate:"); |  | ||||||
|     availp = &data->info.httpauthavail; |     availp = &data->info.httpauthavail; | ||||||
|     authp = &data->state.authhost; |     authp = &data->state.authhost; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* pass all white spaces */ |  | ||||||
|   while(*start && ISSPACE(*start)) |  | ||||||
|     start++; |  | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|    * Here we check if we want the specific single authentication (using ==) and |    * Here we check if we want the specific single authentication (using ==) and | ||||||
|    * if we do, we initiate usage of it. |    * if we do, we initiate usage of it. | ||||||
| @@ -730,10 +736,10 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|    * |    * | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|   while(*start) { |   while(*auth) { | ||||||
| #ifdef USE_HTTP_NEGOTIATE | #ifdef USE_HTTP_NEGOTIATE | ||||||
|     if(checkprefix("GSS-Negotiate", start) || |     if(checkprefix("GSS-Negotiate", auth) || | ||||||
|        checkprefix("Negotiate", start)) { |        checkprefix("Negotiate", auth)) { | ||||||
|       int neg; |       int neg; | ||||||
|       *availp |= CURLAUTH_GSSNEGOTIATE; |       *availp |= CURLAUTH_GSSNEGOTIATE; | ||||||
|       authp->avail |= CURLAUTH_GSSNEGOTIATE; |       authp->avail |= CURLAUTH_GSSNEGOTIATE; | ||||||
| @@ -746,7 +752,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|           data->state.authproblem = TRUE; |           data->state.authproblem = TRUE; | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|           neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); |           neg = Curl_input_negotiate(conn, proxy, auth); | ||||||
|           if(neg == 0) { |           if(neg == 0) { | ||||||
|             DEBUGASSERT(!data->req.newurl); |             DEBUGASSERT(!data->req.newurl); | ||||||
|             data->req.newurl = strdup(data->change.url); |             data->req.newurl = strdup(data->change.url); | ||||||
| @@ -765,14 +771,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
| #endif | #endif | ||||||
| #ifdef USE_NTLM | #ifdef USE_NTLM | ||||||
|       /* NTLM support requires the SSL crypto libs */ |       /* NTLM support requires the SSL crypto libs */ | ||||||
|       if(checkprefix("NTLM", start)) { |       if(checkprefix("NTLM", auth)) { | ||||||
|         *availp |= CURLAUTH_NTLM; |         *availp |= CURLAUTH_NTLM; | ||||||
|         authp->avail |= CURLAUTH_NTLM; |         authp->avail |= CURLAUTH_NTLM; | ||||||
|         if(authp->picked == CURLAUTH_NTLM || |         if(authp->picked == CURLAUTH_NTLM || | ||||||
|            authp->picked == CURLAUTH_NTLM_WB) { |            authp->picked == CURLAUTH_NTLM_WB) { | ||||||
|           /* NTLM authentication is picked and activated */ |           /* NTLM authentication is picked and activated */ | ||||||
|           CURLcode ntlm = |           CURLcode ntlm = | ||||||
|             Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start); |             Curl_input_ntlm(conn, proxy, auth); | ||||||
|           if(CURLE_OK == ntlm) { |           if(CURLE_OK == ntlm) { | ||||||
|             data->state.authproblem = FALSE; |             data->state.authproblem = FALSE; | ||||||
| #ifdef NTLM_WB_ENABLED | #ifdef NTLM_WB_ENABLED | ||||||
| @@ -784,14 +790,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|  |  | ||||||
|               /* Get the challenge-message which will be passed to |               /* Get the challenge-message which will be passed to | ||||||
|                * ntlm_auth for generating the type 3 message later */ |                * ntlm_auth for generating the type 3 message later */ | ||||||
|               while(*start && ISSPACE(*start)) |               while(*auth && ISSPACE(*auth)) | ||||||
|                 start++; |                 auth++; | ||||||
|               if(checkprefix("NTLM", start)) { |               if(checkprefix("NTLM", auth)) { | ||||||
|                 start += strlen("NTLM"); |                 auth += strlen("NTLM"); | ||||||
|                 while(*start && ISSPACE(*start)) |                 while(*auth && ISSPACE(*auth)) | ||||||
|                   start++; |                   auth++; | ||||||
|                 if(*start) |                 if(*auth) | ||||||
|                   if((conn->challenge_header = strdup(start)) == NULL) |                   if((conn->challenge_header = strdup(auth)) == NULL) | ||||||
|                     return CURLE_OUT_OF_MEMORY; |                     return CURLE_OUT_OF_MEMORY; | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
| @@ -806,7 +812,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|       else |       else | ||||||
| #endif | #endif | ||||||
| #ifndef CURL_DISABLE_CRYPTO_AUTH | #ifndef CURL_DISABLE_CRYPTO_AUTH | ||||||
|         if(checkprefix("Digest", start)) { |         if(checkprefix("Digest", auth)) { | ||||||
|           if((authp->avail & CURLAUTH_DIGEST) != 0) { |           if((authp->avail & CURLAUTH_DIGEST) != 0) { | ||||||
|             infof(data, "Ignoring duplicate digest auth header.\n"); |             infof(data, "Ignoring duplicate digest auth header.\n"); | ||||||
|           } |           } | ||||||
| @@ -819,7 +825,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|              * authentication isn't activated yet, as we need to store the |              * authentication isn't activated yet, as we need to store the | ||||||
|              * incoming data from this header in case we are gonna use |              * incoming data from this header in case we are gonna use | ||||||
|              * Digest. */ |              * Digest. */ | ||||||
|             dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start); |             dig = Curl_input_digest(conn, proxy, auth); | ||||||
|  |  | ||||||
|             if(CURLDIGEST_FINE != dig) { |             if(CURLDIGEST_FINE != dig) { | ||||||
|               infof(data, "Authentication problem. Ignoring this.\n"); |               infof(data, "Authentication problem. Ignoring this.\n"); | ||||||
| @@ -829,7 +835,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|         } |         } | ||||||
|         else |         else | ||||||
| #endif | #endif | ||||||
|           if(checkprefix("Basic", start)) { |           if(checkprefix("Basic", auth)) { | ||||||
|             *availp |= CURLAUTH_BASIC; |             *availp |= CURLAUTH_BASIC; | ||||||
|             authp->avail |= CURLAUTH_BASIC; |             authp->avail |= CURLAUTH_BASIC; | ||||||
|             if(authp->picked == CURLAUTH_BASIC) { |             if(authp->picked == CURLAUTH_BASIC) { | ||||||
| @@ -843,12 +849,12 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|           } |           } | ||||||
|  |  | ||||||
|     /* there may be multiple methods on one line, so keep reading */ |     /* there may be multiple methods on one line, so keep reading */ | ||||||
|     while(*start && *start != ',') /* read up to the next comma */ |     while(*auth && *auth != ',') /* read up to the next comma */ | ||||||
|       start++; |       auth++; | ||||||
|     if(*start == ',') /* if we're on a comma, skip it */ |     if(*auth == ',') /* if we're on a comma, skip it */ | ||||||
|       start++; |       auth++; | ||||||
|     while(*start && ISSPACE(*start)) |     while(*auth && ISSPACE(*auth)) | ||||||
|       start++; |       auth++; | ||||||
|   } |   } | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
| @@ -948,7 +954,7 @@ static size_t readmoredata(char *buffer, | |||||||
|                            void *userp) |                            void *userp) | ||||||
| { | { | ||||||
|   struct connectdata *conn = (struct connectdata *)userp; |   struct connectdata *conn = (struct connectdata *)userp; | ||||||
|   struct HTTP *http = conn->data->state.proto.http; |   struct HTTP *http = conn->data->req.protop; | ||||||
|   size_t fullsize = size * nitems; |   size_t fullsize = size * nitems; | ||||||
|  |  | ||||||
|   if(0 == http->postsize) |   if(0 == http->postsize) | ||||||
| @@ -1019,7 +1025,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, | |||||||
|   CURLcode res; |   CURLcode res; | ||||||
|   char *ptr; |   char *ptr; | ||||||
|   size_t size; |   size_t size; | ||||||
|   struct HTTP *http = conn->data->state.proto.http; |   struct HTTP *http = conn->data->req.protop; | ||||||
|   size_t sendsize; |   size_t sendsize; | ||||||
|   curl_socket_t sockfd; |   curl_socket_t sockfd; | ||||||
|   size_t headersize; |   size_t headersize; | ||||||
| @@ -1402,7 +1408,7 @@ CURLcode Curl_http_done(struct connectdata *conn, | |||||||
|                         CURLcode status, bool premature) |                         CURLcode status, bool premature) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct HTTP *http =data->state.proto.http; |   struct HTTP *http =data->req.protop; | ||||||
|  |  | ||||||
|   Curl_unencode_cleanup(conn); |   Curl_unencode_cleanup(conn); | ||||||
|  |  | ||||||
| @@ -1442,6 +1448,7 @@ CURLcode Curl_http_done(struct connectdata *conn, | |||||||
|   if(!premature && /* this check is pointless when DONE is called before the |   if(!premature && /* this check is pointless when DONE is called before the | ||||||
|                       entire operation is complete */ |                       entire operation is complete */ | ||||||
|      !conn->bits.retry && |      !conn->bits.retry && | ||||||
|  |      !data->set.connect_only && | ||||||
|      ((http->readbytecount + |      ((http->readbytecount + | ||||||
|        data->req.headerbytecount - |        data->req.headerbytecount - | ||||||
|        data->req.deductheadercount)) <= 0) { |        data->req.deductheadercount)) <= 0) { | ||||||
| @@ -1456,14 +1463,19 @@ CURLcode Curl_http_done(struct connectdata *conn, | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it | /* | ||||||
|    are if the user specifically requested HTTP 1.0, if the server we are |  * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons | ||||||
|    connected to only supports 1.0, or if any server previously contacted to |  * to avoid it include: | ||||||
|    handle this request only supports 1.0. */ |  * | ||||||
| static bool use_http_1_1(const struct SessionHandle *data, |  * - if the user specifically requested HTTP 1.0 | ||||||
|                          const struct connectdata *conn) |  * - 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) || |   return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) || | ||||||
|          ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && |          ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && | ||||||
|           ((conn->httpversion == 11) || |           ((conn->httpversion == 11) || | ||||||
|            ((conn->httpversion != 10) && |            ((conn->httpversion != 10) && | ||||||
| @@ -1479,7 +1491,7 @@ static CURLcode expect100(struct SessionHandle *data, | |||||||
|   const char *ptr; |   const char *ptr; | ||||||
|   data->state.expect100header = FALSE; /* default to false unless it is set |   data->state.expect100header = FALSE; /* default to false unless it is set | ||||||
|                                           to TRUE below */ |                                           to TRUE below */ | ||||||
|   if(use_http_1_1(data, conn)) { |   if(use_http_1_1plus(data, conn)) { | ||||||
|     /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: |     /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: | ||||||
|        100-continue to the headers which actually speeds up post operations |        100-continue to the headers which actually speeds up post operations | ||||||
|        (as there is one packet coming back from the web server) */ |        (as there is one packet coming back from the web server) */ | ||||||
| @@ -1655,20 +1667,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|      the rest of the request in the PERFORM phase. */ |      the rest of the request in the PERFORM phase. */ | ||||||
|   *done = TRUE; |   *done = TRUE; | ||||||
|  |  | ||||||
|   /* If there already is a protocol-specific struct allocated for this |   http = data->req.protop; | ||||||
|      sessionhandle, deal with it */ |  | ||||||
|   Curl_reset_reqproto(conn); |  | ||||||
|  |  | ||||||
|   if(!data->state.proto.http) { |  | ||||||
|     /* Only allocate this struct if we don't already have it! */ |  | ||||||
|  |  | ||||||
|     http = calloc(1, sizeof(struct HTTP)); |  | ||||||
|     if(!http) |  | ||||||
|       return CURLE_OUT_OF_MEMORY; |  | ||||||
|     data->state.proto.http = http; |  | ||||||
|   } |  | ||||||
|   else |  | ||||||
|     http = data->state.proto.http; |  | ||||||
|  |  | ||||||
|   if(!data->state.this_is_a_follow) { |   if(!data->state.this_is_a_follow) { | ||||||
|     /* this is not a followed location, get the original host name */ |     /* this is not a followed location, get the original host name */ | ||||||
| @@ -1795,7 +1794,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|       if(conn->bits.authneg) |       if(conn->bits.authneg) | ||||||
|         /* don't enable chunked during auth neg */ |         /* don't enable chunked during auth neg */ | ||||||
|         ; |         ; | ||||||
|       else if(use_http_1_1(data, conn)) { |       else if(use_http_1_1plus(data, conn)) { | ||||||
|         /* HTTP, upload, unknown file size and not HTTP 1.0 */ |         /* HTTP, upload, unknown file size and not HTTP 1.0 */ | ||||||
|         data->req.upload_chunky = TRUE; |         data->req.upload_chunky = TRUE; | ||||||
|       } |       } | ||||||
| @@ -1824,7 +1823,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|        custom Host: header if this is NOT a redirect, as setting Host: in 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 |        redirected request is being out on thin ice. Except if the host name | ||||||
|        is the same as the first one! */ |        is the same as the first one! */ | ||||||
|     char *cookiehost = copy_header_value(ptr); |     char *cookiehost = Curl_copy_header_value(ptr); | ||||||
|     if(!cookiehost) |     if(!cookiehost) | ||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
|     if(!*cookiehost) |     if(!*cookiehost) | ||||||
| @@ -2095,7 +2094,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   /* Use 1.1 unless the user specifically asked for 1.0 or the server only |   /* Use 1.1 unless the user specifically asked for 1.0 or the server only | ||||||
|      supports 1.0 */ |      supports 1.0 */ | ||||||
|   httpstring= use_http_1_1(data, conn)?"1.1":"1.0"; |   httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0"; | ||||||
|  |  | ||||||
|   /* initialize a dynamic send-buffer */ |   /* initialize a dynamic send-buffer */ | ||||||
|   req_buffer = Curl_add_buffer_init(); |   req_buffer = Curl_add_buffer_init(); | ||||||
| @@ -2173,6 +2172,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|   if(result) |   if(result) | ||||||
|     return result; |     return result; | ||||||
|  |  | ||||||
|  |   if(!(conn->handler->flags&PROTOPT_SSL) && | ||||||
|  |      (data->set.httpversion == CURL_HTTP_VERSION_2_0)) { | ||||||
|  |     /* append HTTP2 updrade magic stuff to the HTTP request if it isn't done | ||||||
|  |        over SSL */ | ||||||
|  |     result = Curl_http2_request(req_buffer, conn); | ||||||
|  |     if(result) | ||||||
|  |       return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
| #if !defined(CURL_DISABLE_COOKIES) | #if !defined(CURL_DISABLE_COOKIES) | ||||||
|   if(data->cookies || addcookies) { |   if(data->cookies || addcookies) { | ||||||
|     struct Cookie *co=NULL; /* no cookies from start */ |     struct Cookie *co=NULL; /* no cookies from start */ | ||||||
| @@ -3231,7 +3239,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, | |||||||
|     } |     } | ||||||
|     /* check for Content-Type: header lines to get the MIME-type */ |     /* check for Content-Type: header lines to get the MIME-type */ | ||||||
|     else if(checkprefix("Content-Type:", k->p)) { |     else if(checkprefix("Content-Type:", k->p)) { | ||||||
|       char *contenttype = copy_header_value(k->p); |       char *contenttype = Curl_copy_header_value(k->p); | ||||||
|       if(!contenttype) |       if(!contenttype) | ||||||
|         return CURLE_OUT_OF_MEMORY; |         return CURLE_OUT_OF_MEMORY; | ||||||
|       if(!*contenttype) |       if(!*contenttype) | ||||||
| @@ -3243,7 +3251,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     else if(checkprefix("Server:", k->p)) { |     else if(checkprefix("Server:", k->p)) { | ||||||
|       char *server_name = copy_header_value(k->p); |       char *server_name = Curl_copy_header_value(k->p); | ||||||
|  |  | ||||||
|       /* Turn off pipelining if the server version is blacklisted */ |       /* Turn off pipelining if the server version is blacklisted */ | ||||||
|       if(conn->bundle && conn->bundle->server_supports_pipelining) { |       if(conn->bundle && conn->bundle->server_supports_pipelining) { | ||||||
| @@ -3439,7 +3447,16 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, | |||||||
|              (401 == k->httpcode)) || |              (401 == k->httpcode)) || | ||||||
|             (checkprefix("Proxy-authenticate:", k->p) && |             (checkprefix("Proxy-authenticate:", k->p) && | ||||||
|              (407 == k->httpcode))) { |              (407 == k->httpcode))) { | ||||||
|       result = Curl_http_input_auth(conn, k->httpcode, k->p); |  | ||||||
|  |       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); | ||||||
|  |  | ||||||
|  |       Curl_safefree(auth); | ||||||
|  |  | ||||||
|       if(result) |       if(result) | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| @@ -3447,7 +3464,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, | |||||||
|             checkprefix("Location:", k->p) && |             checkprefix("Location:", k->p) && | ||||||
|             !data->req.location) { |             !data->req.location) { | ||||||
|       /* this is the URL that the server advises us to use instead */ |       /* this is the URL that the server advises us to use instead */ | ||||||
|       char *location = copy_header_value(k->p); |       char *location = Curl_copy_header_value(k->p); | ||||||
|       if(!location) |       if(!location) | ||||||
|         return CURLE_OUT_OF_MEMORY; |         return CURLE_OUT_OF_MEMORY; | ||||||
|       if(!*location) |       if(!*location) | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								lib/http.h
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								lib/http.h
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -21,19 +21,26 @@ | |||||||
|  * KIND, either express or implied. |  * KIND, either express or implied. | ||||||
|  * |  * | ||||||
|  ***************************************************************************/ |  ***************************************************************************/ | ||||||
|  | #include "curl_setup.h" | ||||||
|  |  | ||||||
| #ifndef CURL_DISABLE_HTTP | #ifndef CURL_DISABLE_HTTP | ||||||
|  |  | ||||||
|  | #ifdef USE_NGHTTP2 | ||||||
|  | #include <nghttp2/nghttp2.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| extern const struct Curl_handler Curl_handler_http; | extern const struct Curl_handler Curl_handler_http; | ||||||
|  |  | ||||||
| #ifdef USE_SSL | #ifdef USE_SSL | ||||||
| extern const struct Curl_handler Curl_handler_https; | extern const struct Curl_handler Curl_handler_https; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* Header specific functions */ | ||||||
| bool Curl_compareheader(const char *headerline,  /* line to check */ | bool Curl_compareheader(const char *headerline,  /* line to check */ | ||||||
|                         const char *header,   /* header keyword _with_ colon */ |                         const char *header,   /* header keyword _with_ colon */ | ||||||
|                         const char *content); /* content string to find */ |                         const char *content); /* content string to find */ | ||||||
|  |  | ||||||
| char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader); | char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader); | ||||||
|  | char *Curl_copy_header_value(const char *header); | ||||||
|  |  | ||||||
| /* ------------------------------------------------------------------------- */ | /* ------------------------------------------------------------------------- */ | ||||||
| /* | /* | ||||||
| @@ -66,6 +73,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, | |||||||
| CURLcode Curl_http(struct connectdata *conn, bool *done); | CURLcode Curl_http(struct connectdata *conn, bool *done); | ||||||
| CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); | CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); | ||||||
| CURLcode Curl_http_connect(struct connectdata *conn, bool *done); | CURLcode Curl_http_connect(struct connectdata *conn, bool *done); | ||||||
|  | CURLcode Curl_http_setup_conn(struct connectdata *conn); | ||||||
|  |  | ||||||
| /* The following functions are defined in http_chunks.c */ | /* The following functions are defined in http_chunks.c */ | ||||||
| void Curl_httpchunk_init(struct connectdata *conn); | void Curl_httpchunk_init(struct connectdata *conn); | ||||||
| @@ -74,8 +82,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, | |||||||
|  |  | ||||||
| /* These functions are in http.c */ | /* These functions are in http.c */ | ||||||
| void Curl_http_auth_stage(struct SessionHandle *data, int stage); | void Curl_http_auth_stage(struct SessionHandle *data, int stage); | ||||||
| CURLcode Curl_http_input_auth(struct connectdata *conn, | CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, | ||||||
|                               int httpcode, const char *header); |                               const char *auth); | ||||||
| CURLcode Curl_http_auth_act(struct connectdata *conn); | CURLcode Curl_http_auth_act(struct connectdata *conn); | ||||||
| CURLcode Curl_http_perhapsrewind(struct connectdata *conn); | CURLcode Curl_http_perhapsrewind(struct connectdata *conn); | ||||||
|  |  | ||||||
| @@ -141,6 +149,14 @@ struct HTTP { | |||||||
|                         points to an allocated send_buffer struct */ |                         points to an allocated send_buffer struct */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | struct http_conn { | ||||||
|  | #ifdef USE_NGHTTP2 | ||||||
|  |   nghttp2_session *h2; | ||||||
|  | #else | ||||||
|  |   int unused; /* prevent a compiler warning */ | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
| CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, | CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, | ||||||
|                                      struct connectdata *conn, |                                      struct connectdata *conn, | ||||||
|                                      ssize_t *nread, |                                      ssize_t *nread, | ||||||
|   | |||||||
							
								
								
									
										182
									
								
								lib/http2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								lib/http2.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | |||||||
|  | /*************************************************************************** | ||||||
|  |  *                                  _   _ ____  _ | ||||||
|  |  *  Project                     ___| | | |  _ \| | | ||||||
|  |  *                             / __| | | | |_) | | | ||||||
|  |  *                            | (__| |_| |  _ <| |___ | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  |  * This software is licensed as described in the file COPYING, which | ||||||
|  |  * you should have received as part of this distribution. The terms | ||||||
|  |  * are also available at http://curl.haxx.se/docs/copyright.html. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the COPYING file. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "curl_setup.h" | ||||||
|  |  | ||||||
|  | #ifdef USE_NGHTTP2 | ||||||
|  | #define _MPRINTF_REPLACE | ||||||
|  | #include <curl/mprintf.h> | ||||||
|  |  | ||||||
|  | #include <nghttp2/nghttp2.h> | ||||||
|  | #include "urldata.h" | ||||||
|  | #include "http2.h" | ||||||
|  | #include "http.h" | ||||||
|  | #include "sendf.h" | ||||||
|  | #include "curl_base64.h" | ||||||
|  | #include "curl_memory.h" | ||||||
|  |  | ||||||
|  | /* include memdebug.h last */ | ||||||
|  | #include "memdebug.h" | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Store nghttp2 version info in this buffer, Prefix with a space.  Return | ||||||
|  |  * total length written. | ||||||
|  |  */ | ||||||
|  | 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; | ||||||
|  |   ssize_t written; | ||||||
|  |   CURLcode rc = | ||||||
|  |     Curl_write(conn, conn->sock[0], data, length, &written); | ||||||
|  |   (void)h2; | ||||||
|  |   (void)flags; | ||||||
|  |  | ||||||
|  |   if(rc) { | ||||||
|  |     failf(conn->data, "Failed sending HTTP2 data"); | ||||||
|  |     return NGHTTP2_ERR_CALLBACK_FAILURE; | ||||||
|  |   } | ||||||
|  |   else if(!written) | ||||||
|  |     return NGHTTP2_ERR_WOULDBLOCK; | ||||||
|  |  | ||||||
|  |   return written; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * The implementation of nghttp2_recv_callback type. Here we read data from | ||||||
|  |  * the network and write them in |buf|. The capacity of |buf| is |length| | ||||||
|  |  * bytes. Returns the number of bytes stored in |buf|. See the documentation | ||||||
|  |  * of nghttp2_recv_callback for the details. | ||||||
|  |  */ | ||||||
|  | static ssize_t recv_callback(nghttp2_session *h2, | ||||||
|  |                              uint8_t *buf, size_t length, int flags, | ||||||
|  |                              void *userp) | ||||||
|  | { | ||||||
|  |   struct connectdata *conn = (struct connectdata *)userp; | ||||||
|  |   ssize_t nread; | ||||||
|  |   CURLcode rc = Curl_read(conn, conn->sock[0], (char *)buf, length, &nread); | ||||||
|  |   (void)h2; | ||||||
|  |   (void)flags; | ||||||
|  |  | ||||||
|  |   if(rc) { | ||||||
|  |     failf(conn->data, "Failed recving HTTP2 data"); | ||||||
|  |     return NGHTTP2_ERR_CALLBACK_FAILURE; | ||||||
|  |   } | ||||||
|  |   if(!nread) | ||||||
|  |     return NGHTTP2_ERR_WOULDBLOCK; | ||||||
|  |  | ||||||
|  |   return nread; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This is all callbacks nghttp2 calls | ||||||
|  |  */ | ||||||
|  | static const nghttp2_session_callbacks callbacks = { | ||||||
|  |   send_callback, | ||||||
|  |   recv_callback, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL, | ||||||
|  |   NULL | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * 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 }, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Append headers to ask for a HTTP1.1 to HTTP2 upgrade. | ||||||
|  |  */ | ||||||
|  | CURLcode Curl_http2_request(Curl_send_buffer *req, | ||||||
|  |                             struct connectdata *conn) | ||||||
|  | { | ||||||
|  |   uint8_t binsettings[80]; | ||||||
|  |   CURLcode result; | ||||||
|  |   ssize_t binlen; | ||||||
|  |   char *base64; | ||||||
|  |   size_t blen; | ||||||
|  |  | ||||||
|  |   if(!conn->proto.httpc.h2) { | ||||||
|  |     /* The nghttp2 session is not yet setup, do it */ | ||||||
|  |     int rc = nghttp2_session_client_new(&conn->proto.httpc.h2, | ||||||
|  |                                         &callbacks, &conn); | ||||||
|  |     if(rc) { | ||||||
|  |       failf(conn->data, "Couldn't initialize nghttp2!"); | ||||||
|  |       return CURLE_OUT_OF_MEMORY; /* most likely at least */ | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* 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, | ||||||
|  |                                          sizeof(binsettings), | ||||||
|  |                                          settings, | ||||||
|  |                                          sizeof(settings)/sizeof(settings[0])); | ||||||
|  |   if(!binlen) { | ||||||
|  |     failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); | ||||||
|  |     return CURLE_FAILED_INIT; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   result = Curl_base64_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_PROTO_VERSION_ID, base64); | ||||||
|  |   free(base64); | ||||||
|  |  | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | #ifndef HEADER_CURL_HTTP2_H | ||||||
|  | #define HEADER_CURL_HTTP2_H | ||||||
| /***************************************************************************
 | /***************************************************************************
 | ||||||
|  *                                  _   _ ____  _ |  *                                  _   _ ____  _ | ||||||
|  *  Project                     ___| | | |  _ \| | |  *  Project                     ___| | | |  _ \| | | ||||||
| @@ -5,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * This software is licensed as described in the file COPYING, which |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -22,40 +24,19 @@ | |||||||
| 
 | 
 | ||||||
| #include "curl_setup.h" | #include "curl_setup.h" | ||||||
| 
 | 
 | ||||||
| #include <curl/curl.h> | #ifdef USE_NGHTTP2 | ||||||
|  | #include "http.h" | ||||||
|  | /*
 | ||||||
|  |  * Store nghttp2 version info in this buffer, Prefix with a space.  Return | ||||||
|  |  * total length written. | ||||||
|  |  */ | ||||||
|  | int Curl_http2_ver(char *p, size_t len); | ||||||
| 
 | 
 | ||||||
| #include "curl_rand.h" | CURLcode Curl_http2_request(Curl_send_buffer *req, | ||||||
|  |                             struct connectdata *conn); | ||||||
|  | #else /* USE_NGHTTP2 */ | ||||||
|  | #define Curl_http2_request(x,y) CURLE_OK | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #endif /* HEADER_CURL_HTTP2_H */ | ||||||
| #include <curl/mprintf.h> |  | ||||||
| 
 |  | ||||||
| #include "curl_memory.h" |  | ||||||
| /* The last #include file should be: */ |  | ||||||
| #include "memdebug.h" |  | ||||||
| 
 |  | ||||||
| /* Private pseudo-random number seed. Unsigned integer >= 32bit. Threads
 |  | ||||||
|    mutual exclusion is not implemented to acess it since we do not require |  | ||||||
|    high quality random numbers (only used in form boudary generation). */ |  | ||||||
| 
 |  | ||||||
| static unsigned int randseed; |  | ||||||
| 
 |  | ||||||
| /* Pseudo-random number support. */ |  | ||||||
| 
 |  | ||||||
| unsigned int Curl_rand(void) |  | ||||||
| { |  | ||||||
|   unsigned int r; |  | ||||||
|   /* Return an unsigned 32-bit pseudo-random number. */ |  | ||||||
|   r = randseed = randseed * 1103515245 + 12345; |  | ||||||
|   return (r << 16) | ((r >> 16) & 0xFFFF); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Curl_srand(void) |  | ||||||
| { |  | ||||||
|   /* Randomize pseudo-random number sequence. */ |  | ||||||
| 
 |  | ||||||
|   randseed = (unsigned int) time(NULL); |  | ||||||
|   Curl_rand(); |  | ||||||
|   Curl_rand(); |  | ||||||
|   Curl_rand(); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| @@ -25,14 +25,13 @@ | |||||||
| #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) | #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) | ||||||
|  |  | ||||||
| #include "urldata.h" | #include "urldata.h" | ||||||
| #include "sendf.h" |  | ||||||
| #include "rawstr.h" | #include "rawstr.h" | ||||||
| #include "curl_base64.h" | #include "curl_base64.h" | ||||||
| #include "curl_md5.h" | #include "curl_md5.h" | ||||||
| #include "http_digest.h" | #include "http_digest.h" | ||||||
| #include "strtok.h" | #include "strtok.h" | ||||||
| #include "url.h" /* for Curl_safefree() */ |  | ||||||
| #include "curl_memory.h" | #include "curl_memory.h" | ||||||
|  | #include "sslgen.h" /* for Curl_rand() */ | ||||||
| #include "non-ascii.h" /* included for Curl_convert_... prototypes */ | #include "non-ascii.h" /* included for Curl_convert_... prototypes */ | ||||||
| #include "warnless.h" | #include "warnless.h" | ||||||
|  |  | ||||||
| @@ -142,10 +141,6 @@ CURLdigest Curl_input_digest(struct connectdata *conn, | |||||||
|     d = &data->state.digest; |     d = &data->state.digest; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* skip initial whitespaces */ |  | ||||||
|   while(*header && ISSPACE(*header)) |  | ||||||
|     header++; |  | ||||||
|  |  | ||||||
|   if(checkprefix("Digest", header)) { |   if(checkprefix("Digest", header)) { | ||||||
|     header += strlen("Digest"); |     header += strlen("Digest"); | ||||||
|  |  | ||||||
| @@ -283,7 +278,7 @@ static char *string_quoted(const char *source) | |||||||
|     ++s; |     ++s; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   dest = (char *)malloc(n); |   dest = malloc(n); | ||||||
|   if(dest) { |   if(dest) { | ||||||
|     s = source; |     s = source; | ||||||
|     d = dest; |     d = dest; | ||||||
| @@ -307,17 +302,16 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|   /* We have a Digest setup for this, use it!  Now, to get all the details for |   /* We have a Digest setup for this, use it!  Now, to get all the details for | ||||||
|      this sorted out, I must urge you dear friend to read up on the RFC2617 |      this sorted out, I must urge you dear friend to read up on the RFC2617 | ||||||
|      section 3.2.2, */ |      section 3.2.2, */ | ||||||
|  |   size_t urilen; | ||||||
|   unsigned char md5buf[16]; /* 16 bytes/128 bits */ |   unsigned char md5buf[16]; /* 16 bytes/128 bits */ | ||||||
|   unsigned char request_digest[33]; |   unsigned char request_digest[33]; | ||||||
|   unsigned char *md5this; |   unsigned char *md5this; | ||||||
|   unsigned char *ha1; |   unsigned char ha1[33];/* 32 digits and 1 zero byte */ | ||||||
|   unsigned char ha2[33];/* 32 digits and 1 zero byte */ |   unsigned char ha2[33];/* 32 digits and 1 zero byte */ | ||||||
|   char cnoncebuf[33]; |   char cnoncebuf[33]; | ||||||
|   char *cnonce = NULL; |   char *cnonce = NULL; | ||||||
|   size_t cnonce_sz = 0; |   size_t cnonce_sz = 0; | ||||||
|   char *tmp = NULL; |   char *tmp = NULL; | ||||||
|   struct timeval now; |  | ||||||
|  |  | ||||||
|   char **allocuserpwd; |   char **allocuserpwd; | ||||||
|   size_t userlen; |   size_t userlen; | ||||||
|   const char *userp; |   const char *userp; | ||||||
| @@ -354,10 +348,7 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|     authp = &data->state.authhost; |     authp = &data->state.authhost; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(*allocuserpwd) { |   Curl_safefree(*allocuserpwd); | ||||||
|     Curl_safefree(*allocuserpwd); |  | ||||||
|     *allocuserpwd = NULL; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* not set means empty */ |   /* not set means empty */ | ||||||
|   if(!userp) |   if(!userp) | ||||||
| @@ -376,10 +367,11 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|     d->nc = 1; |     d->nc = 1; | ||||||
|  |  | ||||||
|   if(!d->cnonce) { |   if(!d->cnonce) { | ||||||
|     /* Generate a cnonce */ |     struct timeval now = Curl_tvnow(); | ||||||
|     now = Curl_tvnow(); |     snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x", | ||||||
|     snprintf(cnoncebuf, sizeof(cnoncebuf), "%32ld", |              Curl_rand(data), Curl_rand(data), | ||||||
|              (long)now.tv_sec + now.tv_usec); |              (unsigned int)now.tv_sec, | ||||||
|  |              (unsigned int)now.tv_usec); | ||||||
|  |  | ||||||
|     rc = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), |     rc = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), | ||||||
|                             &cnonce, &cnonce_sz); |                             &cnonce, &cnonce_sz); | ||||||
| @@ -406,12 +398,7 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|  |  | ||||||
|   CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ |   CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ | ||||||
|   Curl_md5it(md5buf, md5this); |   Curl_md5it(md5buf, md5this); | ||||||
|   free(md5this); /* free this again */ |   Curl_safefree(md5this); | ||||||
|  |  | ||||||
|   ha1 = malloc(33); /* 32 digits and 1 zero byte */ |  | ||||||
|   if(!ha1) |  | ||||||
|     return CURLE_OUT_OF_MEMORY; |  | ||||||
|  |  | ||||||
|   md5_to_ascii(md5buf, ha1); |   md5_to_ascii(md5buf, ha1); | ||||||
|  |  | ||||||
|   if(d->algo == CURLDIGESTALGO_MD5SESS) { |   if(d->algo == CURLDIGESTALGO_MD5SESS) { | ||||||
| @@ -421,7 +408,7 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
|     CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */ |     CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */ | ||||||
|     Curl_md5it(md5buf, (unsigned char *)tmp); |     Curl_md5it(md5buf, (unsigned char *)tmp); | ||||||
|     free(tmp); /* free this again */ |     Curl_safefree(tmp); | ||||||
|     md5_to_ascii(md5buf, ha1); |     md5_to_ascii(md5buf, ha1); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -450,31 +437,29 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|      Further details on Digest implementation differences: |      Further details on Digest implementation differences: | ||||||
|      http://www.fngtps.com/2006/09/http-authentication |      http://www.fngtps.com/2006/09/http-authentication | ||||||
|   */ |   */ | ||||||
|   if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) { |  | ||||||
|     md5this = (unsigned char *)aprintf("%s:%.*s", request, |   if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) | ||||||
|                                        curlx_sztosi(tmp - (char *)uripath), |     urilen = tmp - (char *)uripath; | ||||||
|                                        uripath); |  | ||||||
|   } |  | ||||||
|   else |   else | ||||||
|     md5this = (unsigned char *)aprintf("%s:%s", request, uripath); |     urilen = strlen((char *)uripath); | ||||||
|  |  | ||||||
|  |   md5this = (unsigned char *)aprintf("%s:%.*s", request, urilen, uripath); | ||||||
|  |  | ||||||
|   if(d->qop && Curl_raw_equal(d->qop, "auth-int")) { |   if(d->qop && Curl_raw_equal(d->qop, "auth-int")) { | ||||||
|     /* We don't support auth-int for PUT or POST at the moment. |     /* 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 */ |        TODO: replace md5 of empty string with entity-body for PUT/POST */ | ||||||
|     unsigned char *md5this2 = (unsigned char *) |     unsigned char *md5this2 = (unsigned char *) | ||||||
|       aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e"); |       aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e"); | ||||||
|     free(md5this); |     Curl_safefree(md5this); | ||||||
|     md5this = md5this2; |     md5this = md5this2; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(!md5this) { |   if(!md5this) | ||||||
|     free(ha1); |  | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ |   CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ | ||||||
|   Curl_md5it(md5buf, md5this); |   Curl_md5it(md5buf, md5this); | ||||||
|   free(md5this); /* free this again */ |   Curl_safefree(md5this); | ||||||
|   md5_to_ascii(md5buf, ha2); |   md5_to_ascii(md5buf, ha2); | ||||||
|  |  | ||||||
|   if(d->qop) { |   if(d->qop) { | ||||||
| @@ -492,13 +477,12 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|                                        d->nonce, |                                        d->nonce, | ||||||
|                                        ha2); |                                        ha2); | ||||||
|   } |   } | ||||||
|   free(ha1); |  | ||||||
|   if(!md5this) |   if(!md5this) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ |   CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ | ||||||
|   Curl_md5it(md5buf, md5this); |   Curl_md5it(md5buf, md5this); | ||||||
|   free(md5this); /* free this again */ |   Curl_safefree(md5this); | ||||||
|   md5_to_ascii(md5buf, request_digest); |   md5_to_ascii(md5buf, request_digest); | ||||||
|  |  | ||||||
|   /* for test case 64 (snooped from a Mozilla 1.3a request) |   /* for test case 64 (snooped from a Mozilla 1.3a request) | ||||||
| @@ -515,7 +499,7 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|     chracters. |     chracters. | ||||||
|   */ |   */ | ||||||
|   userp_quoted = string_quoted(userp); |   userp_quoted = string_quoted(userp); | ||||||
|   if(!*userp_quoted) |   if(!userp_quoted) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   if(d->qop) { |   if(d->qop) { | ||||||
| @@ -524,7 +508,7 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|                "username=\"%s\", " |                "username=\"%s\", " | ||||||
|                "realm=\"%s\", " |                "realm=\"%s\", " | ||||||
|                "nonce=\"%s\", " |                "nonce=\"%s\", " | ||||||
|                "uri=\"%s\", " |                "uri=\"%.*s\", " | ||||||
|                "cnonce=\"%s\", " |                "cnonce=\"%s\", " | ||||||
|                "nc=%08x, " |                "nc=%08x, " | ||||||
|                "qop=%s, " |                "qop=%s, " | ||||||
| @@ -533,7 +517,7 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|                userp_quoted, |                userp_quoted, | ||||||
|                d->realm, |                d->realm, | ||||||
|                d->nonce, |                d->nonce, | ||||||
|                uripath, /* this is the PATH part of the URL */ |                urilen, uripath, /* this is the PATH part of the URL */ | ||||||
|                d->cnonce, |                d->cnonce, | ||||||
|                d->nc, |                d->nc, | ||||||
|                d->qop, |                d->qop, | ||||||
| @@ -550,16 +534,16 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|                "username=\"%s\", " |                "username=\"%s\", " | ||||||
|                "realm=\"%s\", " |                "realm=\"%s\", " | ||||||
|                "nonce=\"%s\", " |                "nonce=\"%s\", " | ||||||
|                "uri=\"%s\", " |                "uri=\"%.*s\", " | ||||||
|                "response=\"%s\"", |                "response=\"%s\"", | ||||||
|                proxy?"Proxy-":"", |                proxy?"Proxy-":"", | ||||||
|                userp_quoted, |                userp_quoted, | ||||||
|                d->realm, |                d->realm, | ||||||
|                d->nonce, |                d->nonce, | ||||||
|                uripath, /* this is the PATH part of the URL */ |                urilen, uripath, /* this is the PATH part of the URL */ | ||||||
|                request_digest); |                request_digest); | ||||||
|   } |   } | ||||||
|   free(userp_quoted); |   Curl_safefree(userp_quoted); | ||||||
|   if(!*allocuserpwd) |   if(!*allocuserpwd) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
| @@ -595,29 +579,12 @@ CURLcode Curl_output_digest(struct connectdata *conn, | |||||||
|  |  | ||||||
| static void digest_cleanup_one(struct digestdata *d) | static void digest_cleanup_one(struct digestdata *d) | ||||||
| { | { | ||||||
|   if(d->nonce) |   Curl_safefree(d->nonce); | ||||||
|     free(d->nonce); |   Curl_safefree(d->cnonce); | ||||||
|   d->nonce = NULL; |   Curl_safefree(d->realm); | ||||||
|  |   Curl_safefree(d->opaque); | ||||||
|   if(d->cnonce) |   Curl_safefree(d->qop); | ||||||
|     free(d->cnonce); |   Curl_safefree(d->algorithm); | ||||||
|   d->cnonce = NULL; |  | ||||||
|  |  | ||||||
|   if(d->realm) |  | ||||||
|     free(d->realm); |  | ||||||
|   d->realm = NULL; |  | ||||||
|  |  | ||||||
|   if(d->opaque) |  | ||||||
|     free(d->opaque); |  | ||||||
|   d->opaque = NULL; |  | ||||||
|  |  | ||||||
|   if(d->qop) |  | ||||||
|     free(d->qop); |  | ||||||
|   d->qop = NULL; |  | ||||||
|  |  | ||||||
|   if(d->algorithm) |  | ||||||
|     free(d->algorithm); |  | ||||||
|   d->algorithm = NULL; |  | ||||||
|  |  | ||||||
|   d->nc = 0; |   d->nc = 0; | ||||||
|   d->algo = CURLDIGESTALGO_MD5; /* default algorithm */ |   d->algo = CURLDIGESTALGO_MD5; /* default algorithm */ | ||||||
|   | |||||||
| @@ -145,8 +145,6 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, | |||||||
|   const char* protocol; |   const char* protocol; | ||||||
|   CURLcode error; |   CURLcode error; | ||||||
|  |  | ||||||
|   while(*header && ISSPACE(*header)) |  | ||||||
|     header++; |  | ||||||
|   if(checkprefix("GSS-Negotiate", header)) { |   if(checkprefix("GSS-Negotiate", header)) { | ||||||
|     protocol = "GSS-Negotiate"; |     protocol = "GSS-Negotiate"; | ||||||
|     gss = TRUE; |     gss = TRUE; | ||||||
|   | |||||||
| @@ -98,9 +98,6 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, | |||||||
|   const char* protocol; |   const char* protocol; | ||||||
|   CURLcode error; |   CURLcode error; | ||||||
|  |  | ||||||
|   while(*header && ISSPACE(*header)) |  | ||||||
|     header++; |  | ||||||
|  |  | ||||||
|   if(checkprefix("GSS-Negotiate", header)) { |   if(checkprefix("GSS-Negotiate", header)) { | ||||||
|     protocol = "GSS-Negotiate"; |     protocol = "GSS-Negotiate"; | ||||||
|     gss = TRUE; |     gss = TRUE; | ||||||
|   | |||||||
| @@ -66,13 +66,13 @@ CURLcode Curl_proxy_connect(struct connectdata *conn) | |||||||
|      * This function might be called several times in the multi interface case |      * This function might be called several times in the multi interface case | ||||||
|      * if the proxy's CONNTECT response is not instant. |      * if the proxy's CONNTECT response is not instant. | ||||||
|      */ |      */ | ||||||
|     prot_save = conn->data->state.proto.generic; |     prot_save = conn->data->req.protop; | ||||||
|     memset(&http_proxy, 0, sizeof(http_proxy)); |     memset(&http_proxy, 0, sizeof(http_proxy)); | ||||||
|     conn->data->state.proto.http = &http_proxy; |     conn->data->req.protop = &http_proxy; | ||||||
|     conn->bits.close = FALSE; |     conn->bits.close = FALSE; | ||||||
|     result = Curl_proxyCONNECT(conn, FIRSTSOCKET, |     result = Curl_proxyCONNECT(conn, FIRSTSOCKET, | ||||||
|                                conn->host.name, conn->remote_port); |                                conn->host.name, conn->remote_port); | ||||||
|     conn->data->state.proto.generic = prot_save; |     conn->data->req.protop = prot_save; | ||||||
|     if(CURLE_OK != result) |     if(CURLE_OK != result) | ||||||
|       return result; |       return result; | ||||||
| #else | #else | ||||||
| @@ -452,8 +452,16 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, | |||||||
|                       (401 == k->httpcode)) || |                       (401 == k->httpcode)) || | ||||||
|                      (checkprefix("Proxy-authenticate:", line_start) && |                      (checkprefix("Proxy-authenticate:", line_start) && | ||||||
|                       (407 == k->httpcode))) { |                       (407 == k->httpcode))) { | ||||||
|                     result = Curl_http_input_auth(conn, k->httpcode, |  | ||||||
|                                                   line_start); |                     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); | ||||||
|  |  | ||||||
|  |                     Curl_safefree(auth); | ||||||
|  |  | ||||||
|                     if(result) |                     if(result) | ||||||
|                       return result; |                       return result; | ||||||
|                   } |                   } | ||||||
|   | |||||||
							
								
								
									
										482
									
								
								lib/imap.c
									
									
									
									
									
								
							
							
						
						
									
										482
									
								
								lib/imap.c
									
									
									
									
									
								
							| @@ -26,6 +26,8 @@ | |||||||
|  * RFC4616 PLAIN authentication |  * RFC4616 PLAIN authentication | ||||||
|  * RFC4959 IMAP Extension for SASL Initial Client Response |  * RFC4959 IMAP Extension for SASL Initial Client Response | ||||||
|  * RFC5092 IMAP URL Scheme |  * RFC5092 IMAP URL Scheme | ||||||
|  |  * RFC6749 OAuth 2.0 Authorization Framework | ||||||
|  |  * Draft   LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt> | ||||||
|  * |  * | ||||||
|  ***************************************************************************/ |  ***************************************************************************/ | ||||||
|  |  | ||||||
| @@ -77,6 +79,7 @@ | |||||||
| #include "url.h" | #include "url.h" | ||||||
| #include "rawstr.h" | #include "rawstr.h" | ||||||
| #include "curl_sasl.h" | #include "curl_sasl.h" | ||||||
|  | #include "warnless.h" | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
| @@ -162,7 +165,7 @@ const struct Curl_handler Curl_handler_imaps = { | |||||||
|  |  | ||||||
| static const struct Curl_handler Curl_handler_imap_proxy = { | static const struct Curl_handler Curl_handler_imap_proxy = { | ||||||
|   "IMAP",                               /* scheme */ |   "IMAP",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -187,7 +190,7 @@ static const struct Curl_handler Curl_handler_imap_proxy = { | |||||||
|  |  | ||||||
| static const struct Curl_handler Curl_handler_imaps_proxy = { | static const struct Curl_handler Curl_handler_imaps_proxy = { | ||||||
|   "IMAPS",                              /* scheme */ |   "IMAPS",                              /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -267,7 +270,7 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd) | |||||||
| static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, | static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, | ||||||
|                            int *resp) |                            int *resp) | ||||||
| { | { | ||||||
|   struct IMAP *imap = conn->data->state.proto.imap; |   struct IMAP *imap = conn->data->req.protop; | ||||||
|   struct imap_conn *imapc = &conn->proto.imapc; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   const char *id = imapc->resptag; |   const char *id = imapc->resptag; | ||||||
|   size_t id_len = strlen(id); |   size_t id_len = strlen(id); | ||||||
| @@ -306,7 +309,12 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, | |||||||
|            (strcmp(imap->custom, "STORE") || |            (strcmp(imap->custom, "STORE") || | ||||||
|             !imap_matchresp(line, len, "FETCH")) && |             !imap_matchresp(line, len, "FETCH")) && | ||||||
|            strcmp(imap->custom, "SELECT") && |            strcmp(imap->custom, "SELECT") && | ||||||
|            strcmp(imap->custom, "EXAMINE"))) |            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; |           return FALSE; | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
| @@ -329,7 +337,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, | |||||||
|     return TRUE; |     return TRUE; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Do we have a continuation response? */ |   /* 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)) || |   if((len == 3 && !memcmp("+", line, 1)) || | ||||||
|      (len >= 2 && !memcmp("+ ", line, 2))) { |      (len >= 2 && !memcmp("+ ", line, 2))) { | ||||||
|     switch(imapc->state) { |     switch(imapc->state) { | ||||||
| @@ -342,6 +353,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, | |||||||
|       case IMAP_AUTHENTICATE_DIGESTMD5_RESP: |       case IMAP_AUTHENTICATE_DIGESTMD5_RESP: | ||||||
|       case IMAP_AUTHENTICATE_NTLM: |       case IMAP_AUTHENTICATE_NTLM: | ||||||
|       case IMAP_AUTHENTICATE_NTLM_TYPE2MSG: |       case IMAP_AUTHENTICATE_NTLM_TYPE2MSG: | ||||||
|  |       case IMAP_AUTHENTICATE_XOAUTH2: | ||||||
|       case IMAP_AUTHENTICATE_FINAL: |       case IMAP_AUTHENTICATE_FINAL: | ||||||
|       case IMAP_APPEND: |       case IMAP_APPEND: | ||||||
|         *resp = '+'; |         *resp = '+'; | ||||||
| @@ -359,6 +371,35 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, | |||||||
|   return FALSE; /* Nothing for us */ |   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() |  * state() | ||||||
| @@ -384,6 +425,8 @@ static void state(struct connectdata *conn, imapstate newstate) | |||||||
|     "AUTHENTICATE_DIGESTMD5_RESP", |     "AUTHENTICATE_DIGESTMD5_RESP", | ||||||
|     "AUTHENTICATE_NTLM", |     "AUTHENTICATE_NTLM", | ||||||
|     "AUTHENTICATE_NTLM_TYPE2MSG", |     "AUTHENTICATE_NTLM_TYPE2MSG", | ||||||
|  |     "AUTHENTICATE_XOAUTH2", | ||||||
|  |     "AUTHENTICATE_CANCEL", | ||||||
|     "AUTHENTICATE_FINAL", |     "AUTHENTICATE_FINAL", | ||||||
|     "LOGIN", |     "LOGIN", | ||||||
|     "LIST", |     "LIST", | ||||||
| @@ -398,7 +441,7 @@ static void state(struct connectdata *conn, imapstate newstate) | |||||||
|  |  | ||||||
|   if(imapc->state != newstate) |   if(imapc->state != newstate) | ||||||
|     infof(conn->data, "IMAP %p state change from %s to %s\n", |     infof(conn->data, "IMAP %p state change from %s to %s\n", | ||||||
|           imapc, names[imapc->state], names[newstate]); |           (void *)imapc, names[imapc->state], names[newstate]); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   imapc->state = newstate; |   imapc->state = newstate; | ||||||
| @@ -541,18 +584,18 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
|     return result; |     return result; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Calculate the supported authentication mechanism by decreasing order of |   /* Calculate the supported authentication mechanism, by decreasing order of | ||||||
|      security */ |      security, as well as the initial response where appropriate */ | ||||||
| #ifndef CURL_DISABLE_CRYPTO_AUTH | #ifndef CURL_DISABLE_CRYPTO_AUTH | ||||||
|   if((imapc->authmechs & SASL_MECH_DIGEST_MD5) && |   if((imapc->authmechs & SASL_MECH_DIGEST_MD5) && | ||||||
|      (imapc->prefmech & SASL_MECH_DIGEST_MD5)) { |      (imapc->prefmech & SASL_MECH_DIGEST_MD5)) { | ||||||
|     mech = "DIGEST-MD5"; |     mech = SASL_MECH_STRING_DIGEST_MD5; | ||||||
|     state1 = IMAP_AUTHENTICATE_DIGESTMD5; |     state1 = IMAP_AUTHENTICATE_DIGESTMD5; | ||||||
|     imapc->authused = SASL_MECH_DIGEST_MD5; |     imapc->authused = SASL_MECH_DIGEST_MD5; | ||||||
|   } |   } | ||||||
|   else if((imapc->authmechs & SASL_MECH_CRAM_MD5) && |   else if((imapc->authmechs & SASL_MECH_CRAM_MD5) && | ||||||
|           (imapc->prefmech & SASL_MECH_CRAM_MD5)) { |           (imapc->prefmech & SASL_MECH_CRAM_MD5)) { | ||||||
|     mech = "CRAM-MD5"; |     mech = SASL_MECH_STRING_CRAM_MD5; | ||||||
|     state1 = IMAP_AUTHENTICATE_CRAMMD5; |     state1 = IMAP_AUTHENTICATE_CRAMMD5; | ||||||
|     imapc->authused = SASL_MECH_CRAM_MD5; |     imapc->authused = SASL_MECH_CRAM_MD5; | ||||||
|   } |   } | ||||||
| @@ -561,7 +604,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
| #ifdef USE_NTLM | #ifdef USE_NTLM | ||||||
|     if((imapc->authmechs & SASL_MECH_NTLM) && |     if((imapc->authmechs & SASL_MECH_NTLM) && | ||||||
|        (imapc->prefmech & SASL_MECH_NTLM)) { |        (imapc->prefmech & SASL_MECH_NTLM)) { | ||||||
|     mech = "NTLM"; |     mech = SASL_MECH_STRING_NTLM; | ||||||
|     state1 = IMAP_AUTHENTICATE_NTLM; |     state1 = IMAP_AUTHENTICATE_NTLM; | ||||||
|     state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG; |     state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG; | ||||||
|     imapc->authused = SASL_MECH_NTLM; |     imapc->authused = SASL_MECH_NTLM; | ||||||
| @@ -573,9 +616,22 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
|   } |   } | ||||||
|   else |   else | ||||||
| #endif | #endif | ||||||
|   if((imapc->authmechs & SASL_MECH_LOGIN) && |   if(((imapc->authmechs & SASL_MECH_XOAUTH2) && | ||||||
|  |       (imapc->prefmech & SASL_MECH_XOAUTH2) && | ||||||
|  |       (imapc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) { | ||||||
|  |     mech = SASL_MECH_STRING_XOAUTH2; | ||||||
|  |     state1 = IMAP_AUTHENTICATE_XOAUTH2; | ||||||
|  |     state2 = IMAP_AUTHENTICATE_FINAL; | ||||||
|  |     imapc->authused = SASL_MECH_XOAUTH2; | ||||||
|  |  | ||||||
|  |     if(imapc->ir_supported || data->set.sasl_ir) | ||||||
|  |       result = Curl_sasl_create_xoauth2_message(conn->data, conn->user, | ||||||
|  |                                                 conn->xoauth2_bearer, | ||||||
|  |                                                 &initresp, &len); | ||||||
|  |   } | ||||||
|  |   else if((imapc->authmechs & SASL_MECH_LOGIN) && | ||||||
|      (imapc->prefmech & SASL_MECH_LOGIN)) { |      (imapc->prefmech & SASL_MECH_LOGIN)) { | ||||||
|     mech = "LOGIN"; |     mech = SASL_MECH_STRING_LOGIN; | ||||||
|     state1 = IMAP_AUTHENTICATE_LOGIN; |     state1 = IMAP_AUTHENTICATE_LOGIN; | ||||||
|     state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD; |     state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD; | ||||||
|     imapc->authused = SASL_MECH_LOGIN; |     imapc->authused = SASL_MECH_LOGIN; | ||||||
| @@ -586,7 +642,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
|   } |   } | ||||||
|   else if((imapc->authmechs & SASL_MECH_PLAIN) && |   else if((imapc->authmechs & SASL_MECH_PLAIN) && | ||||||
|           (imapc->prefmech & SASL_MECH_PLAIN)) { |           (imapc->prefmech & SASL_MECH_PLAIN)) { | ||||||
|     mech = "PLAIN"; |     mech = SASL_MECH_STRING_PLAIN; | ||||||
|     state1 = IMAP_AUTHENTICATE_PLAIN; |     state1 = IMAP_AUTHENTICATE_PLAIN; | ||||||
|     state2 = IMAP_AUTHENTICATE_FINAL; |     state2 = IMAP_AUTHENTICATE_FINAL; | ||||||
|     imapc->authused = SASL_MECH_PLAIN; |     imapc->authused = SASL_MECH_PLAIN; | ||||||
| @@ -597,7 +653,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(!result) { |   if(!result) { | ||||||
|     if(mech) { |     if(mech && (imapc->preftype & IMAP_TYPE_SASL)) { | ||||||
|       /* Perform SASL based authentication */ |       /* Perform SASL based authentication */ | ||||||
|       if(initresp) { |       if(initresp) { | ||||||
|         result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp); |         result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp); | ||||||
| @@ -614,7 +670,8 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
|  |  | ||||||
|       Curl_safefree(initresp); |       Curl_safefree(initresp); | ||||||
|     } |     } | ||||||
|     else if(!imapc->login_disabled) |     else if((!imapc->login_disabled) && | ||||||
|  |             (imapc->preftype & IMAP_TYPE_CLEARTEXT)) | ||||||
|       /* Perform clear text authentication */ |       /* Perform clear text authentication */ | ||||||
|       result = imap_perform_login(conn); |       result = imap_perform_login(conn); | ||||||
|     else { |     else { | ||||||
| @@ -637,7 +694,7 @@ static CURLcode imap_perform_list(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap = data->req.protop; | ||||||
|   char *mailbox; |   char *mailbox; | ||||||
|  |  | ||||||
|   if(imap->custom) |   if(imap->custom) | ||||||
| @@ -672,7 +729,7 @@ static CURLcode imap_perform_select(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap = data->req.protop; | ||||||
|   struct imap_conn *imapc = &conn->proto.imapc; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   char *mailbox; |   char *mailbox; | ||||||
|  |  | ||||||
| @@ -711,7 +768,7 @@ static CURLcode imap_perform_select(struct connectdata *conn) | |||||||
| static CURLcode imap_perform_fetch(struct connectdata *conn) | static CURLcode imap_perform_fetch(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct IMAP *imap = conn->data->state.proto.imap; |   struct IMAP *imap = conn->data->req.protop; | ||||||
|  |  | ||||||
|   /* Check we have a UID */ |   /* Check we have a UID */ | ||||||
|   if(!imap->uid) { |   if(!imap->uid) { | ||||||
| @@ -739,7 +796,7 @@ static CURLcode imap_perform_fetch(struct connectdata *conn) | |||||||
| static CURLcode imap_perform_append(struct connectdata *conn) | static CURLcode imap_perform_append(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct IMAP *imap = conn->data->state.proto.imap; |   struct IMAP *imap = conn->data->req.protop; | ||||||
|   char *mailbox; |   char *mailbox; | ||||||
|  |  | ||||||
|   /* Check we have a mailbox */ |   /* Check we have a mailbox */ | ||||||
| @@ -863,20 +920,22 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, | |||||||
|         wordlen -= 5; |         wordlen -= 5; | ||||||
|  |  | ||||||
|         /* Test the word for a matching authentication mechanism */ |         /* Test the word for a matching authentication mechanism */ | ||||||
|         if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) |         if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN)) | ||||||
|           imapc->authmechs |= SASL_MECH_LOGIN; |           imapc->authmechs |= SASL_MECH_LOGIN; | ||||||
|         if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN)) | ||||||
|           imapc->authmechs |= SASL_MECH_PLAIN; |           imapc->authmechs |= SASL_MECH_PLAIN; | ||||||
|         else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5)) | ||||||
|           imapc->authmechs |= SASL_MECH_CRAM_MD5; |           imapc->authmechs |= SASL_MECH_CRAM_MD5; | ||||||
|         else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5)) | ||||||
|           imapc->authmechs |= SASL_MECH_DIGEST_MD5; |           imapc->authmechs |= SASL_MECH_DIGEST_MD5; | ||||||
|         else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI)) | ||||||
|           imapc->authmechs |= SASL_MECH_GSSAPI; |           imapc->authmechs |= SASL_MECH_GSSAPI; | ||||||
|         else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL)) | ||||||
|           imapc->authmechs |= SASL_MECH_EXTERNAL; |           imapc->authmechs |= SASL_MECH_EXTERNAL; | ||||||
|         else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM)) | ||||||
|           imapc->authmechs |= SASL_MECH_NTLM; |           imapc->authmechs |= SASL_MECH_NTLM; | ||||||
|  |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2)) | ||||||
|  |           imapc->authmechs |= SASL_MECH_XOAUTH2; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       line += wordlen; |       line += wordlen; | ||||||
| @@ -949,20 +1008,17 @@ static CURLcode imap_state_auth_plain_resp(struct connectdata *conn, | |||||||
|     /* Create the authorisation message */ |     /* Create the authorisation message */ | ||||||
|     result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, |     result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, | ||||||
|                                             &plainauth, &len); |                                             &plainauth, &len); | ||||||
|  |     if(!result && plainauth) { | ||||||
|  |       /* Send the message */ | ||||||
|  |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth); | ||||||
|  |  | ||||||
|     /* Send the message */ |       if(!result) | ||||||
|     if(!result) { |         state(conn, IMAP_AUTHENTICATE_FINAL); | ||||||
|       if(plainauth) { |  | ||||||
|         result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth); |  | ||||||
|  |  | ||||||
|         if(!result) |  | ||||||
|           state(conn, IMAP_AUTHENTICATE_FINAL); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       Curl_safefree(plainauth); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(plainauth); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -986,20 +1042,17 @@ static CURLcode imap_state_auth_login_resp(struct connectdata *conn, | |||||||
|     /* Create the user message */ |     /* Create the user message */ | ||||||
|     result = Curl_sasl_create_login_message(data, conn->user, |     result = Curl_sasl_create_login_message(data, conn->user, | ||||||
|                                             &authuser, &len); |                                             &authuser, &len); | ||||||
|  |     if(!result && authuser) { | ||||||
|  |       /* Send the user */ | ||||||
|  |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authuser); | ||||||
|  |  | ||||||
|     /* Send the user */ |       if(!result) | ||||||
|     if(!result) { |         state(conn, IMAP_AUTHENTICATE_LOGIN_PASSWD); | ||||||
|       if(authuser) { |  | ||||||
|         result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authuser); |  | ||||||
|  |  | ||||||
|         if(!result) |  | ||||||
|           state(conn, IMAP_AUTHENTICATE_LOGIN_PASSWD); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       Curl_safefree(authuser); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(authuser); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1023,20 +1076,17 @@ static CURLcode imap_state_auth_login_password_resp(struct connectdata *conn, | |||||||
|     /* Create the password message */ |     /* Create the password message */ | ||||||
|     result = Curl_sasl_create_login_message(data, conn->passwd, |     result = Curl_sasl_create_login_message(data, conn->passwd, | ||||||
|                                             &authpasswd, &len); |                                             &authpasswd, &len); | ||||||
|  |     if(!result && authpasswd) { | ||||||
|  |       /* Send the password */ | ||||||
|  |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authpasswd); | ||||||
|  |  | ||||||
|     /* Send the password */ |       if(!result) | ||||||
|     if(!result) { |         state(conn, IMAP_AUTHENTICATE_FINAL); | ||||||
|       if(authpasswd) { |  | ||||||
|         result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authpasswd); |  | ||||||
|  |  | ||||||
|         if(!result) |  | ||||||
|           state(conn, IMAP_AUTHENTICATE_FINAL); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       Curl_safefree(authpasswd); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(authpasswd); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1048,9 +1098,10 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   char *chlg64 = data->state.buffer; |   char *chlg = NULL; | ||||||
|   size_t len = 0; |   char *chlg64 = NULL; | ||||||
|   char *rplyb64 = NULL; |   char *rplyb64 = NULL; | ||||||
|  |   size_t len = 0; | ||||||
|  |  | ||||||
|   (void)instate; /* no use for this yet */ |   (void)instate; /* no use for this yet */ | ||||||
|  |  | ||||||
| @@ -1059,38 +1110,34 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn, | |||||||
|     return CURLE_LOGIN_DENIED; |     return CURLE_LOGIN_DENIED; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Get the challenge */ |   /* Get the challenge message */ | ||||||
|   for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) |   imap_get_message(data->state.buffer, &chlg64); | ||||||
|     ; |  | ||||||
|  |  | ||||||
|   /* Terminate the challenge */ |   /* Decode the challenge message */ | ||||||
|   if(*chlg64 != '=') { |   result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len); | ||||||
|     for(len = strlen(chlg64); len--;) |   if(result) { | ||||||
|       if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' && |     /* Send the cancellation */ | ||||||
|          chlg64[len] != '\t') |     result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*"); | ||||||
|         break; |  | ||||||
|  |  | ||||||
|     if(++len) { |     if(!result) | ||||||
|       chlg64[len] = '\0'; |       state(conn, IMAP_AUTHENTICATE_CANCEL); | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |   else { | ||||||
|   /* Create the response message */ |     /* Create the response message */ | ||||||
|   result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user, |     result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user, | ||||||
|                                              conn->passwd, &rplyb64, &len); |                                                conn->passwd, &rplyb64, &len); | ||||||
|  |     if(!result && rplyb64) { | ||||||
|   /* Send the response */ |       /* Send the response */ | ||||||
|   if(!result) { |  | ||||||
|     if(rplyb64) { |  | ||||||
|       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); | ||||||
|  |  | ||||||
|       if(!result) |       if(!result) | ||||||
|         state(conn, IMAP_AUTHENTICATE_FINAL); |         state(conn, IMAP_AUTHENTICATE_FINAL); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Curl_safefree(rplyb64); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(chlg); | ||||||
|  |   Curl_safefree(rplyb64); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1101,9 +1148,13 @@ static CURLcode imap_state_auth_digest_resp(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   char *chlg64 = data->state.buffer; |   char *chlg64 = NULL; | ||||||
|   size_t len = 0; |  | ||||||
|   char *rplyb64 = NULL; |   char *rplyb64 = NULL; | ||||||
|  |   size_t len = 0; | ||||||
|  |  | ||||||
|  |   char nonce[64]; | ||||||
|  |   char realm[128]; | ||||||
|  |   char algorithm[64]; | ||||||
|  |  | ||||||
|   (void)instate; /* no use for this yet */ |   (void)instate; /* no use for this yet */ | ||||||
|  |  | ||||||
| @@ -1112,27 +1163,36 @@ static CURLcode imap_state_auth_digest_resp(struct connectdata *conn, | |||||||
|     return CURLE_LOGIN_DENIED; |     return CURLE_LOGIN_DENIED; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Get the challenge */ |   /* Get the challenge message */ | ||||||
|   for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) |   imap_get_message(data->state.buffer, &chlg64); | ||||||
|     ; |  | ||||||
|  |  | ||||||
|   /* Create the response message */ |   /* Decode the challange message */ | ||||||
|   result = Curl_sasl_create_digest_md5_message(data, chlg64, conn->user, |   result = Curl_sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce), | ||||||
|                                                conn->passwd, "imap", |                                                realm, sizeof(realm), | ||||||
|                                                &rplyb64, &len); |                                                algorithm, sizeof(algorithm)); | ||||||
|  |   if(result || strcmp(algorithm, "md5-sess") != 0) { | ||||||
|  |     /* Send the cancellation */ | ||||||
|  |     result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*"); | ||||||
|  |  | ||||||
|   /* Send the response */ |     if(!result) | ||||||
|   if(!result) { |       state(conn, IMAP_AUTHENTICATE_CANCEL); | ||||||
|     if(rplyb64) { |   } | ||||||
|  |   else { | ||||||
|  |     /* Create the response message */ | ||||||
|  |     result = Curl_sasl_create_digest_md5_message(data, nonce, realm, | ||||||
|  |                                                  conn->user, conn->passwd, | ||||||
|  |                                                  "imap", &rplyb64, &len); | ||||||
|  |     if(!result && rplyb64) { | ||||||
|  |       /* Send the response */ | ||||||
|       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); | ||||||
|  |  | ||||||
|       if(!result) |       if(!result) | ||||||
|         state(conn, IMAP_AUTHENTICATE_DIGESTMD5_RESP); |         state(conn, IMAP_AUTHENTICATE_DIGESTMD5_RESP); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Curl_safefree(rplyb64); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(rplyb64); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1152,7 +1212,7 @@ static CURLcode imap_state_auth_digest_resp_resp(struct connectdata *conn, | |||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     /* Send an empty response */ |     /* Send an empty response */ | ||||||
|     result = Curl_pp_sendf(&conn->proto.imapc.pp, ""); |     result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", ""); | ||||||
|  |  | ||||||
|     if(!result) |     if(!result) | ||||||
|       state(conn, IMAP_AUTHENTICATE_FINAL); |       state(conn, IMAP_AUTHENTICATE_FINAL); | ||||||
| @@ -1184,20 +1244,17 @@ static CURLcode imap_state_auth_ntlm_resp(struct connectdata *conn, | |||||||
|     result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, |     result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, | ||||||
|                                                  &conn->ntlm, |                                                  &conn->ntlm, | ||||||
|                                                  &type1msg, &len); |                                                  &type1msg, &len); | ||||||
|  |     if(!result && type1msg) { | ||||||
|  |       /* Send the message */ | ||||||
|  |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type1msg); | ||||||
|  |  | ||||||
|     /* Send the message */ |       if(!result) | ||||||
|     if(!result) { |         state(conn, IMAP_AUTHENTICATE_NTLM_TYPE2MSG); | ||||||
|       if(type1msg) { |  | ||||||
|         result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type1msg); |  | ||||||
|  |  | ||||||
|         if(!result) |  | ||||||
|           state(conn, IMAP_AUTHENTICATE_NTLM_TYPE2MSG); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       Curl_safefree(type1msg); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(type1msg); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1208,8 +1265,9 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   size_t len = 0; |   char *type2msg = NULL; | ||||||
|   char *type3msg = NULL; |   char *type3msg = NULL; | ||||||
|  |   size_t len = 0; | ||||||
|  |  | ||||||
|   (void)instate; /* no use for this yet */ |   (void)instate; /* no use for this yet */ | ||||||
|  |  | ||||||
| @@ -1218,31 +1276,90 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn, | |||||||
|     result = CURLE_LOGIN_DENIED; |     result = CURLE_LOGIN_DENIED; | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     /* Create the type-3 message */ |     /* Get the challenge message */ | ||||||
|     result = Curl_sasl_create_ntlm_type3_message(data, |     imap_get_message(data->state.buffer, &type2msg); | ||||||
|                                                  data->state.buffer + 2, |  | ||||||
|                                                  conn->user, conn->passwd, |  | ||||||
|                                                  &conn->ntlm, |  | ||||||
|                                                  &type3msg, &len); |  | ||||||
|  |  | ||||||
|     /* Send the message */ |     /* Decode the type-2 message */ | ||||||
|     if(!result) { |     result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm); | ||||||
|       if(type3msg) { |     if(result) { | ||||||
|  |       /* Send the cancellation */ | ||||||
|  |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*"); | ||||||
|  |  | ||||||
|  |       if(!result) | ||||||
|  |         state(conn, IMAP_AUTHENTICATE_CANCEL); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       /* Create the type-3 message */ | ||||||
|  |       result = Curl_sasl_create_ntlm_type3_message(data, conn->user, | ||||||
|  |                                                    conn->passwd, &conn->ntlm, | ||||||
|  |                                                    &type3msg, &len); | ||||||
|  |       if(!result && type3msg) { | ||||||
|  |         /* Send the message */ | ||||||
|         result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type3msg); |         result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type3msg); | ||||||
|  |  | ||||||
|         if(!result) |         if(!result) | ||||||
|           state(conn, IMAP_AUTHENTICATE_FINAL); |           state(conn, IMAP_AUTHENTICATE_FINAL); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       Curl_safefree(type3msg); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(type3msg); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* For final responses to the AUTHENTICATE sequence */ | /* For AUTHENTICATE XOAUTH2 (without initial response) responses */ | ||||||
|  | static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn, | ||||||
|  |                                              int imapcode, | ||||||
|  |                                              imapstate instate) | ||||||
|  | { | ||||||
|  |   CURLcode result = CURLE_OK; | ||||||
|  |   struct SessionHandle *data = conn->data; | ||||||
|  |   size_t len = 0; | ||||||
|  |   char *xoauth = NULL; | ||||||
|  |  | ||||||
|  |   (void)instate; /* no use for this yet */ | ||||||
|  |  | ||||||
|  |   if(imapcode != '+') { | ||||||
|  |     failf(data, "Access denied: %d", imapcode); | ||||||
|  |     result = CURLE_LOGIN_DENIED; | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     /* Create the authorisation message */ | ||||||
|  |     result = Curl_sasl_create_xoauth2_message(conn->data, conn->user, | ||||||
|  |                                               conn->xoauth2_bearer, | ||||||
|  |                                               &xoauth, &len); | ||||||
|  |     if(!result && xoauth) { | ||||||
|  |       /* Send the message */ | ||||||
|  |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth); | ||||||
|  |  | ||||||
|  |       if(!result) | ||||||
|  |         state(conn, IMAP_AUTHENTICATE_FINAL); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Curl_safefree(xoauth); | ||||||
|  |  | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* For AUTHENTICATE cancellation responses */ | ||||||
|  | static CURLcode imap_state_auth_cancel_resp(struct connectdata *conn, | ||||||
|  |                                             int imapcode, | ||||||
|  |                                             imapstate instate) | ||||||
|  | { | ||||||
|  |   struct SessionHandle *data = conn->data; | ||||||
|  |  | ||||||
|  |   (void)imapcode; | ||||||
|  |   (void)instate; /* no use for this yet */ | ||||||
|  |  | ||||||
|  |   failf(data, "Authentication cancelled"); | ||||||
|  |  | ||||||
|  |   return CURLE_LOGIN_DENIED; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* For final responses in the AUTHENTICATE sequence */ | ||||||
| static CURLcode imap_state_auth_final_resp(struct connectdata *conn, | static CURLcode imap_state_auth_final_resp(struct connectdata *conn, | ||||||
|                                            int imapcode, |                                            int imapcode, | ||||||
|                                            imapstate instate) |                                            imapstate instate) | ||||||
| @@ -1315,7 +1432,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = conn->data->state.proto.imap; |   struct IMAP *imap = conn->data->req.protop; | ||||||
|   struct imap_conn *imapc = &conn->proto.imapc; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   const char *line = data->state.buffer; |   const char *line = data->state.buffer; | ||||||
|   char tmp[20]; |   char tmp[20]; | ||||||
| @@ -1406,10 +1523,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, | |||||||
|         return result; |         return result; | ||||||
|  |  | ||||||
|       data->req.bytecount += chunk; |       data->req.bytecount += chunk; | ||||||
|       size -= chunk; |  | ||||||
|  |  | ||||||
|       infof(data, "Written %" FORMAT_OFF_TU " bytes, %" FORMAT_OFF_TU |       infof(data, "Written %" FORMAT_OFF_TU " bytes, %" FORMAT_OFF_TU | ||||||
|             " bytes are left for transfer\n", (curl_off_t)chunk, size); |             " bytes are left for transfer\n", (curl_off_t)chunk, | ||||||
|  |             size - chunk); | ||||||
|  |  | ||||||
|       /* Have we used the entire cache or just part of it?*/ |       /* Have we used the entire cache or just part of it?*/ | ||||||
|       if(pp->cache_size > chunk) { |       if(pp->cache_size > chunk) { | ||||||
| @@ -1426,7 +1543,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(!size) |     if(data->req.bytecount == size) | ||||||
|       /* The entire data is already transferred! */ |       /* The entire data is already transferred! */ | ||||||
|       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); |       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); | ||||||
|     else { |     else { | ||||||
| @@ -1591,6 +1708,14 @@ static CURLcode imap_statemach_act(struct connectdata *conn) | |||||||
|       break; |       break; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |     case IMAP_AUTHENTICATE_XOAUTH2: | ||||||
|  |       result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state); | ||||||
|  |       break; | ||||||
|  |  | ||||||
|  |     case IMAP_AUTHENTICATE_CANCEL: | ||||||
|  |       result = imap_state_auth_cancel_resp(conn, imapcode, imapc->state); | ||||||
|  |       break; | ||||||
|  |  | ||||||
|     case IMAP_AUTHENTICATE_FINAL: |     case IMAP_AUTHENTICATE_FINAL: | ||||||
|       result = imap_state_auth_final_resp(conn, imapcode, imapc->state); |       result = imap_state_auth_final_resp(conn, imapcode, imapc->state); | ||||||
|       break; |       break; | ||||||
| @@ -1641,11 +1766,13 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done) | |||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct imap_conn *imapc = &conn->proto.imapc; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|  |  | ||||||
|   if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) |   if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) { | ||||||
|     result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); |     result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); | ||||||
|   else |     if(result || !imapc->ssldone) | ||||||
|     result = Curl_pp_statemach(&imapc->pp, FALSE); |       return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   result = Curl_pp_statemach(&imapc->pp, FALSE); | ||||||
|   *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; |   *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| @@ -1668,13 +1795,11 @@ static CURLcode imap_init(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap; | ||||||
|  |  | ||||||
|   if(!imap) { |   imap = data->req.protop = calloc(sizeof(struct IMAP), 1); | ||||||
|     imap = data->state.proto.imap = calloc(sizeof(struct IMAP), 1); |   if(!imap) | ||||||
|     if(!imap) |     result = CURLE_OUT_OF_MEMORY; | ||||||
|       result = CURLE_OUT_OF_MEMORY; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| @@ -1694,8 +1819,7 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, | |||||||
|  * connection phase. |  * connection phase. | ||||||
|  * |  * | ||||||
|  * The variable 'done' points to will be TRUE if the protocol-layer connect |  * The variable 'done' points to will be TRUE if the protocol-layer connect | ||||||
|  * phase is done when this function returns, or FALSE is not. When called as |  * phase is done when this function returns, or FALSE if not. | ||||||
|  * a part of the easy interface, it will always be TRUE. |  | ||||||
|  */ |  */ | ||||||
| static CURLcode imap_connect(struct connectdata *conn, bool *done) | static CURLcode imap_connect(struct connectdata *conn, bool *done) | ||||||
| { | { | ||||||
| @@ -1705,15 +1829,6 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to not done yet */ |   *done = FALSE; /* default to not done yet */ | ||||||
|  |  | ||||||
|   /* If there already is a protocol-specific struct allocated for this |  | ||||||
|      sessionhandle, deal with it */ |  | ||||||
|   Curl_reset_reqproto(conn); |  | ||||||
|  |  | ||||||
|   /* Initialise the IMAP layer */ |  | ||||||
|   result = imap_init(conn); |  | ||||||
|   if(result) |  | ||||||
|     return result; |  | ||||||
|  |  | ||||||
|   /* We always support persistent connections in IMAP */ |   /* We always support persistent connections in IMAP */ | ||||||
|   conn->bits.close = FALSE; |   conn->bits.close = FALSE; | ||||||
|  |  | ||||||
| @@ -1723,7 +1838,8 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done) | |||||||
|   pp->endofresp = imap_endofresp; |   pp->endofresp = imap_endofresp; | ||||||
|   pp->conn = conn; |   pp->conn = conn; | ||||||
|  |  | ||||||
|   /* Set the default preferred authentication mechanism */ |   /* Set the default preferred authentication type and mechanism */ | ||||||
|  |   imapc->preftype = IMAP_TYPE_ANY; | ||||||
|   imapc->prefmech = SASL_AUTH_ANY; |   imapc->prefmech = SASL_AUTH_ANY; | ||||||
|  |  | ||||||
|   /* Initialise the pingpong layer */ |   /* Initialise the pingpong layer */ | ||||||
| @@ -1759,7 +1875,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap = data->req.protop; | ||||||
|  |  | ||||||
|   (void)premature; |   (void)premature; | ||||||
|  |  | ||||||
| @@ -1781,7 +1897,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status, | |||||||
|       state(conn, IMAP_FETCH_FINAL); |       state(conn, IMAP_FETCH_FINAL); | ||||||
|     else { |     else { | ||||||
|       /* End the APPEND command first by sending an empty line */ |       /* End the APPEND command first by sending an empty line */ | ||||||
|       result = Curl_pp_sendf(&conn->proto.imapc.pp, ""); |       result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", ""); | ||||||
|       if(!result) |       if(!result) | ||||||
|         state(conn, IMAP_APPEND_FINAL); |         state(conn, IMAP_APPEND_FINAL); | ||||||
|     } |     } | ||||||
| @@ -1824,7 +1940,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected, | |||||||
|   /* This is IMAP and no proxy */ |   /* This is IMAP and no proxy */ | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap = data->req.protop; | ||||||
|   struct imap_conn *imapc = &conn->proto.imapc; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   bool selected = FALSE; |   bool selected = FALSE; | ||||||
|  |  | ||||||
| @@ -1891,15 +2007,6 @@ static CURLcode imap_do(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to false */ |   *done = FALSE; /* default to false */ | ||||||
|  |  | ||||||
|   /* Since connections can be re-used between SessionHandles, there might be a |  | ||||||
|      connection already existing but on a fresh SessionHandle struct. As such |  | ||||||
|      we make sure we have a good IMAP struct to play with. For new connections |  | ||||||
|      the IMAP struct is allocated and setup in the imap_connect() function. */ |  | ||||||
|   Curl_reset_reqproto(conn); |  | ||||||
|   result = imap_init(conn); |  | ||||||
|   if(result) |  | ||||||
|     return result; |  | ||||||
|  |  | ||||||
|   /* Parse the URL path */ |   /* Parse the URL path */ | ||||||
|   result = imap_parse_url_path(conn); |   result = imap_parse_url_path(conn); | ||||||
|   if(result) |   if(result) | ||||||
| @@ -1932,7 +2039,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) | |||||||
|  |  | ||||||
|   /* The IMAP session may or may not have been allocated/setup at this |   /* The IMAP session may or may not have been allocated/setup at this | ||||||
|      point! */ |      point! */ | ||||||
|   if(!dead_connection && imapc->pp.conn) |   if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart) | ||||||
|     if(!imap_perform_logout(conn)) |     if(!imap_perform_logout(conn)) | ||||||
|       (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */ |       (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */ | ||||||
|  |  | ||||||
| @@ -1952,7 +2059,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) | |||||||
| /* Call this when the DO phase has completed */ | /* Call this when the DO phase has completed */ | ||||||
| static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) | static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) | ||||||
| { | { | ||||||
|   struct IMAP *imap = conn->data->state.proto.imap; |   struct IMAP *imap = conn->data->req.protop; | ||||||
|  |  | ||||||
|   (void)connected; |   (void)connected; | ||||||
|  |  | ||||||
| @@ -2018,6 +2125,11 @@ static CURLcode imap_setup_connection(struct connectdata *conn) | |||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   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) { |   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { | ||||||
|     /* Unless we have asked to tunnel IMAP operations through the proxy, we |     /* Unless we have asked to tunnel IMAP operations through the proxy, we | ||||||
|        switch and use HTTP operations only */ |        switch and use HTTP operations only */ | ||||||
| @@ -2033,10 +2145,8 @@ static CURLcode imap_setup_connection(struct connectdata *conn) | |||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* We explicitly mark this connection as persistent here as we're doing |     /* set it up as an HTTP connection instead */ | ||||||
|        IMAP over HTTP and thus we accidentally avoid setting this value |     return conn->handler->setup_connection(conn); | ||||||
|        otherwise */ |  | ||||||
|     conn->bits.close = FALSE; |  | ||||||
| #else | #else | ||||||
|     failf(data, "IMAP over http proxy requires HTTP support built-in!"); |     failf(data, "IMAP over http proxy requires HTTP support built-in!"); | ||||||
|     return CURLE_UNSUPPORTED_PROTOCOL; |     return CURLE_UNSUPPORTED_PROTOCOL; | ||||||
| @@ -2062,14 +2172,15 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) | |||||||
|   struct imap_conn *imapc = &conn->proto.imapc; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   char *taggedfmt; |   char *taggedfmt; | ||||||
|   va_list ap; |   va_list ap; | ||||||
|   va_start(ap, fmt); |  | ||||||
|  |   DEBUGASSERT(fmt); | ||||||
|  |  | ||||||
|   /* Calculate the next command ID wrapping at 3 digits */ |   /* Calculate the next command ID wrapping at 3 digits */ | ||||||
|   imapc->cmdid = (imapc->cmdid + 1) % 1000; |   imapc->cmdid = (imapc->cmdid + 1) % 1000; | ||||||
|  |  | ||||||
|   /* Calculate the tag based on the connection ID and command ID */ |   /* Calculate the tag based on the connection ID and command ID */ | ||||||
|   snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d", |   snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d", | ||||||
|            'A' + (conn->connection_id % 26), imapc->cmdid); |            'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid); | ||||||
|  |  | ||||||
|   /* Prefix the format with the tag */ |   /* Prefix the format with the tag */ | ||||||
|   taggedfmt = aprintf("%s %s", imapc->resptag, fmt); |   taggedfmt = aprintf("%s %s", imapc->resptag, fmt); | ||||||
| @@ -2077,10 +2188,11 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) | |||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   /* Send the data with the tag */ |   /* Send the data with the tag */ | ||||||
|  |   va_start(ap, fmt); | ||||||
|   result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap); |   result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap); | ||||||
|  |   va_end(ap); | ||||||
|  |  | ||||||
|   Curl_safefree(taggedfmt); |   Curl_safefree(taggedfmt); | ||||||
|   va_end(ap); |  | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| @@ -2221,22 +2333,42 @@ static CURLcode imap_parse_url_options(struct connectdata *conn) | |||||||
|     if(strnequal(key, "AUTH", 4)) { |     if(strnequal(key, "AUTH", 4)) { | ||||||
|       const char *value = ptr + 1; |       const char *value = ptr + 1; | ||||||
|  |  | ||||||
|       if(strequal(value, "*")) |       if(strequal(value, "*")) { | ||||||
|  |         imapc->preftype = IMAP_TYPE_ANY; | ||||||
|         imapc->prefmech = SASL_AUTH_ANY; |         imapc->prefmech = SASL_AUTH_ANY; | ||||||
|       else if(strequal(value, "LOGIN")) |       } | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_LOGIN)) { | ||||||
|  |         imapc->preftype = IMAP_TYPE_SASL; | ||||||
|         imapc->prefmech = SASL_MECH_LOGIN; |         imapc->prefmech = SASL_MECH_LOGIN; | ||||||
|       else if(strequal(value, "PLAIN")) |       } | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_PLAIN)) { | ||||||
|  |         imapc->preftype = IMAP_TYPE_SASL; | ||||||
|         imapc->prefmech = SASL_MECH_PLAIN; |         imapc->prefmech = SASL_MECH_PLAIN; | ||||||
|       else if(strequal(value, "CRAM-MD5")) |       } | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_CRAM_MD5)) { | ||||||
|  |         imapc->preftype = IMAP_TYPE_SASL; | ||||||
|         imapc->prefmech = SASL_MECH_CRAM_MD5; |         imapc->prefmech = SASL_MECH_CRAM_MD5; | ||||||
|       else if(strequal(value, "DIGEST-MD5")) |       } | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5)) { | ||||||
|  |         imapc->preftype = IMAP_TYPE_SASL; | ||||||
|         imapc->prefmech = SASL_MECH_DIGEST_MD5; |         imapc->prefmech = SASL_MECH_DIGEST_MD5; | ||||||
|       else if(strequal(value, "GSSAPI")) |       } | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_GSSAPI)) { | ||||||
|  |         imapc->preftype = IMAP_TYPE_SASL; | ||||||
|         imapc->prefmech = SASL_MECH_GSSAPI; |         imapc->prefmech = SASL_MECH_GSSAPI; | ||||||
|       else if(strequal(value, "NTLM")) |       } | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_NTLM)) { | ||||||
|  |         imapc->preftype = IMAP_TYPE_SASL; | ||||||
|         imapc->prefmech = SASL_MECH_NTLM; |         imapc->prefmech = SASL_MECH_NTLM; | ||||||
|       else |       } | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) { | ||||||
|  |         imapc->preftype = IMAP_TYPE_SASL; | ||||||
|  |         imapc->prefmech = SASL_MECH_XOAUTH2; | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         imapc->preftype = IMAP_TYPE_NONE; | ||||||
|         imapc->prefmech = SASL_AUTH_NONE; |         imapc->prefmech = SASL_AUTH_NONE; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|       result = CURLE_URL_MALFORMAT; |       result = CURLE_URL_MALFORMAT; | ||||||
| @@ -2257,7 +2389,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn) | |||||||
|   /* The imap struct is already initialised in imap_connect() */ |   /* The imap struct is already initialised in imap_connect() */ | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap = data->req.protop; | ||||||
|   const char *begin = data->state.path; |   const char *begin = data->state.path; | ||||||
|   const char *ptr = begin; |   const char *ptr = begin; | ||||||
|  |  | ||||||
| @@ -2365,7 +2497,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap = data->req.protop; | ||||||
|   const char *custom = data->set.str[STRING_CUSTOMREQUEST]; |   const char *custom = data->set.str[STRING_CUSTOMREQUEST]; | ||||||
|  |  | ||||||
|   if(custom) { |   if(custom) { | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								lib/imap.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								lib/imap.h
									
									
									
									
									
								
							| @@ -43,6 +43,8 @@ typedef enum { | |||||||
|   IMAP_AUTHENTICATE_DIGESTMD5_RESP, |   IMAP_AUTHENTICATE_DIGESTMD5_RESP, | ||||||
|   IMAP_AUTHENTICATE_NTLM, |   IMAP_AUTHENTICATE_NTLM, | ||||||
|   IMAP_AUTHENTICATE_NTLM_TYPE2MSG, |   IMAP_AUTHENTICATE_NTLM_TYPE2MSG, | ||||||
|  |   IMAP_AUTHENTICATE_XOAUTH2, | ||||||
|  |   IMAP_AUTHENTICATE_CANCEL, | ||||||
|   IMAP_AUTHENTICATE_FINAL, |   IMAP_AUTHENTICATE_FINAL, | ||||||
|   IMAP_LOGIN, |   IMAP_LOGIN, | ||||||
|   IMAP_LIST, |   IMAP_LIST, | ||||||
| @@ -76,6 +78,7 @@ struct imap_conn { | |||||||
|   imapstate state;            /* Always use imap.c:state() to change state! */ |   imapstate state;            /* Always use imap.c:state() to change state! */ | ||||||
|   bool ssldone;               /* Is connect() over SSL done? */ |   bool ssldone;               /* Is connect() over SSL done? */ | ||||||
|   unsigned int authmechs;     /* Accepted authentication mechanisms */ |   unsigned int authmechs;     /* Accepted authentication mechanisms */ | ||||||
|  |   unsigned int preftype;      /* Preferred authentication type */ | ||||||
|   unsigned int prefmech;      /* Preferred authentication mechanism */ |   unsigned int prefmech;      /* Preferred authentication mechanism */ | ||||||
|   unsigned int authused;      /* Auth mechanism used for the connection */ |   unsigned int authused;      /* Auth mechanism used for the connection */ | ||||||
|   int cmdid;                  /* Last used command ID */ |   int cmdid;                  /* Last used command ID */ | ||||||
| @@ -90,4 +93,12 @@ struct imap_conn { | |||||||
| extern const struct Curl_handler Curl_handler_imap; | extern const struct Curl_handler Curl_handler_imap; | ||||||
| extern const struct Curl_handler Curl_handler_imaps; | 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 */ | #endif /* HEADER_CURL_IMAP_H */ | ||||||
|   | |||||||
							
								
								
									
										440
									
								
								lib/krb4.c
									
									
									
									
									
								
							
							
						
						
									
										440
									
								
								lib/krb4.c
									
									
									
									
									
								
							| @@ -1,440 +0,0 @@ | |||||||
| /* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for |  | ||||||
|  * use in Curl. Martin's latest changes were done 2000-09-18. |  | ||||||
|  * |  | ||||||
|  * It has since been patched away like a madman by Daniel Stenberg to make it |  | ||||||
|  * better applied to curl conditions, and to make it not use globals, pollute |  | ||||||
|  * name space and more. |  | ||||||
|  * |  | ||||||
|  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan |  | ||||||
|  * (Royal Institute of Technology, Stockholm, Sweden). |  | ||||||
|  * Copyright (c) 2004 - 2011 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" |  | ||||||
|  |  | ||||||
| #ifndef CURL_DISABLE_FTP |  | ||||||
| #ifdef HAVE_KRB4 |  | ||||||
|  |  | ||||||
| #ifdef HAVE_NETDB_H |  | ||||||
| #include <netdb.h> |  | ||||||
| #endif |  | ||||||
| #include <krb.h> |  | ||||||
| #include <des.h> |  | ||||||
|  |  | ||||||
| #include "urldata.h" |  | ||||||
| #include "curl_base64.h" |  | ||||||
| #include "ftp.h" |  | ||||||
| #include "sendf.h" |  | ||||||
| #include "krb4.h" |  | ||||||
| #include "inet_ntop.h" |  | ||||||
| #include "curl_memory.h" |  | ||||||
|  |  | ||||||
| /* The last #include file should be: */ |  | ||||||
| #include "memdebug.h" |  | ||||||
|  |  | ||||||
| #define LOCAL_ADDR (&conn->local_addr) |  | ||||||
| #define REMOTE_ADDR conn->ip_addr->ai_addr |  | ||||||
| #define myctladdr LOCAL_ADDR |  | ||||||
| #define hisctladdr REMOTE_ADDR |  | ||||||
|  |  | ||||||
| struct krb4_data { |  | ||||||
|   des_cblock key; |  | ||||||
|   des_key_schedule schedule; |  | ||||||
|   char name[ANAME_SZ]; |  | ||||||
|   char instance[INST_SZ]; |  | ||||||
|   char realm[REALM_SZ]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| #ifndef HAVE_STRLCPY |  | ||||||
| /* if it ever goes non-static, make it Curl_ prefixed! */ |  | ||||||
| static size_t |  | ||||||
| strlcpy (char *dst, const char *src, size_t dst_sz) |  | ||||||
| { |  | ||||||
|   size_t n; |  | ||||||
|   char *p; |  | ||||||
|  |  | ||||||
|   for(p = dst, n = 0; |  | ||||||
|       n + 1 < dst_sz && *src != '\0'; |  | ||||||
|       ++p, ++src, ++n) |  | ||||||
|     *p = *src; |  | ||||||
|   *p = '\0'; |  | ||||||
|   if(*src == '\0') |  | ||||||
|     return n; |  | ||||||
|   else |  | ||||||
|     return n + strlen (src); |  | ||||||
| } |  | ||||||
| #else |  | ||||||
| size_t strlcpy (char *dst, const char *src, size_t dst_sz); |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| krb4_check_prot(void *app_data, int level) |  | ||||||
| { |  | ||||||
|   app_data = NULL; /* prevent compiler warning */ |  | ||||||
|   if(level == PROT_CONFIDENTIAL) |  | ||||||
|     return -1; |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| krb4_decode(void *app_data, void *buf, int len, int level, |  | ||||||
|             struct connectdata *conn) |  | ||||||
| { |  | ||||||
|   MSG_DAT m; |  | ||||||
|   int e; |  | ||||||
|   struct krb4_data *d = app_data; |  | ||||||
|  |  | ||||||
|   if(level == PROT_SAFE) |  | ||||||
|     e = krb_rd_safe(buf, len, &d->key, |  | ||||||
|                     (struct sockaddr_in *)REMOTE_ADDR, |  | ||||||
|                     (struct sockaddr_in *)LOCAL_ADDR, &m); |  | ||||||
|   else |  | ||||||
|     e = krb_rd_priv(buf, len, d->schedule, &d->key, |  | ||||||
|                     (struct sockaddr_in *)REMOTE_ADDR, |  | ||||||
|                     (struct sockaddr_in *)LOCAL_ADDR, &m); |  | ||||||
|   if(e) { |  | ||||||
|     struct SessionHandle *data = conn->data; |  | ||||||
|     infof(data, "krb4_decode: %s\n", krb_get_err_text(e)); |  | ||||||
|     return -1; |  | ||||||
|   } |  | ||||||
|   memmove(buf, m.app_data, m.app_length); |  | ||||||
|   return m.app_length; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| krb4_overhead(void *app_data, int level, int len) |  | ||||||
| { |  | ||||||
|   /* no arguments are used, just init them to prevent compiler warnings */ |  | ||||||
|   app_data = NULL; |  | ||||||
|   level = 0; |  | ||||||
|   len = 0; |  | ||||||
|   return 31; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| krb4_encode(void *app_data, const void *from, int length, int level, void **to, |  | ||||||
|             struct connectdata *conn) |  | ||||||
| { |  | ||||||
|   struct krb4_data *d = app_data; |  | ||||||
|   *to = malloc(length + 31); |  | ||||||
|   if(!*to) |  | ||||||
|     return -1; |  | ||||||
|   if(level == PROT_SAFE) |  | ||||||
|     /* NOTE that the void* cast is safe, krb_mk_safe/priv don't modify the |  | ||||||
|      * input buffer |  | ||||||
|      */ |  | ||||||
|     return krb_mk_safe((void*)from, *to, length, &d->key, |  | ||||||
|                        (struct sockaddr_in *)LOCAL_ADDR, |  | ||||||
|                        (struct sockaddr_in *)REMOTE_ADDR); |  | ||||||
|   else if(level == PROT_PRIVATE) |  | ||||||
|     return krb_mk_priv((void*)from, *to, length, d->schedule, &d->key, |  | ||||||
|                        (struct sockaddr_in *)LOCAL_ADDR, |  | ||||||
|                        (struct sockaddr_in *)REMOTE_ADDR); |  | ||||||
|   else |  | ||||||
|     return -1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| mk_auth(struct krb4_data *d, KTEXT adat, |  | ||||||
|         const char *service, char *host, int checksum) |  | ||||||
| { |  | ||||||
|   int ret; |  | ||||||
|   CREDENTIALS cred; |  | ||||||
|   char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ]; |  | ||||||
|  |  | ||||||
|   strlcpy(sname, service, sizeof(sname)); |  | ||||||
|   strlcpy(inst, krb_get_phost(host), sizeof(inst)); |  | ||||||
|   strlcpy(realm, krb_realmofhost(host), sizeof(realm)); |  | ||||||
|   ret = krb_mk_req(adat, sname, inst, realm, checksum); |  | ||||||
|   if(ret) |  | ||||||
|     return ret; |  | ||||||
|   strlcpy(sname, service, sizeof(sname)); |  | ||||||
|   strlcpy(inst, krb_get_phost(host), sizeof(inst)); |  | ||||||
|   strlcpy(realm, krb_realmofhost(host), sizeof(realm)); |  | ||||||
|   ret = krb_get_cred(sname, inst, realm, &cred); |  | ||||||
|   memmove(&d->key, &cred.session, sizeof(des_cblock)); |  | ||||||
|   des_key_sched(&d->key, d->schedule); |  | ||||||
|   memset(&cred, 0, sizeof(cred)); |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM |  | ||||||
| int krb_get_our_ip_for_realm(char *, struct in_addr *); |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| krb4_auth(void *app_data, struct connectdata *conn) |  | ||||||
| { |  | ||||||
|   int ret; |  | ||||||
|   char *p; |  | ||||||
|   unsigned char *ptr; |  | ||||||
|   size_t len = 0; |  | ||||||
|   KTEXT_ST adat; |  | ||||||
|   MSG_DAT msg_data; |  | ||||||
|   int checksum; |  | ||||||
|   u_int32_t cs; |  | ||||||
|   struct krb4_data *d = app_data; |  | ||||||
|   char *host = conn->host.name; |  | ||||||
|   ssize_t nread; |  | ||||||
|   int l = sizeof(conn->local_addr); |  | ||||||
|   struct SessionHandle *data = conn->data; |  | ||||||
|   CURLcode result; |  | ||||||
|   size_t base64_sz = 0; |  | ||||||
|  |  | ||||||
|   if(getsockname(conn->sock[FIRSTSOCKET], |  | ||||||
|                  (struct sockaddr *)LOCAL_ADDR, &l) < 0) |  | ||||||
|     perror("getsockname()"); |  | ||||||
|  |  | ||||||
|   checksum = getpid(); |  | ||||||
|   ret = mk_auth(d, &adat, "ftp", host, checksum); |  | ||||||
|   if(ret == KDC_PR_UNKNOWN) |  | ||||||
|     ret = mk_auth(d, &adat, "rcmd", host, checksum); |  | ||||||
|   if(ret) { |  | ||||||
|     infof(data, "%s\n", krb_get_err_text(ret)); |  | ||||||
|     return AUTH_CONTINUE; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM |  | ||||||
|   if(krb_get_config_bool("nat_in_use")) { |  | ||||||
|     struct sockaddr_in *localaddr  = (struct sockaddr_in *)LOCAL_ADDR; |  | ||||||
|     struct in_addr natAddr; |  | ||||||
|  |  | ||||||
|     if(krb_get_our_ip_for_realm(krb_realmofhost(host), |  | ||||||
|                                  &natAddr) != KSUCCESS |  | ||||||
|         && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS) |  | ||||||
|       infof(data, "Can't get address for realm %s\n", |  | ||||||
|                  krb_realmofhost(host)); |  | ||||||
|     else { |  | ||||||
|       if(natAddr.s_addr != localaddr->sin_addr.s_addr) { |  | ||||||
|         char addr_buf[128]; |  | ||||||
|         if(Curl_inet_ntop(AF_INET, natAddr, addr_buf, sizeof(addr_buf))) |  | ||||||
|           infof(data, "Using NAT IP address (%s) for kerberos 4\n", addr_buf); |  | ||||||
|         localaddr->sin_addr = natAddr; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   result = Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, |  | ||||||
|                               &p, &base64_sz); |  | ||||||
|   if(result) { |  | ||||||
|     Curl_failf(data, "base64-encoding: %s", curl_easy_strerror(result)); |  | ||||||
|     return AUTH_CONTINUE; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   result = Curl_ftpsendf(conn, "ADAT %s", p); |  | ||||||
|  |  | ||||||
|   free(p); |  | ||||||
|  |  | ||||||
|   if(result) |  | ||||||
|     return -2; |  | ||||||
|  |  | ||||||
|   if(Curl_GetFTPResponse(&nread, conn, NULL)) |  | ||||||
|     return -1; |  | ||||||
|  |  | ||||||
|   if(data->state.buffer[0] != '2') { |  | ||||||
|     Curl_failf(data, "Server didn't accept auth data"); |  | ||||||
|     return AUTH_ERROR; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   p = strstr(data->state.buffer, "ADAT="); |  | ||||||
|   if(!p) { |  | ||||||
|     Curl_failf(data, "Remote host didn't send adat reply"); |  | ||||||
|     return AUTH_ERROR; |  | ||||||
|   } |  | ||||||
|   p += 5; |  | ||||||
|   result = Curl_base64_decode(p, &ptr, &len); |  | ||||||
|   if(result) { |  | ||||||
|     Curl_failf(data, "base64-decoding: %s", curl_easy_strerror(result)); |  | ||||||
|     return AUTH_ERROR; |  | ||||||
|   } |  | ||||||
|   if(len > sizeof(adat.dat)-1) { |  | ||||||
|     free(ptr); |  | ||||||
|     ptr = NULL; |  | ||||||
|     len = 0; |  | ||||||
|   } |  | ||||||
|   if(!len || !ptr) { |  | ||||||
|     Curl_failf(data, "Failed to decode base64 from server"); |  | ||||||
|     return AUTH_ERROR; |  | ||||||
|   } |  | ||||||
|   memcpy((char *)adat.dat, ptr, len); |  | ||||||
|   free(ptr); |  | ||||||
|   adat.length = len; |  | ||||||
|   ret = krb_rd_safe(adat.dat, adat.length, &d->key, |  | ||||||
|                     (struct sockaddr_in *)hisctladdr, |  | ||||||
|                     (struct sockaddr_in *)myctladdr, &msg_data); |  | ||||||
|   if(ret) { |  | ||||||
|     Curl_failf(data, "Error reading reply from server: %s", |  | ||||||
|                krb_get_err_text(ret)); |  | ||||||
|     return AUTH_ERROR; |  | ||||||
|   } |  | ||||||
|   krb_get_int(msg_data.app_data, &cs, 4, 0); |  | ||||||
|   if(cs - checksum != 1) { |  | ||||||
|     Curl_failf(data, "Bad checksum returned from server"); |  | ||||||
|     return AUTH_ERROR; |  | ||||||
|   } |  | ||||||
|   return AUTH_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct Curl_sec_client_mech Curl_krb4_client_mech = { |  | ||||||
|     "KERBEROS_V4", |  | ||||||
|     sizeof(struct krb4_data), |  | ||||||
|     NULL, /* init */ |  | ||||||
|     krb4_auth, |  | ||||||
|     NULL, /* end */ |  | ||||||
|     krb4_check_prot, |  | ||||||
|     krb4_overhead, |  | ||||||
|     krb4_encode, |  | ||||||
|     krb4_decode |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static enum protection_level |  | ||||||
| krb4_set_command_prot(struct connectdata *conn, enum protection_level level) |  | ||||||
| { |  | ||||||
|   enum protection_level old = conn->command_prot; |  | ||||||
|   DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); |  | ||||||
|   conn->command_prot = level; |  | ||||||
|   return old; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| CURLcode Curl_krb_kauth(struct connectdata *conn) |  | ||||||
| { |  | ||||||
|   des_cblock key; |  | ||||||
|   des_key_schedule schedule; |  | ||||||
|   KTEXT_ST tkt, tktcopy; |  | ||||||
|   char *name; |  | ||||||
|   char *p; |  | ||||||
|   char passwd[100]; |  | ||||||
|   size_t tmp = 0; |  | ||||||
|   ssize_t nread; |  | ||||||
|   enum protection_level save; |  | ||||||
|   CURLcode result; |  | ||||||
|   unsigned char *ptr; |  | ||||||
|   size_t base64_sz = 0; |  | ||||||
|  |  | ||||||
|   save = krb4_set_command_prot(conn, PROT_PRIVATE); |  | ||||||
|  |  | ||||||
|   result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->user); |  | ||||||
|  |  | ||||||
|   if(result) |  | ||||||
|     return result; |  | ||||||
|  |  | ||||||
|   result = Curl_GetFTPResponse(&nread, conn, NULL); |  | ||||||
|   if(result) |  | ||||||
|     return result; |  | ||||||
|  |  | ||||||
|   if(conn->data->state.buffer[0] != '3') { |  | ||||||
|     krb4_set_command_prot(conn, save); |  | ||||||
|     return CURLE_FTP_WEIRD_SERVER_REPLY; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   p = strstr(conn->data->state.buffer, "T="); |  | ||||||
|   if(!p) { |  | ||||||
|     Curl_failf(conn->data, "Bad reply from server"); |  | ||||||
|     krb4_set_command_prot(conn, save); |  | ||||||
|     return CURLE_FTP_WEIRD_SERVER_REPLY; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   p += 2; |  | ||||||
|   result = Curl_base64_decode(p, &ptr, &tmp); |  | ||||||
|   if(result) { |  | ||||||
|     Curl_failf(conn->data, "base64-decoding: %s", curl_easy_strerror(result)); |  | ||||||
|     return result; |  | ||||||
|   } |  | ||||||
|   if(tmp >= sizeof(tkt.dat)) { |  | ||||||
|     free(ptr); |  | ||||||
|     ptr = NULL; |  | ||||||
|     tmp = 0; |  | ||||||
|   } |  | ||||||
|   if(!tmp || !ptr) { |  | ||||||
|     Curl_failf(conn->data, "Failed to decode base64 in reply"); |  | ||||||
|     krb4_set_command_prot(conn, save); |  | ||||||
|     return CURLE_FTP_WEIRD_SERVER_REPLY; |  | ||||||
|   } |  | ||||||
|   memcpy((char *)tkt.dat, ptr, tmp); |  | ||||||
|   free(ptr); |  | ||||||
|   tkt.length = tmp; |  | ||||||
|   tktcopy.length = tkt.length; |  | ||||||
|  |  | ||||||
|   p = strstr(conn->data->state.buffer, "P="); |  | ||||||
|   if(!p) { |  | ||||||
|     Curl_failf(conn->data, "Bad reply from server"); |  | ||||||
|     krb4_set_command_prot(conn, save); |  | ||||||
|     return CURLE_FTP_WEIRD_SERVER_REPLY; |  | ||||||
|   } |  | ||||||
|   name = p + 2; |  | ||||||
|   for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++); |  | ||||||
|   *p = 0; |  | ||||||
|  |  | ||||||
|   des_string_to_key (conn->passwd, &key); |  | ||||||
|   des_key_sched(&key, schedule); |  | ||||||
|  |  | ||||||
|   des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat, |  | ||||||
|                    tkt.length, |  | ||||||
|                    schedule, &key, DES_DECRYPT); |  | ||||||
|   if(strcmp ((char*)tktcopy.dat + 8, |  | ||||||
|               KRB_TICKET_GRANTING_TICKET) != 0) { |  | ||||||
|     afs_string_to_key(passwd, |  | ||||||
|                       krb_realmofhost(conn->host.name), |  | ||||||
|                       &key); |  | ||||||
|     des_key_sched(&key, schedule); |  | ||||||
|     des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat, |  | ||||||
|                      tkt.length, |  | ||||||
|                      schedule, &key, DES_DECRYPT); |  | ||||||
|   } |  | ||||||
|   memset(key, 0, sizeof(key)); |  | ||||||
|   memset(schedule, 0, sizeof(schedule)); |  | ||||||
|   memset(passwd, 0, sizeof(passwd)); |  | ||||||
|   result = Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length, |  | ||||||
|                               &p, &base64_sz); |  | ||||||
|   if(result) { |  | ||||||
|     Curl_failf(conn->data, "base64-encoding: %s", curl_easy_strerror(result)); |  | ||||||
|     krb4_set_command_prot(conn, save); |  | ||||||
|     return result; |  | ||||||
|   } |  | ||||||
|   memset (tktcopy.dat, 0, tktcopy.length); |  | ||||||
|  |  | ||||||
|   result = Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p); |  | ||||||
|   free(p); |  | ||||||
|   if(result) |  | ||||||
|     return result; |  | ||||||
|  |  | ||||||
|   result = Curl_GetFTPResponse(&nread, conn, NULL); |  | ||||||
|   if(result) |  | ||||||
|     return result; |  | ||||||
|   krb4_set_command_prot(conn, save); |  | ||||||
|  |  | ||||||
|   return CURLE_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif /* HAVE_KRB4 */ |  | ||||||
| #endif /* CURL_DISABLE_FTP */ |  | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| /* GSSAPI/krb5 support for FTP - loosely based on old krb4.c | /* GSSAPI/krb5 support for FTP - loosely based on old krb4.c | ||||||
|  * |  * | ||||||
|  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan |  * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2013 Kungliga Tekniska H<>gskolan | ||||||
|  * (Royal Institute of Technology, Stockholm, Sweden). |  * (Royal Institute of Technology, Stockholm, Sweden). | ||||||
|  * Copyright (c) 2004 - 2012 Daniel Stenberg |  * Copyright (c) 2004 - 2012 Daniel Stenberg | ||||||
|  * All rights reserved. |  * All rights reserved. | ||||||
| @@ -51,7 +51,7 @@ | |||||||
| #include "ftp.h" | #include "ftp.h" | ||||||
| #include "curl_gssapi.h" | #include "curl_gssapi.h" | ||||||
| #include "sendf.h" | #include "sendf.h" | ||||||
| #include "krb4.h" | #include "curl_sec.h" | ||||||
| #include "curl_memory.h" | #include "curl_memory.h" | ||||||
| #include "warnless.h" | #include "warnless.h" | ||||||
|  |  | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user