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_INET_NTOA_R_DECL 0)
|
||||
set(HAVE_INET_NTOA_R_DECL_REENTRANT 0)
|
||||
if(ENABLE_IPV6)
|
||||
set(HAVE_GETADDRINFO 1)
|
||||
else()
|
||||
set(HAVE_GETADDRINFO 0)
|
||||
endif()
|
||||
set(STDC_HEADERS 1)
|
||||
set(RETSIGTYPE_TEST 1)
|
||||
|
||||
|
||||
@@ -783,6 +783,17 @@ else()
|
||||
set(CURL_SIZEOF_CURL_SOCKLEN_T ${SIZEOF_INT})
|
||||
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)
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
|
||||
@@ -148,12 +148,24 @@ vc-ssl-zlib: $(VC)
|
||||
cd ..\src
|
||||
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)
|
||||
cd lib
|
||||
nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-ssl-zlib
|
||||
cd ..\src
|
||||
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)
|
||||
cd lib
|
||||
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
|
||||
Command line options: 152
|
||||
curl_easy_setopt() options: 199
|
||||
Public curl releases: 136
|
||||
Command line options: 161
|
||||
curl_easy_setopt() options: 206
|
||||
Public functions in libcurl: 58
|
||||
Known libcurl bindings: 42
|
||||
Contributors: 1005
|
||||
Contributors: 1104
|
||||
|
||||
***
|
||||
krb4 support is up for removal. If you care about it at all, speak up
|
||||
on the curl-library list asap!
|
||||
***
|
||||
This release includes the following security fix:
|
||||
o gtls: respect *VERIFYHOST independently of *VERIFYPEER [26]
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o darwinssl: add TLS session resumption
|
||||
o darwinssl: add TLS crypto authentication
|
||||
o imap/pop3/smtp: Added support for ;auth=<mech> in the URL
|
||||
o imap/pop3/smtp: Added support for ;auth=<mech> to CURLOPT_USERPWD
|
||||
o usercertinmem.c: add example showing user cert in memory
|
||||
o url: Added smtp and pop3 hostnames to the protocol detection list
|
||||
o imap/pop3/smtp: Added support for enabling the SASL initial response [8]
|
||||
o curl -E: allow to use ':' in certificate nicknames [10]
|
||||
o SSL: protocol version can be specified more precisely [1]
|
||||
o imap/pop3/smtp: Added graceful cancellation of SASL authentication
|
||||
o Add "Happy Eyeballs" for IPv4/IPv6 dual connect attempts
|
||||
o base64: Added validation of base64 input strings when decoding [8]
|
||||
o curl_easy_setopt: Added the ability to set the login options separately
|
||||
o smtp: Added support for additional SMTP commands
|
||||
o curl_easy_getinfo: Added CURLINFO_TLS_SESSION for accessing TLS internals
|
||||
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:
|
||||
|
||||
o SECURITY VULNERABILITY: curl_easy_unescape() may parse data beyond the end
|
||||
of the input buffer [26]
|
||||
|
||||
o FTP: access files in root dir correctly [1]
|
||||
o configure: try pthread_create without -lpthread [2]
|
||||
o FTP: handle a 230 welcome response [3]
|
||||
o curl-config: don't output static libs when they are disabled
|
||||
o CURL_CHECK_CA_BUNDLE: don't check for paths when cross-compiling [4]
|
||||
o Various documentation updates
|
||||
o getinfo.c: reset timecond when clearing session-info variables [5]
|
||||
o FILE: prevent an artificial timeout event due to stale speed-check data [6]
|
||||
o ftp_state_pasv_resp: connect through proxy also when set by env [7]
|
||||
o sshserver: disable StrictHostKeyChecking
|
||||
o ftpserver: Fixed imap logout confirmation data
|
||||
o curl_easy_init: use less mallocs
|
||||
o smtp: Fixed unknown percentage complete in progress bar
|
||||
o smtp: Fixed sending of double CRLF caused by first in EOB
|
||||
o bindlocal: move brace out of #ifdef [9]
|
||||
o winssl: Fixed invalid memory access during SSL shutdown [11]
|
||||
o OS X framework: fix invalid symbolic link
|
||||
o OpenSSL: allow empty server certificate subject [12]
|
||||
o axtls: prevent memleaks on SSL handshake failures
|
||||
o cookies: only consider full path matches
|
||||
o Revert win32 MemoryTracking: wcsdup() _wcsdup() and _tcsdup() [13]
|
||||
o Curl_cookie_add: handle IPv6 hosts [14]
|
||||
o ossl_send: SSL_write() returning 0 is an error too
|
||||
o ossl_recv: SSL_read() returning 0 is an error too
|
||||
o Digest auth: escape user names with \ or " in them [15]
|
||||
o curl_formadd.3: fixed wrong "end-marker" syntax [16]
|
||||
o libcurl-tutorial.3: fix incorrect backslash [17]
|
||||
o curl_multi_wait: reduce timeout if the multi handle wants to [18]
|
||||
o tests/Makefile: typo in the perlcheck target [19]
|
||||
o axtls: honor disabled VERIFYHOST
|
||||
o OpenSSL: avoid double free in the PKCS12 certificate code [20]
|
||||
o multi_socket: reduce timeout inaccuracy margin [21]
|
||||
o digest: support auth-int for empty entity body [22]
|
||||
o axtls: now done non-blocking
|
||||
o lib1900: use tutil_tvnow instead of gettimeofday
|
||||
o curl_easy_perform: avoid busy-looping [23]
|
||||
o CURLOPT_COOKIELIST: take cookie share lock [24]
|
||||
o multi_socket: react on socket close immediately [25]
|
||||
o darwinssl: un-break iOS build after PKCS#12 feature added
|
||||
o tool: use XFERFUNCTION to save some casts [2]
|
||||
o usercertinmem: fix memory leaks
|
||||
o ssh: Handle successful SSH_USERAUTH_NONE [3]
|
||||
o NSS: acknowledge the --no-sessionid/CURLOPT_SSL_SESSIONID_CACHE option [4]
|
||||
o test906: Fixed failing test on some platforms [5]
|
||||
o sasl: initialize NSS before using NTLM crypto
|
||||
o sasl: Fixed memory leak in OAUTH2 message creation
|
||||
o imap/pop3/smtp: Fixed QUIT / LOGOUT being sent when SSL connect fails
|
||||
o cmake: unbreak for non-Windows platforms [6]
|
||||
o ssh: initialize per-handle data in ssh_connect()
|
||||
o glob: fix broken URLs
|
||||
o configure: check for long long when building with cyassl
|
||||
o CURLOPT_RESOLVE: mention they don't time-out [7]
|
||||
o docs/examples/httpput.c: fix build for MSVC
|
||||
o FTP: make the data connection work when going through proxy
|
||||
o NSS: support for CERTINFO feature
|
||||
o curl_multi_wait: accept 0 from multi_timeout() as valid timeout
|
||||
o glob_range: pass the closing bracket for a-z ranges
|
||||
o tool_help: Updated --list-only description to include POP3
|
||||
o Curl_ssl_push_certinfo_len: don't %.*s non-zero-terminated string [9]
|
||||
o cmake: fix Windows build with IPv6 support [10]
|
||||
o ares: Fixed compilation under Visual Studio 2012 [11]
|
||||
o curl_easy_setopt.3: clarify CURLOPT_SSL_VERIFYHOST documentation [12]
|
||||
o curl.1: mention that -O does no URL decoding [13]
|
||||
o darwinssl: PKCS#12 import feature now requires Lion or later [14]
|
||||
o darwinssl: check for SSLSetSessionOption() presence when toggling BEAST
|
||||
o configure: Fix test with -Werror=implicit-function-declaration [15]
|
||||
o sigpipe: factor out sigpipe_reset from easy.c
|
||||
o curl_multi_cleanup: ignore SIGPIPE
|
||||
o globbing: curl glob counter mismatch with {} list use [16]
|
||||
o parseconfig: dash options can't specified with colon or equals [17]
|
||||
o digest: fix CURLAUTH_DIGEST_IE [19]
|
||||
o curl.h: <sys/select.h> for OpenBSD [20]
|
||||
o darwinssl: Fix #if 10.6.0 for SecKeychainSearch
|
||||
o TFTP: fix return codes for connect timeout [21]
|
||||
o login options: remove the ;[options] support from CURLOPT_USERPWD [23]
|
||||
o imap: Fixed incorrect fallback to clear text authentication
|
||||
o parsedate: avoid integer overflow
|
||||
o curl.1: document -J doesn't %-decode [25]
|
||||
o multi: add timer inaccuracy margin to timeout/connecttimeout [24]
|
||||
|
||||
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
|
||||
advice from friends like these:
|
||||
|
||||
David Strauss, Kamil Dudka, Steve Holme, Nick Zitzmann, Sam Deane, Duncan,
|
||||
Anders Havn, Dan Fandrich, Paul Howarth, Dave Reisner, Wouter Van Rooy,
|
||||
Linus Nielsen Feltzing, Ishan SinghLevett, Alessandro Ghedini,
|
||||
Ludovico Cavedon, Zdenek Pavlas, Zekun Ni, Lars Johannesen, Marc Hoersken,
|
||||
Renaud Guillard, John Gardiner Myers, Jared Jennings, Eric Hu,
|
||||
Yamada Yasuharu, Stefan Neis, Mike Giancola, Eric S. Raymond, Andrii Moiseiev,
|
||||
Christian Weisgerber, Peter Gal, Aleksey Tulinov, Hang Su, Sergei Nikulov,
|
||||
Miguel Angel, Nach M. S., Benjamin Gilbert, Erik Johansson, Timo Sirainen,
|
||||
Guenter Knauf
|
||||
Alessandro Ghedini, Andreas Rieke, Björn Stenberg, Chris Conlon,
|
||||
Christian Grothoff, Christian Weisgerber, Dave Reisner, David Walser,
|
||||
Dima Tisnek, Fabian Keil, Felix Yan, Gergely Nagy, Gisle Vanem,
|
||||
Ishan SinghLevett, James Dury, Javier Barroso, Jeff King, Kamil Dudka,
|
||||
Kim Vandry, Marcin Gryszkalis, Melissa Mears, Michael Osipov, Nick Zitzmann,
|
||||
Oliver Kuckertz, Patrick Monnerat, Paul Donohue, Paul Marks, Romulo A. Ceccon,
|
||||
Rémy Léone, Sergey Tatarincev, Steve Holme, Tomas Hoger, Tyler Hall,
|
||||
Yaakov Selkowitz, Eric Lubin, Petr Bahula, He Qin, Marc Deslauriers
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
||||
References to bug reports and discussions on issues:
|
||||
|
||||
[1] = http://curl.haxx.se/mail/lib-2013-04/0142.html
|
||||
[2] = http://curl.haxx.se/bug/view.cgi?id=1216
|
||||
[3] = http://curl.haxx.se/mail/lib-2013-02/0102.html
|
||||
[4] = http://curl.haxx.se/mail/lib-2013-04/0294.html
|
||||
[5] = http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=705783
|
||||
[6] = https://bugzilla.redhat.com/906031
|
||||
[7] = http://curl.haxx.se/bug/view.cgi?id=1218
|
||||
[8] = http://curl.haxx.se/mail/lib-2012-03/0114.html
|
||||
[9] = http://curl.haxx.se/mail/lib-2013-05/0000.html
|
||||
[10] = http://curl.haxx.se/bug/view.cgi?id=1196
|
||||
[11] = http://curl.haxx.se/bug/view.cgi?id=1219
|
||||
[12] = http://curl.haxx.se/bug/view.cgi?id=1220
|
||||
[13] = http://curl.haxx.se/mail/lib-2013-05/0070.html
|
||||
[14] = http://curl.haxx.se/bug/view.cgi?id=1221
|
||||
[15] = http://curl.haxx.se/bug/view.cgi?id=1230
|
||||
[16] = http://curl.haxx.se/bug/view.cgi?id=1233
|
||||
[17] = http://curl.haxx.se/bug/view.cgi?id=1234
|
||||
[18] = http://curl.haxx.se/bug/view.cgi?id=1224
|
||||
[19] = http://curl.haxx.se/bug/view.cgi?id=1239
|
||||
[20] = http://curl.haxx.se/bug/view.cgi?id=1236
|
||||
[21] = http://curl.haxx.se/bug/view.cgi?id=1228
|
||||
[22] = http://curl.haxx.se/bug/view.cgi?id=1235
|
||||
[23] = http://curl.haxx.se/bug/view.cgi?id=1238
|
||||
[24] = http://curl.haxx.se/bug/view.cgi?id=1215
|
||||
[25] = http://curl.haxx.se/bug/view.cgi?id=1248
|
||||
[26] = http://curl.haxx.se/docs/adv_20130622.html
|
||||
[1] = https://github.com/bagder/curl/pull/79
|
||||
[2] = http://curl.haxx.se/mail/lib-2013-10/0089.html
|
||||
[3] = http://curl.haxx.se/mail/lib-2013-10/0096.html
|
||||
[4] = http://curl.haxx.se/mail/lib-2013-10/0113.html
|
||||
[5] = http://sourceforge.net/p/curl/bugs/1291
|
||||
[6] = http://sourceforge.net/p/curl/bugs/1292
|
||||
[7] = http://curl.haxx.se/mail/lib-2013-10/0062.html
|
||||
[8] = http://curl.haxx.se/mail/lib-2013-10/0242.html
|
||||
[9] = http://curl.haxx.se/bug/view.cgi?id=1295
|
||||
[10] = http://sourceforge.net/p/curl/bugs/1064
|
||||
[11] = http://curl.haxx.se/mail/lib-2013-11/0057.html
|
||||
[12] = https://github.com/bagder/curl/pull/83
|
||||
[13] = http://sourceforge.net/p/curl/bugs/1299
|
||||
[14] = http://curl.haxx.se/mail/lib-2013-11/0076.html
|
||||
[15] = http://curl.haxx.se/bug/view.cgi?id=1304
|
||||
[16] = http://curl.haxx.se/bug/view.cgi?id=1305
|
||||
[17] = http://curl.haxx.se/bug/view.cgi?id=1297
|
||||
[18] = http://curl.haxx.se/mail/lib-2013-11/0162.html
|
||||
[19] = http://curl.haxx.se/bug/view.cgi?id=1308
|
||||
[20] = http://curl.haxx.se/mail/lib-2013-12/0017.html
|
||||
[21] = http://curl.haxx.se/bug/view.cgi?id=1310
|
||||
[22] = http://curl.haxx.se/dev/security.html
|
||||
[23] = http://curl.haxx.se/bug/view.cgi?id=1311
|
||||
[24] = http://curl.haxx.se/bug/view.cgi?id=1298
|
||||
[25] = http://curl.haxx.se/bug/view.cgi?id=1294
|
||||
[26] = http://curl.haxx.se/docs/adv_20131217.html
|
||||
|
||||
13
acinclude.m4
13
acinclude.m4
@@ -2619,18 +2619,18 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
|
||||
fi
|
||||
capath="$want_capath"
|
||||
ca="no"
|
||||
elif test "x$cross_compiling" != "xyes"; then
|
||||
dnl NOT cross-compiling and...
|
||||
dnl neither of the --with-ca-* options are provided
|
||||
|
||||
else
|
||||
dnl first try autodetecting a CA bundle , then a CA path
|
||||
dnl both autodetections can be skipped by --without-ca-*
|
||||
ca="no"
|
||||
capath="no"
|
||||
if test "x$cross_compiling" != "xyes"; then
|
||||
dnl NOT cross-compiling and...
|
||||
dnl neither of the --with-ca-* options are provided
|
||||
if test "x$want_ca" = "xunset"; then
|
||||
dnl the path we previously would have installed the curl ca bundle
|
||||
dnl to, and thus we now check for an already existing cert in that place
|
||||
dnl in case we find no other
|
||||
dnl to, and thus we now check for an already existing cert in that
|
||||
dnl place in case we find no other
|
||||
if test "x$prefix" != xNONE; then
|
||||
cac="${prefix}/share/curl/curl-ca-bundle.crt"
|
||||
else
|
||||
@@ -2662,6 +2662,7 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
|
||||
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
|
||||
CURL_CA_BUNDLE='"'$ca'"'
|
||||
|
||||
211
configure.ac
211
configure.ac
@@ -126,7 +126,7 @@ fi
|
||||
dnl figure out the libcurl version
|
||||
CURLVERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curlver.h`
|
||||
XC_CHECK_PROG_CC
|
||||
AM_INIT_AUTOMAKE
|
||||
XC_AUTOMAKE
|
||||
AC_MSG_CHECKING([curl version])
|
||||
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_ssh_msg="no (--with-libssh2)"
|
||||
curl_zlib_msg="no (--with-zlib)"
|
||||
curl_krb4_msg="no (--with-krb4*)"
|
||||
curl_gss_msg="no (--with-gssapi)"
|
||||
curl_spnego_msg="no (--with-spnego)"
|
||||
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? */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdlib.h> /* for exit() */
|
||||
main()
|
||||
{
|
||||
if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
|
||||
@@ -1134,101 +1134,6 @@ no)
|
||||
;;
|
||||
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 Check for FBopenssl(SPNEGO) libraries
|
||||
dnl **********************************************************************
|
||||
@@ -2079,6 +1984,9 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
|
||||
if test "x$USE_CYASSL" = "xyes"; then
|
||||
AC_MSG_NOTICE([detected CyaSSL])
|
||||
|
||||
dnl cyassl/ctaocrypt/types.h needs SIZEOF_LONG_LONG defined!
|
||||
AC_CHECK_SIZEOF(long long)
|
||||
|
||||
LIBS="-lcyassl -lm $LIBS"
|
||||
|
||||
if test -n "$cyassllib"; then
|
||||
@@ -2163,8 +2071,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
|
||||
CPPFLAGS="$CPPFLAGS $addcflags"
|
||||
fi
|
||||
|
||||
dnl The function PK11_CreateGenericObject is needed to load libnsspem.so
|
||||
AC_CHECK_LIB(nss3, PK11_CreateGenericObject,
|
||||
dnl The function SSL_VersionRangeSet() is needed to enable TLS > 1.0
|
||||
AC_CHECK_LIB(nss3, SSL_VersionRangeSet,
|
||||
[
|
||||
AC_DEFINE(USE_NSS, 1, [if NSS is enabled])
|
||||
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
|
||||
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 linker doesn't search through, we need to add it to
|
||||
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 **********************************************************************
|
||||
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 Back to "normal" configuring
|
||||
dnl **********************************************************************
|
||||
@@ -3365,9 +3351,6 @@ if test "x$USE_SSLEAY" = "x1"; then
|
||||
elif test -n "$SSL_ENABLED"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES SSL"
|
||||
fi
|
||||
if test "@KRB4_ENABLED@" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES KRB4"
|
||||
fi
|
||||
if test "x$IPV6_ENABLED" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6"
|
||||
fi
|
||||
@@ -3397,6 +3380,10 @@ if test "x$USE_TLS_SRP" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
|
||||
fi
|
||||
|
||||
if test "x$USE_NGHTTP2" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
|
||||
fi
|
||||
|
||||
AC_SUBST(SUPPORT_FEATURES)
|
||||
|
||||
dnl For supported protocols in pkg-config file
|
||||
@@ -3531,6 +3518,8 @@ AC_OUTPUT
|
||||
|
||||
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:
|
||||
|
||||
curl version: ${CURLVERSION}
|
||||
@@ -3540,7 +3529,6 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
|
||||
SSL support: ${curl_ssl_msg}
|
||||
SSH support: ${curl_ssh_msg}
|
||||
zlib support: ${curl_zlib_msg}
|
||||
krb4 support: ${curl_krb4_msg}
|
||||
GSSAPI support: ${curl_gss_msg}
|
||||
SPNEGO support: ${curl_spnego_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}
|
||||
RTMP support: ${curl_rtmp_msg}
|
||||
metalink support: ${curl_mtlnk_msg}
|
||||
HTTP2 support: ${curl_h2_msg}
|
||||
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
|
||||
@@ -79,9 +79,9 @@
|
||||
1.3 What To Read
|
||||
|
||||
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
|
||||
you a lot of insights on what's going on right now. Asking there is a good
|
||||
idea too.
|
||||
most recent CHANGES. Just lurking on the curl-library mailing list is gonna
|
||||
give you a lot of insights on what's going on right now. Asking there is a
|
||||
good idea too.
|
||||
|
||||
2. cURL Coding Standards
|
||||
|
||||
@@ -98,12 +98,12 @@
|
||||
|
||||
2.2 Indenting
|
||||
|
||||
Please try using the same indenting levels and bracing method as all the
|
||||
other code already does. It makes the source code a lot easier to follow if
|
||||
all of it is written using the same style. We don't ask you to like it, we
|
||||
just ask you to follow the tradition! ;-) This mainly means: 2-level indents,
|
||||
using spaces only (no tabs) and having the opening brace ({) on the same line
|
||||
as the if() or while().
|
||||
Use the same indenting levels and bracing method as all the other code
|
||||
already does. It makes the source code easier to follow if all of it is
|
||||
written using the same style. We don't ask you to like it, we just ask you to
|
||||
follow the tradition! ;-) This mainly means: 2-level indents, using spaces
|
||||
only (no tabs) and having the opening brace ({) on the same line as the if()
|
||||
or while().
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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.1 Write Access to git Repository
|
||||
|
||||
102
docs/FAQ
102
docs/FAQ
@@ -202,27 +202,25 @@ FAQ
|
||||
better. We do however believe in a few rules when it comes to the future of
|
||||
curl:
|
||||
|
||||
* 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
|
||||
for another tool that uses libcurl.
|
||||
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 for
|
||||
another tool that uses libcurl.
|
||||
|
||||
* We do not add things to curl that other small and available tools already
|
||||
do very fine at the side. Curl's output is fine to pipe into another
|
||||
program or redirect to another file for the next program to interpret.
|
||||
We do not add things to curl that other small and available tools already do
|
||||
very fine at the side. Curl's output is fine to pipe into another program or
|
||||
redirect to another file for the next program to interpret.
|
||||
|
||||
* We focus on protocol related issues and improvements. If you wanna do more
|
||||
magic with the supported protocols than curl currently does, chances are
|
||||
big we will agree. If you wanna add more protocols, we may very well
|
||||
agree.
|
||||
We focus on protocol related issues and improvements. If you wanna do more
|
||||
magic with the supported protocols than curl currently does, chances are big
|
||||
we will agree. If you wanna add more protocols, we may very well 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
|
||||
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
|
||||
efforts in return.
|
||||
|
||||
* If you write the code, chances are bigger that it will get into curl
|
||||
faster.
|
||||
If you write the code, chances are bigger that it will get into curl faster.
|
||||
|
||||
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
|
||||
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
|
||||
every success.
|
||||
@@ -620,15 +618,15 @@ FAQ
|
||||
|
||||
Some workarounds usually suggested to overcome this Javascript dependency:
|
||||
|
||||
- Depending on the Javascript complexity, write up a script that
|
||||
translates it to another language and execute that.
|
||||
Depending on the Javascript complexity, write up a script that translates it
|
||||
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.
|
||||
|
||||
- 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?
|
||||
|
||||
@@ -644,23 +642,27 @@ FAQ
|
||||
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.
|
||||
|
||||
- Client certificate. The server you communicate may require that you can
|
||||
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.
|
||||
CLIENT CERTIFICATE
|
||||
|
||||
The server you communicate may require that you can 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
|
||||
private key has a pass phrase that protects it.
|
||||
|
||||
- Server certificate. The server you communicate with has a server
|
||||
certificate. You can and should verify this certificate to make sure that
|
||||
you are truly talking to the real server and not a server impersonating
|
||||
it.
|
||||
SERVER CERTIFICATE
|
||||
|
||||
- Certificate Authority certificate ("CA cert"). You often have several CA
|
||||
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 you communicate with has a server certificate. You can and should
|
||||
verify this certificate to make sure that you are truly talking to the real
|
||||
server and not a server impersonating it.
|
||||
|
||||
CERTIFICATE AUTHORITY CERTIFICATE ("CA cert")
|
||||
|
||||
You often have several CA 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
|
||||
Authority certificate ("CA cert") that was used to sign the server
|
||||
@@ -669,9 +671,9 @@ FAQ
|
||||
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.
|
||||
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?
|
||||
|
||||
@@ -794,12 +796,13 @@ FAQ
|
||||
|
||||
curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl'
|
||||
|
||||
In Windows, the standard DOS shell treats the %-symbol specially and you
|
||||
need to use TWO %-symbols for each single one you want to use in the URL.
|
||||
In Windows, the standard DOS shell treats the percent sign specially and you
|
||||
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
|
||||
pass in a POST using -d/--data you must encode it as '%25' (which then also
|
||||
needs the %-symbol doubled on Windows machines).
|
||||
If you want a literal percent sign to be part of the data you pass in a POST
|
||||
using -d/--data you must encode it as '%25' (which then also needs the
|
||||
percent sign doubled on Windows machines).
|
||||
|
||||
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!
|
||||
|
||||
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
|
||||
redirect to another given URL after a certain time.
|
||||
Meta tags. You can write a HTML tag that will cause the browser to redirect
|
||||
to another given URL after a certain time.
|
||||
|
||||
- Javascript. You can write a Javascript program embedded in a HTML page
|
||||
that redirects the browser to another given URL.
|
||||
Javascript. You can write a Javascript program embedded in a HTML page that
|
||||
redirects the browser to another given URL.
|
||||
|
||||
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
|
||||
@@ -1270,17 +1273,18 @@ FAQ
|
||||
|
||||
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
|
||||
would imply sending IP packages with a made-up source address, and then you
|
||||
normally get a problem with intercepting the packages sent back as they
|
||||
would then not be routed to you!
|
||||
No. libcurl operates on a higher level. Besides, faking IP address would
|
||||
imply sending IP packet with a made-up source address, and then you normally
|
||||
get a problem with receiving the packet sent back as they would then not be
|
||||
routed to you!
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
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?
|
||||
|
||||
|
||||
@@ -1045,7 +1045,7 @@ PORTS
|
||||
- Alpha OpenVMS V7.1-1H2
|
||||
- Alpha Tru64 v5.0 5.1
|
||||
- AVR32 Linux
|
||||
- ARM Android 1.5, 2.1
|
||||
- ARM Android 1.5, 2.1, 2.3, 3.2, 4.x
|
||||
- ARM INTEGRITY
|
||||
- ARM iOS
|
||||
- Cell Linux
|
||||
@@ -1116,6 +1116,7 @@ GNU GSS http://www.gnu.org/software/gss/
|
||||
GnuTLS http://www.gnu.org/software/gnutls/
|
||||
Heimdal http://www.pdc.kth.se/heimdal/
|
||||
libidn http://www.gnu.org/software/libidn/
|
||||
libmetalink https://launchpad.net/libmetalink/
|
||||
libssh2 http://www.libssh2.org/
|
||||
MIT Kerberos http://web.mit.edu/kerberos/www/dist/
|
||||
NSS http://www.mozilla.org/projects/security/pki/nss/
|
||||
|
||||
115
docs/INTERNALS
115
docs/INTERNALS
@@ -43,7 +43,7 @@ Portability
|
||||
openldap 2.0
|
||||
MIT krb5 lib 1.2.4
|
||||
qsossl V5R3M0
|
||||
NSS 3.12.x
|
||||
NSS 3.14.x
|
||||
axTLS 1.2.7
|
||||
Heimdal ?
|
||||
|
||||
@@ -111,6 +111,9 @@ Windows vs Unix
|
||||
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
|
||||
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
|
||||
@@ -135,16 +138,18 @@ Library
|
||||
options is documented in the man page. This function mainly sets things in
|
||||
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
|
||||
work then continues in lib/url.c. The flow continues with a call to
|
||||
Curl_connect() to connect to the remote site.
|
||||
Some of the most important key functions in url.c are called from multi.c
|
||||
when certain key steps are to be made in the transfer operation.
|
||||
|
||||
o Curl_connect()
|
||||
|
||||
... analyzes the URL, it separates the different components and connects to
|
||||
the remote host. This may involve using a proxy and/or using SSL. The
|
||||
Analyzes the URL, it separates the different components and connects to 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
|
||||
(it does then use the proper underlying method, which may vary between
|
||||
platforms and builds).
|
||||
@@ -160,10 +165,7 @@ Library
|
||||
o Curl_do()
|
||||
|
||||
Curl_do() makes sure the proper protocol-specific function is called. The
|
||||
functions are named after the protocols they handle. Curl_ftp(),
|
||||
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().
|
||||
functions are named after the protocols they handle.
|
||||
|
||||
The protocol-specific functions of course deal with protocol-specific
|
||||
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)
|
||||
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
|
||||
entire file transfer.
|
||||
Called during the transfer of the actual protocol payload.
|
||||
|
||||
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
|
||||
@@ -207,33 +208,11 @@ Library
|
||||
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
|
||||
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
|
||||
can be changed with the CURLOPT_MAXCONNECTS option).
|
||||
connections alive at the same time.
|
||||
|
||||
This function cleans up all resources that are associated with a single
|
||||
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)
|
||||
|
||||
@@ -316,48 +295,38 @@ Persistent Connections
|
||||
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.
|
||||
o The 'SessionHandle' struct holds the "connection cache" (an array of
|
||||
pointers to 'connectdata' structs). There's one connectdata struct
|
||||
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.
|
||||
pointers to 'connectdata' structs).
|
||||
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
|
||||
check for an already existing connection in the cache that we can use,
|
||||
otherwise we create a new one and add to the cache. If the cache is full
|
||||
already when we add a new connection, we close one of the present ones. We
|
||||
select which one to close dependent on the close policy that may have been
|
||||
previously set.
|
||||
o When the transfer operation is complete, we try to leave the connection
|
||||
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 libcurl is told to perform a transfer, it first checks for an already
|
||||
existing connection in the cache that we can use. Otherwise it creates a
|
||||
new one and adds that the cache. If the cache is full already when a new
|
||||
conncetion is added added, it will first close the oldest unused one.
|
||||
o When the transfer operation is complete, the connection is left
|
||||
open. Particular options may tell libcurl not to, and protocols may signal
|
||||
closure on connections and then they won't be kept open of course.
|
||||
o When curl_easy_cleanup() is called, we close all still opened 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
|
||||
persistent connections to work.
|
||||
The curl handle must be re-used in order for the persistent connections to
|
||||
work.
|
||||
|
||||
multi interface/non-blocking
|
||||
============================
|
||||
|
||||
We make an effort to provide a non-blocking interface to the library, the
|
||||
multi interface. To make that interface work as good as possible, no
|
||||
low-level functions within libcurl must be written to work in a blocking
|
||||
manner.
|
||||
The multi interface is a non-blocking interface to the library. To make that
|
||||
interface work as good as possible, no low-level functions within libcurl
|
||||
must be written to work in a blocking manner. (There are still a few spots
|
||||
violating this rule.)
|
||||
|
||||
One of the primary reasons we introduced c-ares support was to allow the name
|
||||
resolve phase to be perfectly non-blocking as well.
|
||||
|
||||
The ultimate goal is to provide the easy interface simply by wrapping the
|
||||
multi interface functions and thus treat everything internally as the multi
|
||||
interface is the single interface we have.
|
||||
|
||||
The FTP and the SFTP/SCP protocols are thus perfect examples of how we adapt
|
||||
and adjust the code to allow non-blocking operations even on multi-stage
|
||||
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.
|
||||
The FTP and the SFTP/SCP protocols are examples of how we adapt and adjust
|
||||
the code to allow non-blocking operations even on multi-stage command-
|
||||
response protocols. They are built around state machines that return when
|
||||
they would otherwise 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
|
||||
=============
|
||||
@@ -408,12 +377,12 @@ API/ABI
|
||||
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
|
||||
to display the complete "manual" and the src/urlglob.c file holds the
|
||||
functions used for the URL-"globbing" support. Globbing in the sense that
|
||||
the {} and [] expansion stuff is there.
|
||||
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 the
|
||||
{} and [] expansion stuff is there.
|
||||
|
||||
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
|
||||
@@ -425,8 +394,8 @@ Client
|
||||
curl_easy_getinfo() function to extract useful information from the curl
|
||||
session.
|
||||
|
||||
Recent versions may loop and do all this several times if many URLs were
|
||||
specified on the command line or config file.
|
||||
It may loop and do all this several times if many URLs were specified on the
|
||||
command line or config file.
|
||||
|
||||
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
|
||||
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
|
||||
"tlib" tool doesn't support hyphens (minus signs) in file names and we have
|
||||
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
|
||||
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
|
||||
failure if one of the recipients indicate failure (on the "RCPT TO"
|
||||
command). Ordinary mail programs would proceed and still send to the ones
|
||||
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"
|
||||
zero bytes files - it makes for example the command line client not creating
|
||||
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
|
||||
"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
|
||||
backend. The original problem was mentioned in:
|
||||
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
|
||||
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"
|
||||
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:
|
||||
http://curl.haxx.se/bug/view.cgi?id=2844077
|
||||
http://curl.haxx.se/bug/view.cgi?id=856
|
||||
|
||||
72. "Pausing pipeline problems."
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
server using the multi interface, the commands are not being sent correctly
|
||||
and instead the connection is "cancelled" (the operation is considered done)
|
||||
prematurely. There is a half-baked (busy-looping) patch provided in the bug
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
when logging in), the operation will fail since libcurl doesn't detect this
|
||||
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:
|
||||
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.
|
||||
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
|
||||
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
|
||||
special. According to the reporter, Firefox deals with the URL _with_ a
|
||||
percent letter (which seems like a blatant URL spec violation).
|
||||
libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25).
|
||||
|
||||
See http://curl.haxx.se/bug/view.cgi?id=1371118
|
||||
libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25):
|
||||
http://curl.haxx.se/bug/view.cgi?id=555
|
||||
|
||||
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
|
||||
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:
|
||||
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
|
||||
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
|
||||
accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1
|
||||
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
|
||||
(fake) user name (this concerns both curl and the lib) because the code
|
||||
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
|
||||
|
||||
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
|
||||
# you should have received as part of this distribution. The terms
|
||||
@@ -22,7 +22,8 @@
|
||||
|
||||
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
|
||||
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 \
|
||||
KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL \
|
||||
$(PDFPAGES) LICENSE-MIXING README.netware DISTRO-DILEMMA INSTALL.devcpp \
|
||||
MAIL-ETIQUETTE HTTP-COOKIES
|
||||
MAIL-ETIQUETTE HTTP-COOKIES LIBCURL-STRUCTS SECURITY
|
||||
|
||||
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
|
||||
Alejandro Alvarez
|
||||
Aleksandar Milivojevic
|
||||
Aleksey Tulinov
|
||||
Alessandro Ghedini
|
||||
Alessandro Vesely
|
||||
Alex Bligh
|
||||
Alex Fishman
|
||||
Alex Gruz
|
||||
Alex McLellan
|
||||
Alex Neblett
|
||||
Alex Suykov
|
||||
Alex Vinnik
|
||||
@@ -47,11 +49,13 @@ Amol Pattekar
|
||||
Amr Shahin
|
||||
Anatoli Tubman
|
||||
Anders Gustafsson
|
||||
Anders Havn
|
||||
Andi Jahja
|
||||
Andre Guibert de Bruet
|
||||
Andreas Damm
|
||||
Andreas Faerber
|
||||
Andreas Farber
|
||||
Andreas Malzahn
|
||||
Andreas Ntaflos
|
||||
Andreas Olsson
|
||||
Andreas Rieke
|
||||
@@ -59,6 +63,7 @@ Andreas Schuldei
|
||||
Andreas Wurf
|
||||
Andrei Benea
|
||||
Andrei Cipu
|
||||
Andrej E Baranov
|
||||
Andres Garcia
|
||||
Andrew Benham
|
||||
Andrew Biggs
|
||||
@@ -69,6 +74,7 @@ Andrew Kurushin
|
||||
Andrew Moise
|
||||
Andrew Wansink
|
||||
Andrew de los Reyes
|
||||
Andrii Moiseiev
|
||||
Andrés García
|
||||
Andy Cedilnik
|
||||
Andy Serpa
|
||||
@@ -103,10 +109,13 @@ Ben Van Hof
|
||||
Ben Winslow
|
||||
Benbuck Nason
|
||||
Benjamin Gerard
|
||||
Benjamin Gilbert
|
||||
Benjamin Johnson
|
||||
Benoit Sigoure
|
||||
Bernard Leak
|
||||
Bernhard Reutner-Fischer
|
||||
Bertrand Demiddelaer
|
||||
Bill Doyle
|
||||
Bill Egert
|
||||
Bill Hoffman
|
||||
Bill Middlecamp
|
||||
@@ -136,6 +145,7 @@ Bruce Mitchener
|
||||
Bruno de Carvalho
|
||||
Bryan Henderson
|
||||
Bryan Kemp
|
||||
Byrial Jensen
|
||||
Cameron Kaiser
|
||||
Camille Moncelier
|
||||
Caolan McNamara
|
||||
@@ -148,6 +158,7 @@ Charles Kerr
|
||||
Chih-Chung Chang
|
||||
Chris "Bob Bob"
|
||||
Chris Combes
|
||||
Chris Conlon
|
||||
Chris Conroy
|
||||
Chris Deidun
|
||||
Chris Flerackers
|
||||
@@ -162,6 +173,7 @@ Christian Kurz
|
||||
Christian Robottom Reis
|
||||
Christian Schmitz
|
||||
Christian Vogt
|
||||
Christian Weisgerber
|
||||
Christophe Demory
|
||||
Christophe Legry
|
||||
Christopher Conroy
|
||||
@@ -174,6 +186,7 @@ Clarence Gardner
|
||||
Clemens Gruber
|
||||
Clifford Wolf
|
||||
Cody Jones
|
||||
Colby Ranger
|
||||
Colin Hogben
|
||||
Colin Watson
|
||||
Colm Buckley
|
||||
@@ -187,6 +200,7 @@ Cristian Rodríguez
|
||||
Curt Bogmine
|
||||
Cyrill Osterwalder
|
||||
Cédric Deltheil
|
||||
D. Flinkmann
|
||||
Dag Ekengren
|
||||
Dagobert Michelsen
|
||||
Damien Adant
|
||||
@@ -214,6 +228,7 @@ Dave Halbakken
|
||||
Dave Hamilton
|
||||
Dave May
|
||||
Dave Reisner
|
||||
Dave Thompson
|
||||
Dave Vasilevsky
|
||||
David Bau
|
||||
David Binderman
|
||||
@@ -234,15 +249,19 @@ David Odin
|
||||
David Phillips
|
||||
David Rosenstrauch
|
||||
David Shaw
|
||||
David Strauss
|
||||
David Tarendash
|
||||
David Thiel
|
||||
David Walser
|
||||
David Wright
|
||||
David Yan
|
||||
Dengminwen
|
||||
Derek Higgins
|
||||
Detlef Schmier
|
||||
Didier Brisebourg
|
||||
Diego Casorran
|
||||
Dima Barsky
|
||||
Dima Tisnek
|
||||
Dimitre Dimitrov
|
||||
Dimitris Sarris
|
||||
Dinar
|
||||
@@ -266,6 +285,7 @@ Douglas R. Horner
|
||||
Douglas Steinwand
|
||||
Dov Murik
|
||||
Duane Cathey
|
||||
Duncan
|
||||
Duncan Mac-Vicar Prett
|
||||
Dustin Boswell
|
||||
Dylan Ellicott
|
||||
@@ -274,11 +294,13 @@ Early Ehlinger
|
||||
Ebenezer Ikonne
|
||||
Edin Kadribasic
|
||||
Eduard Bloch
|
||||
Edward Rudd
|
||||
Edward Sheldrake
|
||||
Eelco Dolstra
|
||||
Eetu Ojanen
|
||||
Eldar Zaitov
|
||||
Ellis Pritchard
|
||||
Elmira A Semenova
|
||||
Emanuele Bovisio
|
||||
Emil Romanus
|
||||
Emiliano Ida
|
||||
@@ -288,27 +310,33 @@ Eric Cooper
|
||||
Eric Hu
|
||||
Eric Landes
|
||||
Eric Lavigne
|
||||
Eric Lubin
|
||||
Eric Melville
|
||||
Eric Mertens
|
||||
Eric Rautman
|
||||
Eric S. Raymond
|
||||
Eric Thelin
|
||||
Eric Vergnaud
|
||||
Eric Wong
|
||||
Eric Young
|
||||
Erick Nuwendam
|
||||
Erik Johansson
|
||||
Erwan Legrand
|
||||
Erwin Authried
|
||||
Eugene Kotlyarov
|
||||
Evan Jordan
|
||||
Evgeny Turnaev
|
||||
Eygene Ryabinkin
|
||||
Fabian Hiernaux
|
||||
Fabian Keil
|
||||
Fabrizio Ammollo
|
||||
Fedor Karpelevitch
|
||||
Felix Yan
|
||||
Felix von Leitner
|
||||
Feng Tu
|
||||
Florian Schoppmann
|
||||
Forrest Cahoon
|
||||
Francois Charlier
|
||||
Frank Hempel
|
||||
Frank Keeney
|
||||
Frank McGeough
|
||||
@@ -329,11 +357,13 @@ Gautam Kachroo
|
||||
Gautam Mani
|
||||
Gavrie Philipson
|
||||
Gaz Iqbal
|
||||
Geoff Beier
|
||||
Georg Horn
|
||||
Georg Huettenegger
|
||||
Georg Lippitsch
|
||||
Georg Wicherski
|
||||
Gerd v. Egidy
|
||||
Gergely Nagy
|
||||
Gerhard Herre
|
||||
Gerrit Bruchhäuser
|
||||
Ghennadi Procopciuc
|
||||
@@ -349,6 +379,8 @@ Giuseppe D'Ambrosio
|
||||
Glen Nakamura
|
||||
Glen Scott
|
||||
Gokhan Sengun
|
||||
Gordon Marler
|
||||
Gorilla Maguila
|
||||
Grant Erickson
|
||||
Greg Hewgill
|
||||
Greg Morse
|
||||
@@ -364,14 +396,17 @@ Gwenole Beauchesne
|
||||
Götz Babin-Ebell
|
||||
Hamish Mackenzie
|
||||
Hang Kin Lau
|
||||
Hang Su
|
||||
Hanno Kranzhoff
|
||||
Hans Steegers
|
||||
Hans-Jurgen May
|
||||
Hardeep Singh
|
||||
Harshal Pradhan
|
||||
Hauke Duden
|
||||
He Qin
|
||||
Heikki Korpela
|
||||
Heinrich Ko
|
||||
Heinrich Schaefer
|
||||
Hendrik Visage
|
||||
Henrik Storner
|
||||
Henry Ludemann
|
||||
@@ -398,6 +433,7 @@ Immanuel Gregoire
|
||||
Ingmar Runge
|
||||
Ingo Ralf Blum
|
||||
Ingo Wilken
|
||||
Ishan SinghLevett
|
||||
Jack Zhang
|
||||
Jacky Lam
|
||||
Jacob Meuser
|
||||
@@ -407,6 +443,7 @@ James Bursa
|
||||
James Cheng
|
||||
James Clancy
|
||||
James Cone
|
||||
James Dury
|
||||
James Gallagher
|
||||
James Griffiths
|
||||
James Housley
|
||||
@@ -419,12 +456,14 @@ Jan Koen Annot
|
||||
Jan Kunder
|
||||
Jan Schaumann
|
||||
Jan Van Boghout
|
||||
Jared Jennings
|
||||
Jared Lundell
|
||||
Jari Sundell
|
||||
Jason Glasgow
|
||||
Jason Liu
|
||||
Jason McDonald
|
||||
Jason S. Priebe
|
||||
Javier Barroso
|
||||
Jay Austin
|
||||
Jayesh A Shah
|
||||
Jaz Fresh
|
||||
@@ -433,9 +472,11 @@ Jean-Claude Chauve
|
||||
Jean-Francois Bertrand
|
||||
Jean-Louis Lemaire
|
||||
Jean-Marc Ranger
|
||||
Jean-Noel Rouvignac
|
||||
Jean-Philippe Barrette-LaPierre
|
||||
Jeff Connelly
|
||||
Jeff Johnson
|
||||
Jeff King
|
||||
Jeff Lawson
|
||||
Jeff Phillips
|
||||
Jeff Pohlmeyer
|
||||
@@ -445,6 +486,7 @@ Jeremy Friesner
|
||||
Jeremy Huddleston
|
||||
Jerome Muffat-Meridol
|
||||
Jerome Vouillon
|
||||
Jerry Krinock
|
||||
Jerry Wu
|
||||
Jes Badwal
|
||||
Jesper Jensen
|
||||
@@ -469,7 +511,9 @@ Johannes Bauer
|
||||
John Bradshaw
|
||||
John Crow
|
||||
John Dennis
|
||||
John Dunn
|
||||
John E. Malmberg
|
||||
John Gardiner Myers
|
||||
John Janssen
|
||||
John Joseph Bachir
|
||||
John Kelly
|
||||
@@ -511,6 +555,7 @@ Julien Royer
|
||||
Jun-ichiro itojun Hagino
|
||||
Jurij Smakov
|
||||
Justin Fletcher
|
||||
Justin Karneges
|
||||
Jörg Mueller-Tolk
|
||||
Jörn Hartroth
|
||||
Kai Engert
|
||||
@@ -544,11 +589,13 @@ Kimmo Kinnunen
|
||||
Kjell Ericson
|
||||
Kjetil Jacobsen
|
||||
Klevtsov Vadim
|
||||
Konstantin Isakov
|
||||
Kris Kennaway
|
||||
Krishnendu Majumdar
|
||||
Krister Johansen
|
||||
Kristian Gunstone
|
||||
Kristian Köhntopp
|
||||
Kyle L. Huff
|
||||
Kyle Sallee
|
||||
Lachlan O'Dea
|
||||
Larry Campbell
|
||||
@@ -556,6 +603,7 @@ Larry Fahnoe
|
||||
Lars Buitinck
|
||||
Lars Gustafsson
|
||||
Lars J. Aas
|
||||
Lars Johannesen
|
||||
Lars Nilsson
|
||||
Lars Torben Wilson
|
||||
Lau Hang Kin
|
||||
@@ -578,6 +626,7 @@ Loren Kirkby
|
||||
Luca Altea
|
||||
Luca Alteas
|
||||
Lucas Adamski
|
||||
Ludovico Cavedon
|
||||
Lukasz Czekierda
|
||||
Luke Amery
|
||||
Luke Call
|
||||
@@ -589,12 +638,15 @@ Mandy Wu
|
||||
Manfred Schwarb
|
||||
Manuel Massing
|
||||
Marc Boucher
|
||||
Marc Deslauriers
|
||||
Marc Doughty
|
||||
Marc Hoersken
|
||||
Marc Kleine-Budde
|
||||
Marcel Raad
|
||||
Marcel Roelofs
|
||||
Marcelo Juchem
|
||||
Marcin Adamski
|
||||
Marcin Gryszkalis
|
||||
Marcin Konicki
|
||||
Marco G. Salvagno
|
||||
Marco Maggi
|
||||
@@ -649,6 +701,7 @@ Maxim Prohorov
|
||||
Maxime Larocque
|
||||
Mehmet Bozkurt
|
||||
Mekonikum
|
||||
Melissa Mears
|
||||
Mettgut Jamalla
|
||||
Michael Benedict
|
||||
Michael Calmer
|
||||
@@ -660,6 +713,7 @@ Michael Jahn
|
||||
Michael Jerris
|
||||
Michael Mealling
|
||||
Michael Mueller
|
||||
Michael Osipov
|
||||
Michael Smith
|
||||
Michael Stillwell
|
||||
Michael Wallner
|
||||
@@ -668,13 +722,16 @@ Michal Gorny
|
||||
Michal Kowalczyk
|
||||
Michal Marek
|
||||
Michele Bini
|
||||
Miguel Angel
|
||||
Mihai Ionescu
|
||||
Mikael Johansson
|
||||
Mikael Sennerholm
|
||||
Mike Bytnar
|
||||
Mike Crowe
|
||||
Mike Dobbs
|
||||
Mike Giancola
|
||||
Mike Hommey
|
||||
Mike Mio
|
||||
Mike Power
|
||||
Mike Protts
|
||||
Mike Revi
|
||||
@@ -684,6 +741,7 @@ Mohamed Lrhazi
|
||||
Mohun Biswas
|
||||
Moonesamy
|
||||
Myk Taylor
|
||||
Nach M. S.
|
||||
Nathan Coulter
|
||||
Nathan O'Sullivan
|
||||
Nathanael Nerode
|
||||
@@ -718,6 +776,7 @@ Olaf Flebbe
|
||||
Olaf Stueben
|
||||
Olaf Stüben
|
||||
Oliver Gondža
|
||||
Oliver Kuckertz
|
||||
Olivier Berger
|
||||
Oren Tirosh
|
||||
Ori Avtalion
|
||||
@@ -736,8 +795,10 @@ Patrick Scott
|
||||
Patrick Smith
|
||||
Patrik Thunstrom
|
||||
Pau Garcia i Quiles
|
||||
Paul Donohue
|
||||
Paul Harrington
|
||||
Paul Howarth
|
||||
Paul Marks
|
||||
Paul Marquis
|
||||
Paul Moore
|
||||
Paul Nolan
|
||||
@@ -752,6 +813,7 @@ Pedro Neves
|
||||
Pete Su
|
||||
Peter Bray
|
||||
Peter Forret
|
||||
Peter Gal
|
||||
Peter Heuchert
|
||||
Peter Hjalmarsson
|
||||
Peter Korsgaard
|
||||
@@ -765,6 +827,8 @@ Peter Todd
|
||||
Peter Verhas
|
||||
Peter Wullinger
|
||||
Peteris Krumins
|
||||
Petr Bahula
|
||||
Petr Pisar
|
||||
Phil Blundell
|
||||
Phil Karn
|
||||
Phil Lisiecki
|
||||
@@ -804,6 +868,7 @@ Reinout van Schouwen
|
||||
Renato Botelho
|
||||
Renaud Chaillat
|
||||
Renaud Duhaut
|
||||
Renaud Guillard
|
||||
Rene Bernhardt
|
||||
Rene Rebe
|
||||
Reuven Wachtfogel
|
||||
@@ -847,6 +912,7 @@ Roland Zimmermann
|
||||
Rolland Dudemaine
|
||||
Roman Koifman
|
||||
Roman Mamedov
|
||||
Romulo A. Ceccon
|
||||
Ron Zapp
|
||||
Rosimildo da Silva
|
||||
Roy Shan
|
||||
@@ -856,6 +922,7 @@ Rutger Hofman
|
||||
Ryan Chan
|
||||
Ryan Nelson
|
||||
Ryan Schmidt
|
||||
Rémy Léone
|
||||
S. Moonesamy
|
||||
Salvador Dávila
|
||||
Salvatore Sorrentino
|
||||
@@ -881,11 +948,13 @@ Sebastian Rasmussen
|
||||
Sebastien Willemijns
|
||||
Senthil Raja Velu
|
||||
Sergei Nikulov
|
||||
Sergey Tatarincev
|
||||
Sergio Ballestrero
|
||||
Seshubabu Pasam
|
||||
Sh Diao
|
||||
Sharad Gupta
|
||||
Shard
|
||||
Shawn Landden
|
||||
Shawn Poulson
|
||||
Shmulik Regev
|
||||
Siddhartha Prakash Jain
|
||||
@@ -903,6 +972,7 @@ Stan van de Burgt
|
||||
Stanislav Ivochkin
|
||||
Stefan Esser
|
||||
Stefan Krause
|
||||
Stefan Neis
|
||||
Stefan Teleman
|
||||
Stefan Tomanek
|
||||
Stefan Ulrich
|
||||
@@ -950,6 +1020,7 @@ Tim Harder
|
||||
Tim Heckman
|
||||
Tim Newsome
|
||||
Tim Sneddon
|
||||
Timo Sirainen
|
||||
Tinus van den Berg
|
||||
Tobias Rundström
|
||||
Toby Peterson
|
||||
@@ -967,6 +1038,7 @@ Tom Mueller
|
||||
Tom Regner
|
||||
Tom Wright
|
||||
Tom Zerucha
|
||||
Tomas Hoger
|
||||
Tomas Mlcoch
|
||||
Tomas Pospisek
|
||||
Tomas Szepe
|
||||
@@ -984,7 +1056,9 @@ Traian Nicolescu
|
||||
Troels Walsted Hansen
|
||||
Troy Engel
|
||||
Tupone Alfredo
|
||||
Tyler Hall
|
||||
Ulf Härnhammar
|
||||
Ulf Samuelsson
|
||||
Ulrich Doehner
|
||||
Ulrich Zadow
|
||||
Venkat Akella
|
||||
@@ -1011,19 +1085,24 @@ Wesley Laxton
|
||||
Wesley Miaw
|
||||
Wez Furlong
|
||||
Wilfredo Sanchez
|
||||
Will Dietz
|
||||
Willem Sparreboom
|
||||
Wojciech Zwiefka
|
||||
Wouter Van Rooy
|
||||
Wu Yongzheng
|
||||
Xavier Bouchoux
|
||||
Yaakov Selkowitz
|
||||
Yamada Yasuharu
|
||||
Yang Tse
|
||||
Yarram Sunil
|
||||
Yehoshua Hershberg
|
||||
Yi Huang
|
||||
Yukihiro Kawada
|
||||
Yuriy Sosov
|
||||
Yves Arrouye
|
||||
Yves Lejeune
|
||||
Zdenek Pavlas
|
||||
Zekun Ni
|
||||
Zmey Petroff
|
||||
Zvi Har'El
|
||||
nk
|
||||
|
||||
82
docs/TODO
82
docs/TODO
@@ -16,8 +16,7 @@
|
||||
1.3 struct lifreq
|
||||
1.4 signal-based resolver timeouts
|
||||
1.5 get rid of PATH_MAX
|
||||
1.6 progress callback without doubles
|
||||
1.7 Happy Eyeball dual stack connect
|
||||
1.6 Modified buffer size approach
|
||||
|
||||
2. libcurl - multi interface
|
||||
2.1 More non-blocking
|
||||
@@ -39,6 +38,7 @@
|
||||
5.2 support FF3 sqlite cookie files
|
||||
5.3 Rearrange request header order
|
||||
5.4 HTTP2/SPDY
|
||||
5.5 auth= in URLs
|
||||
|
||||
6. TELNET
|
||||
6.1 ditch stdin
|
||||
@@ -48,17 +48,14 @@
|
||||
|
||||
7. SMTP
|
||||
7.1 Pipelining
|
||||
7.2 Graceful base64 decoding failure
|
||||
7.3 Enhanced capability support
|
||||
7.2 Enhanced capability support
|
||||
|
||||
8. POP3
|
||||
8.1 Pipelining
|
||||
8.2 Graceful base64 decoding failure
|
||||
8.3 Enhanced capability support
|
||||
8.2 Enhanced capability support
|
||||
|
||||
9. IMAP
|
||||
9.1 Graceful base64 decoding failure
|
||||
9.2 Enhanced capability support
|
||||
9.1 Enhanced capability support
|
||||
|
||||
10. LDAP
|
||||
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
|
||||
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
|
||||
use doubles in the arguments was possibly good at the time. Today the doubles
|
||||
only confuse users and make the amounts less precise. We should introduce
|
||||
another progress callback option that take precedence over the old one and
|
||||
have both co-exist for a forseeable time until we can remove the double-using
|
||||
one.
|
||||
Current libcurl allocates a fixed 16K size buffer for download and an
|
||||
additional 16K for upload. They are always unconditionally part of the easy
|
||||
handle. If CRLF translations are requested, an additional 32K "scratch
|
||||
buffer" is allocated. A total of 64K transfer buffers in the worst case.
|
||||
|
||||
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
|
||||
when introducing IPv6 as an alternative to IPv4 and there are more than one
|
||||
option existing simultaneously there are reasons to reconsider internal
|
||||
choices.
|
||||
Secondly, SFTP is a protocol that needs to handle many ~30K blocks at once
|
||||
since each need to be individually acked and therefore libssh2 must be
|
||||
allowed to send (or receive) many separate ones in parallel to achieve high
|
||||
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
|
||||
to be addressed:
|
||||
Dynamically allocate buffer size depending on protocol in use in combination
|
||||
with freeing it after each individual transfer? Other suggestions?
|
||||
|
||||
http://tools.ietf.org/html/rfc6555
|
||||
|
||||
2. libcurl - multi interface
|
||||
|
||||
@@ -287,6 +285,17 @@
|
||||
be a better option, either used directly or wrapped with a more spindly-like
|
||||
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
|
||||
|
||||
@@ -318,14 +327,7 @@ to provide the data to send.
|
||||
|
||||
Add support for pipelining emails.
|
||||
|
||||
7.2 Graceful base64 decoding failure
|
||||
|
||||
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
|
||||
7.2 Enhanced capability support
|
||||
|
||||
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||
capabilities returned from the EHLO command.
|
||||
@@ -336,28 +338,14 @@ to provide the data to send.
|
||||
|
||||
Add support for pipelining commands.
|
||||
|
||||
8.2 Graceful base64 decoding failure
|
||||
|
||||
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
|
||||
8.2 Enhanced capability support
|
||||
|
||||
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||
capabilities returned from the CAPA command.
|
||||
|
||||
9. IMAP
|
||||
|
||||
9.1 Graceful base64 decoding failure
|
||||
|
||||
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
|
||||
9.1 Enhanced capability support
|
||||
|
||||
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||
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
|
||||
friend.
|
||||
.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
|
||||
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
|
||||
@@ -113,8 +125,14 @@ same command line option.)
|
||||
Make curl display progress as a simple progress bar instead of the standard,
|
||||
more informational, meter.
|
||||
.IP "-0, --http1.0"
|
||||
(HTTP) Forces curl to issue its requests using HTTP 1.0 instead of using its
|
||||
internally preferred: HTTP 1.1.
|
||||
(HTTP) Tells curl to use HTTP version 1.0 instead of using its internally
|
||||
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"
|
||||
(SSL)
|
||||
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>"
|
||||
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
|
||||
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.
|
||||
.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
|
||||
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
|
||||
\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>"
|
||||
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
|
||||
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
|
||||
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
|
||||
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>"
|
||||
(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
|
||||
@@ -378,7 +432,8 @@ If this option is used several times, the last one will be used.
|
||||
.IP "-E, --cert <certificate[:password]>"
|
||||
(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
|
||||
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
|
||||
is the private key and the private certificate concatenated! See \fI--cert\fP
|
||||
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
|
||||
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.
|
||||
.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
|
||||
contents but they should be encoded according to the URI standard.
|
||||
.IP "-G, --get"
|
||||
When used, this option will make all data specified with \fI-d, --data\fP or
|
||||
\fI--data-binary\fP to be used in an HTTP GET request instead of the POST
|
||||
request that otherwise would be used. The data will be appended to the URL
|
||||
with a '?' separator.
|
||||
When used, this option will make all data specified with \fI-d, --data\fP,
|
||||
\fI--data-binary\fP or \fI--data-urlencode\fP to be used in an HTTP GET
|
||||
request instead of the POST request that otherwise would be used. The data
|
||||
will be appended to the URL with a '?' separator.
|
||||
|
||||
If used in combination with -I, the POST data will instead be appended to the
|
||||
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
|
||||
server-specified Content-Disposition filename instead of extracting a filename
|
||||
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"
|
||||
(SSL) This option explicitly allows curl to perform "insecure" SSL connections
|
||||
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>"
|
||||
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
|
||||
used as if they were written on the actual command line. Options and their
|
||||
parameters must be specified on the same config file line, separated by
|
||||
whitespace, colon, the equals sign or any combination thereof (however,
|
||||
the preferred separator is the equals sign). 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.
|
||||
used as if they were written on the actual command line.
|
||||
|
||||
Options and their parameters must be specified on the same config file line,
|
||||
separated by whitespace, colon, or the equals sign. Long option names can
|
||||
optionally be given in the config file without the initial double dashes and
|
||||
if so, the colon or equals characters can be used as separators. If the option
|
||||
is specified with one or two dashes, there can be no colon or equals character
|
||||
between the option and its parameter.
|
||||
|
||||
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
|
||||
stdin.
|
||||
@@ -683,9 +750,6 @@ line. So, it could look similar to this:
|
||||
|
||||
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
|
||||
config file and uses it if found. The default config file is checked for in
|
||||
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.
|
||||
.IP "-l, --list-only"
|
||||
(FTP)
|
||||
When listing an FTP directory, this switch forces a name-only view.
|
||||
Especially useful if you want to machine-parse the contents of an FTP
|
||||
directory since the normal directory view doesn't use a standard look
|
||||
or format.
|
||||
When listing an FTP directory, this switch forces a name-only view. This is
|
||||
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 or
|
||||
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
|
||||
list only files in their response to NLST; they do not include
|
||||
subdirectories and symbolic links.
|
||||
Note: Some FTP servers list only files in their response to NLST; they do not
|
||||
include sub-directories 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"
|
||||
(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),
|
||||
@@ -810,7 +882,10 @@ Basic authentication).
|
||||
.IP "-m, --max-time <seconds>"
|
||||
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
|
||||
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.
|
||||
.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
|
||||
than this given limit. This concerns both FTP and HTTP transfers.
|
||||
.IP "--mail-rcpt <address>"
|
||||
(SMTP) Specify a single address that the given mail should get sent to. This
|
||||
option can be used multiple times to specify many recipients.
|
||||
(SMTP) Specify a single address, user name or mailing list name.
|
||||
|
||||
(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>"
|
||||
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
|
||||
@@ -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
|
||||
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.
|
||||
.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"
|
||||
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
|
||||
@@ -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
|
||||
a redirection. This option is meaningful only when using \fI-L, --location\fP
|
||||
(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>"
|
||||
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
|
||||
@@ -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
|
||||
mute. It will still output the data you ask for, potentially even to the
|
||||
terminal/stdout unless you redirect it.
|
||||
.IP "--sasl-ir"
|
||||
Enable initial response in SASL authentication.
|
||||
(Added in 7.31.0)
|
||||
.IP "-S, --show-error"
|
||||
When used with \fI-s\fP it makes curl show an error message if it fails.
|
||||
.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
|
||||
specified but \fI--tlsauthtype\fP is not, then this option defaults to "SRP".
|
||||
(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>"
|
||||
Set password for use with the TLS authentication method specified with
|
||||
\fI--tlsauthtype\fP. Requires that \fI--tlsuser\fP also be set. (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 "--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"
|
||||
(HTTP) Request a compressed Transfer-Encoding response using one of the
|
||||
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"
|
||||
Prepends a time stamp to each trace or verbose line that curl displays.
|
||||
(Added in 7.14.0)
|
||||
.IP "-u, --user <user:password>"
|
||||
Specify the user name and password to use for server authentication. Overrides
|
||||
\fI-n, --netrc\fP and \fI--netrc-optional\fP.
|
||||
.IP "-u, --user <user:password;options>"
|
||||
Specify the user name, password and optional login options to use for server
|
||||
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
|
||||
a password.
|
||||
If you simply specify the user name, with or without the login options, curl
|
||||
will prompt for a password.
|
||||
|
||||
If you use an SSPI-enabled curl binary and do NTLM authentication, you can
|
||||
force curl to pick up the user name and password from your environment by
|
||||
simply specifying a single colon with this option: "-u :".
|
||||
If you use an SSPI-enabled curl binary and perform NTLM authentication, you
|
||||
can force curl to select the user name and password from your environment by
|
||||
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.
|
||||
.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.
|
||||
.IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>"
|
||||
Use the specified HTTP proxy. If the port number is not specified, it is
|
||||
assumed at port 1080.
|
||||
Use the specified proxy.
|
||||
|
||||
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
|
||||
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 +
|
||||
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.
|
||||
.IP "-X, --request <command>"
|
||||
(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
|
||||
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"
|
||||
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
|
||||
the mime_type attribute. If the file system does not support extended
|
||||
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 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
|
||||
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
|
||||
@@ -1965,6 +2101,8 @@ RTSP: mismatch of Session Identifiers
|
||||
unable to parse FTP file list
|
||||
.IP 88
|
||||
FTP chunk callback reported error
|
||||
.IP 89
|
||||
No connection available, the session will be queued
|
||||
.IP XX
|
||||
More error codes will appear here in future releases. The existing ones
|
||||
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 \
|
||||
sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \
|
||||
smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \
|
||||
progressfunc pop3s pop3slist imap url2file sftpget ftpsget \
|
||||
usercertinmem
|
||||
progressfunc pop3s pop3slist imap url2file sftpget ftpsget postinmemory
|
||||
|
||||
# These examples require external dependencies that may not be commonly
|
||||
# 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 \
|
||||
opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* 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);
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
/*
|
||||
@@ -59,7 +57,6 @@ int main(int argc, char **argv)
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
FILE * hd_src ;
|
||||
int hd ;
|
||||
struct stat file_info;
|
||||
|
||||
char *file;
|
||||
@@ -72,9 +69,7 @@ int main(int argc, char **argv)
|
||||
url = argv[2];
|
||||
|
||||
/* get the file size of the local file */
|
||||
hd = open(file, O_RDONLY) ;
|
||||
fstat(hd, &file_info);
|
||||
close(hd) ;
|
||||
stat(file, &file_info);
|
||||
|
||||
/* get a FILE * of the same file, could also be made with
|
||||
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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -30,9 +30,10 @@ struct myprogress {
|
||||
CURL *curl;
|
||||
};
|
||||
|
||||
static int progress(void *p,
|
||||
double dltotal, double dlnow,
|
||||
double ultotal, double ulnow)
|
||||
/* this is how the CURLOPT_XFERINFOFUNCTION callback works */
|
||||
static int xferinfo(void *p,
|
||||
curl_off_t dltotal, curl_off_t dlnow,
|
||||
curl_off_t ultotal, curl_off_t ulnow)
|
||||
{
|
||||
struct myprogress *myp = (struct myprogress *)p;
|
||||
CURL *curl = myp->curl;
|
||||
@@ -48,7 +49,9 @@ static int progress(void *p,
|
||||
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);
|
||||
|
||||
if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES)
|
||||
@@ -56,6 +59,19 @@ static int progress(void *p,
|
||||
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)
|
||||
{
|
||||
CURL *curl;
|
||||
@@ -68,9 +84,28 @@ int main(void)
|
||||
prog.curl = curl;
|
||||
|
||||
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 */
|
||||
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);
|
||||
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
|
||||
* https page.
|
||||
* 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
|
||||
* if you want a properly secure connection
|
||||
* Note that to maintain simplicity this example does not use a CA certificate
|
||||
* 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>
|
||||
@@ -152,6 +153,18 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
|
||||
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 */
|
||||
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_easy_send.pdf curl_multi_socket_action.pdf curl_multi_wait.pdf
|
||||
|
||||
m4macrodir = $(datadir)/aclocal
|
||||
dist_m4macro_DATA = libcurl.m4
|
||||
|
||||
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
|
||||
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
|
||||
.\" * 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
|
||||
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
|
||||
option is only available in libcurl built with OpenSSL support. (Added in
|
||||
7.19.1)
|
||||
option is only available in libcurl built with OpenSSL, NSS, GSKit or QsoSSL
|
||||
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
|
||||
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
|
||||
@@ -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.
|
||||
|
||||
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
|
||||
Pass a pointer to a long to receive the next CSeq that will be used by the
|
||||
application.
|
||||
@@ -244,7 +256,7 @@ by the application.
|
||||
unimplemented).\fP
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
.\" * 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
|
||||
the writing is later unpaused.
|
||||
|
||||
NOTE: while it may feel tempting, take care and notice that you cannot call
|
||||
this function from another thread.
|
||||
While it may feel tempting, take care and notice that you cannot call this
|
||||
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
|
||||
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
|
||||
This function was added in libcurl 7.18.0. Before this version, there was no
|
||||
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"
|
||||
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
|
||||
|
||||
@@ -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
|
||||
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,
|
||||
SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl
|
||||
only passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on
|
||||
success, 1 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
|
||||
SEEK_CUR and SEEK_END as argument for origin, although libcurl currently only
|
||||
passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on success, 1
|
||||
(CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
|
||||
(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
|
||||
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
|
||||
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
|
||||
Pass a pointer that will be untouched by libcurl and passed as the first
|
||||
argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP.
|
||||
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
|
||||
Pass a pointer to a function that matches the following prototype:
|
||||
\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
|
||||
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
|
||||
|
||||
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)
|
||||
.IP CURLOPT_USERPWD
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
.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)
|
||||
CURLOPT_USERPWD option.
|
||||
|
||||
In order to specify the password to be used in conjunction with the user name
|
||||
use the \fICURLOPT_PASSWORD\fP option. (Added in 7.19.1)
|
||||
To specify the password and login options, along with the user name, use the
|
||||
\fICURLOPT_PASSWORD\fP and \fICURLOPT_LOGIN_OPTIONS\fP options. (Added in
|
||||
7.19.1)
|
||||
.IP CURLOPT_PASSWORD
|
||||
Pass a char * as parameter, which should be pointing to the zero terminated
|
||||
password to use for the transfer.
|
||||
|
||||
The CURLOPT_PASSWORD option should be used in conjunction with
|
||||
the \fICURLOPT_USERNAME\fP option. (Added in 7.19.1)
|
||||
The CURLOPT_PASSWORD option should be used in conjunction with the
|
||||
\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
|
||||
Pass a char * as parameter, which should be pointing to the zero terminated
|
||||
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,
|
||||
as libcurl can determine the feature itself when the server supports the
|
||||
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
|
||||
.IP CURLOPT_AUTOREFERER
|
||||
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
|
||||
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 (<>),
|
||||
however, should you not use an angled bracket as the first character libcurl
|
||||
will assume you provided a single email address and enclose that address
|
||||
within brackets for you.
|
||||
When performing a mail transfer, each recipient should be specified within a
|
||||
pair of angled brackets (<>), however, should you not use an angled bracket as
|
||||
the first character libcurl will assume you provided a single email address and
|
||||
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
|
||||
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
|
||||
@@ -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
|
||||
you want the transfer to start from. (Added in 7.11.0)
|
||||
.IP CURLOPT_CUSTOMREQUEST
|
||||
Pass a pointer to a zero terminated string as parameter. It can be used to
|
||||
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.
|
||||
Pass a pointer to a zero terminated string as parameter.
|
||||
|
||||
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
|
||||
to the particular request method, it will only change the actual string sent
|
||||
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:
|
||||
|
||||
With the HTTP protocol when you tell libcurl to do a HEAD request, but then
|
||||
specify a GET though a custom request libcurl will still act as if it sent a
|
||||
HEAD. To switch to a proper HEAD use \fICURLOPT_NOBODY\fP, to switch to a
|
||||
proper POST use \fICURLOPT_POST\fP or \fICURLOPT_POSTFIELDS\fP and to switch
|
||||
to a proper GET use CURLOPT_HTTPGET.
|
||||
When you tell libcurl to do a HEAD request, but then specify a GET though a
|
||||
custom request libcurl will still act as if it sent a HEAD. To switch to a
|
||||
proper HEAD use \fICURLOPT_NOBODY\fP, to switch to a proper POST use
|
||||
\fICURLOPT_POST\fP or \fICURLOPT_POSTFIELDS\fP and to switch to a proper GET
|
||||
use CURLOPT_HTTPGET.
|
||||
|
||||
With the POP3 protocol 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.
|
||||
|
||||
Restore to the internal default by setting this to NULL.
|
||||
Please don't perform this at will, on HTTP based requests, by making sure
|
||||
your server supports the command you are sending first.
|
||||
|
||||
Many people have wrongly used this option to replace the entire request with
|
||||
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
|
||||
\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
|
||||
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
|
||||
@@ -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.
|
||||
.IP CURLOPT_TIMEOUT_MS
|
||||
Like \fICURLOPT_TIMEOUT\fP but takes number of milliseconds instead. If
|
||||
libcurl is built to use the standard system name resolver, that portion
|
||||
of the transfer will still use full-second resolution for timeouts with
|
||||
a minimum timeout allowed of one second.
|
||||
An alternative to \fICURLOPT_TIMEOUT\fP but takes number of milliseconds
|
||||
instead. If libcurl is built to use the standard system name resolver, that
|
||||
portion of the transfer will still use full-second resolution for timeouts
|
||||
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)
|
||||
.IP CURLOPT_LOW_SPEED_LIMIT
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
(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
|
||||
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
|
||||
@@ -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
|
||||
.IP CURLOPT_SSLCERT
|
||||
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
|
||||
changed with \fICURLOPT_SSLCERTTYPE\fP.
|
||||
the file name of your certificate. The default format is "P12" on Secure
|
||||
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
|
||||
authenticate with. If you 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)
|
||||
With NSS or Secure Transport, this can also be the nickname of the certificate
|
||||
you wish to authenticate with as it is named in the security database. If you
|
||||
want to use a file from the current directory, please precede it with "./"
|
||||
prefix, in order to avoid confusion with a nickname.
|
||||
.IP CURLOPT_SSLCERTTYPE
|
||||
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
|
||||
in 7.9.3)
|
||||
the format of your certificate. Supported formats are "PEM" and "DER", except
|
||||
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
|
||||
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
|
||||
@@ -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
|
||||
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
|
||||
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".
|
||||
@@ -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.
|
||||
.IP CURLOPT_SSLVERSION
|
||||
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:
|
||||
.RS
|
||||
.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
|
||||
by default with 7.18.1).
|
||||
.IP CURL_SSLVERSION_TLSv1
|
||||
Force TLSv1
|
||||
Force TLSv1.x
|
||||
.IP CURL_SSLVERSION_SSLv2
|
||||
Force SSLv2
|
||||
.IP CURL_SSLVERSION_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
|
||||
.IP CURLOPT_SSL_VERIFYPEER
|
||||
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
|
||||
URL to which you told Curl to connect.
|
||||
|
||||
When the value is 1, libcurl will return a failure. It was previously (in
|
||||
7.28.0 and earlier) a debug option of some sorts, but it is no longer
|
||||
supported due to frequently leading to programmer mistakes.
|
||||
When the value is 1, \fIcurl_easy_setopt\fP will return an error and the option
|
||||
value will not be changed. It was previously (in 7.28.0 and earlier) a debug
|
||||
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
|
||||
certificate.
|
||||
@@ -2438,14 +2591,14 @@ The default value for this option is 2.
|
||||
This option controls checking the server's certificate's claimed identity.
|
||||
The server could be lying. To control lying, see
|
||||
\fICURLOPT_SSL_VERIFYPEER\fP. If libcurl is built against NSS and
|
||||
\fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_SSL_VERIFYHOST\fP
|
||||
is ignored.
|
||||
|
||||
\fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_SSL_VERIFYHOST\fP is also set
|
||||
to zero and cannot be overridden.
|
||||
.IP CURLOPT_CERTINFO
|
||||
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
|
||||
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
|
||||
7.19.1)
|
||||
.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
|
||||
.\" * 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
|
||||
.SH DESCRIPTION
|
||||
Adds a standard easy handle to the multi stack. This function call will make
|
||||
this \fImulti_handle\fP control the specified \fIeasy_handle\fP.
|
||||
Furthermore, libcurl now initiates the connection associated with the
|
||||
specified \fIeasy_handle\fP.
|
||||
this \fImulti_handle\fP control the specified \fIeasy_handle\fP. Furthermore,
|
||||
libcurl now initiates the connection associated with the specified
|
||||
\fIeasy_handle\fP.
|
||||
|
||||
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!
|
||||
@@ -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
|
||||
\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
|
||||
\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
|
||||
|
||||
@@ -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
|
||||
.\" * 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)"
|
||||
curl_multi_setopt() with unsupported option
|
||||
(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"
|
||||
The "share" interface will return a CURLSHcode to indicate when an error has
|
||||
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
|
||||
.\" * 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.
|
||||
|
||||
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
|
||||
the option of using the "easy" interface, or the "multi" interface.
|
||||
\fIcurl_easy_init(3)\fP for a single specific transfer (in either
|
||||
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
|
||||
\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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
attempt to use an existing connection to do the transfer, and if none exists
|
||||
it'll open a new one that will be subject for re-use on a possible following
|
||||
call to \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP.
|
||||
use \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP etc, libcurl
|
||||
will attempt to use an existing connection to do the transfer, and if none
|
||||
exists it'll open a new one that will be subject for re-use on a possible
|
||||
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
|
||||
do as many of your file transfers as possible using the same curl handle. When
|
||||
you call \fIcurl_easy_cleanup(3)\fP, all the possibly open connections held by
|
||||
libcurl will be closed and forgotten.
|
||||
do as many of your file transfers as possible using the same handle.
|
||||
|
||||
Note that the options set with \fIcurl_easy_setopt(3)\fP will be used on
|
||||
every repeated \fIcurl_easy_perform(3)\fP call.
|
||||
If you use the easy interface, and you call \fIcurl_easy_cleanup(3)\fP, all
|
||||
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"
|
||||
There are a variety of constants that libcurl uses, mainly through its
|
||||
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_LOGIN_DENIED 7.13.1
|
||||
CURLE_MALFORMAT_USER 7.1 7.17.0
|
||||
CURLE_NO_CONNECTION_AVAILABLE 7.30.0
|
||||
CURLE_NOT_BUILT_IN 7.21.5
|
||||
CURLE_NO_CONNECTION_AVAILABLE 7.30.0
|
||||
CURLE_OK 7.1
|
||||
CURLE_OPERATION_TIMEDOUT 7.10.2
|
||||
CURLE_OPERATION_TIMEOUTED 7.1 7.17.0
|
||||
@@ -250,6 +250,7 @@ CURLINFO_SSL_VERIFYRESULT 7.5
|
||||
CURLINFO_STARTTRANSFER_TIME 7.9.2
|
||||
CURLINFO_STRING 7.4.1
|
||||
CURLINFO_TEXT 7.9.6
|
||||
CURLINFO_TLS_SESSION 7.34.0
|
||||
CURLINFO_TOTAL_TIME 7.4.1
|
||||
CURLINFO_TYPEMASK 7.4.1
|
||||
CURLIOCMD_NOP 7.12.3
|
||||
@@ -270,10 +271,10 @@ CURLKHTYPE_RSA1 7.19.6
|
||||
CURLKHTYPE_UNKNOWN 7.19.6
|
||||
CURLMOPT_CHUNK_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_PIPELINE_LENGTH 7.30.0
|
||||
CURLMOPT_MAX_TOTAL_CONNECTIONS 7.30.0
|
||||
CURLMOPT_MAXCONNECTS 7.16.3
|
||||
CURLMOPT_PIPELINING 7.16.0
|
||||
CURLMOPT_PIPELINING_SERVER_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
|
||||
CURLMSG_DONE 7.9.6
|
||||
CURLMSG_NONE 7.9.6
|
||||
CURLM_ADDED_ALREADY 7.32.1
|
||||
CURLM_BAD_EASY_HANDLE 7.9.6
|
||||
CURLM_BAD_HANDLE 7.9.6
|
||||
CURLM_BAD_SOCKET 7.15.4
|
||||
@@ -331,6 +333,9 @@ CURLOPT_DEBUGDATA 7.9.6
|
||||
CURLOPT_DEBUGFUNCTION 7.9.6
|
||||
CURLOPT_DIRLISTONLY 7.17.0
|
||||
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_USE_GLOBAL_CACHE 7.9.3 7.11.1
|
||||
CURLOPT_EGDSOCKET 7.7
|
||||
@@ -390,6 +395,7 @@ CURLOPT_KRB4LEVEL 7.3 7.17.0
|
||||
CURLOPT_KRBLEVEL 7.16.4
|
||||
CURLOPT_LOCALPORT 7.15.2
|
||||
CURLOPT_LOCALPORTRANGE 7.15.2
|
||||
CURLOPT_LOGIN_OPTIONS 7.34.0
|
||||
CURLOPT_LOW_SPEED_LIMIT 7.1
|
||||
CURLOPT_LOW_SPEED_TIME 7.1
|
||||
CURLOPT_MAIL_AUTH 7.25.0
|
||||
@@ -428,7 +434,7 @@ CURLOPT_POSTREDIR 7.19.1
|
||||
CURLOPT_PREQUOTE 7.9.5
|
||||
CURLOPT_PRIVATE 7.10.3
|
||||
CURLOPT_PROGRESSDATA 7.1
|
||||
CURLOPT_PROGRESSFUNCTION 7.1
|
||||
CURLOPT_PROGRESSFUNCTION 7.1 7.32.0
|
||||
CURLOPT_PROTOCOLS 7.19.4
|
||||
CURLOPT_PROXY 7.1
|
||||
CURLOPT_PROXYAUTH 7.10.7
|
||||
@@ -525,6 +531,9 @@ CURLOPT_WRITEDATA 7.9.7
|
||||
CURLOPT_WRITEFUNCTION 7.1
|
||||
CURLOPT_WRITEHEADER 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_CONT 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_PASSWORD 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
|
||||
CURLUSESSL_ALL 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_OPTION_TWICE 7.9.8
|
||||
CURL_FORMADD_UNKNOWN_OPTION 7.9.8
|
||||
CURL_GLOBAL_ACK_EINTR 7.30.0
|
||||
CURL_GLOBAL_ALL 7.8
|
||||
CURL_GLOBAL_DEFAULT 7.8
|
||||
CURL_GLOBAL_NOTHING 7.8
|
||||
CURL_GLOBAL_SSL 7.8
|
||||
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_1 7.9.1
|
||||
CURL_HTTP_VERSION_2_0 7.33.0
|
||||
CURL_HTTP_VERSION_NONE 7.9.1
|
||||
CURL_IPRESOLVE_V4 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_SSLv3 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_IFUNMODSINCE 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_DEBUG 7.10.6
|
||||
CURL_VERSION_GSSNEGOTIATE 7.10.6
|
||||
CURL_VERSION_HTTP2 7.33.0
|
||||
CURL_VERSION_IDN 7.12.0
|
||||
CURL_VERSION_IPV6 7.10
|
||||
CURL_VERSION_KERBEROS4 7.10
|
||||
|
||||
@@ -60,11 +60,16 @@ unlink (remove) certdata.txt after processing
|
||||
be verbose and print out processed CAs
|
||||
.SH EXIT STATUS
|
||||
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
|
||||
.BR curl (1)
|
||||
.SH HISTORY
|
||||
\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
|
||||
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
|
||||
\&<jschauma@netmeister.org>.
|
||||
improved by Guenter Knauf. This manual page was initially written by Jan
|
||||
Schaumann \&<jschauma@netmeister.org>.
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
require it! */
|
||||
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
|
||||
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
|
||||
defined(ANDROID) || defined(__ANDROID__) || \
|
||||
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
|
||||
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
@@ -156,12 +156,22 @@ struct curl_httppost {
|
||||
HTTPPOST_CALLBACK posts */
|
||||
};
|
||||
|
||||
/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
|
||||
deprecated but was the only choice up until 7.31.0 */
|
||||
typedef int (*curl_progress_callback)(void *clientp,
|
||||
double dltotal,
|
||||
double dlnow,
|
||||
double ultotal,
|
||||
double ulnow);
|
||||
|
||||
/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
|
||||
7.32.0, it avoids floating point and provides more detailed information. */
|
||||
typedef int (*curl_xferinfo_callback)(void *clientp,
|
||||
curl_off_t dltotal,
|
||||
curl_off_t dlnow,
|
||||
curl_off_t ultotal,
|
||||
curl_off_t ulnow);
|
||||
|
||||
#ifndef CURL_MAX_WRITE_SIZE
|
||||
/* Tests have proven that 20K is a very bad buffer size for uploads on
|
||||
Windows, while 16K for some odd reason performed a lot better.
|
||||
@@ -635,16 +645,18 @@ typedef enum {
|
||||
|
||||
#define CURL_ERROR_SIZE 256
|
||||
|
||||
struct curl_khkey {
|
||||
const char *key; /* points to a zero-terminated string encoded with base64
|
||||
if len is zero, otherwise to the "raw" data */
|
||||
size_t len;
|
||||
enum type {
|
||||
enum curl_khtype {
|
||||
CURLKHTYPE_UNKNOWN,
|
||||
CURLKHTYPE_RSA1,
|
||||
CURLKHTYPE_RSA,
|
||||
CURLKHTYPE_DSS
|
||||
} keytype;
|
||||
};
|
||||
|
||||
struct curl_khkey {
|
||||
const char *key; /* points to a zero-terminated string encoded with base64
|
||||
if len is zero, otherwise to the "raw" data */
|
||||
size_t len;
|
||||
enum curl_khtype keytype;
|
||||
};
|
||||
|
||||
/* this is the set of return values expected from the curl_sshkeycallback
|
||||
@@ -815,10 +827,10 @@ typedef enum {
|
||||
/* Name of proxy to use. */
|
||||
CINIT(PROXY, OBJECTPOINT, 4),
|
||||
|
||||
/* "name:password" to use when fetching. */
|
||||
/* "user:password;options" to use when fetching. */
|
||||
CINIT(USERPWD, OBJECTPOINT, 5),
|
||||
|
||||
/* "name:password" to use with proxy. */
|
||||
/* "user:password" to use with proxy. */
|
||||
CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
|
||||
|
||||
/* Range to get, specified as an ASCII string. */
|
||||
@@ -968,13 +980,16 @@ typedef enum {
|
||||
|
||||
/* 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
|
||||
* prototype defines. */
|
||||
CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
|
||||
|
||||
/* Data passed to the progress callback */
|
||||
/* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
|
||||
callbacks */
|
||||
CINIT(PROGRESSDATA, OBJECTPOINT, 57),
|
||||
#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
|
||||
|
||||
/* We want the referrer field set automatically when following locations */
|
||||
CINIT(AUTOREFERER, LONG, 58),
|
||||
@@ -1373,8 +1388,7 @@ typedef enum {
|
||||
CINIT(ADDRESS_SCOPE, LONG, 171),
|
||||
|
||||
/* Collect certificate chain info and allow it to get retrievable with
|
||||
CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only
|
||||
working with OpenSSL-powered builds. */
|
||||
CURLINFO_CERTINFO after the transfer is complete. */
|
||||
CINIT(CERTINFO, LONG, 172),
|
||||
|
||||
/* "name" and "pwd" to use when fetching. */
|
||||
@@ -1533,6 +1547,30 @@ typedef enum {
|
||||
/* Enable/disable SASL initial response */
|
||||
CINIT(SASL_IR, LONG, 218),
|
||||
|
||||
/* Function that will be called instead of the internal progress display
|
||||
* function. This function should be defined as the curl_xferinfo_callback
|
||||
* prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
|
||||
CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
|
||||
|
||||
/* The XOAUTH2 bearer token */
|
||||
CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
|
||||
|
||||
/* Set the interface string to use as outgoing network
|
||||
* interface for DNS requests.
|
||||
* Only supported by the c-ares DNS backend */
|
||||
CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
|
||||
|
||||
/* Set the local IPv4 address to use for outgoing DNS requests.
|
||||
* Only supported by the c-ares DNS backend */
|
||||
CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
|
||||
|
||||
/* Set the local IPv4 address to use for outgoing DNS requests.
|
||||
* Only supported by the c-ares DNS backend */
|
||||
CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
|
||||
|
||||
/* Set authentication options directly */
|
||||
CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -1585,6 +1623,7 @@ enum {
|
||||
for us! */
|
||||
CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
|
||||
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
|
||||
CURL_HTTP_VERSION_2_0, /* please use HTTP 2.0 in the request */
|
||||
|
||||
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
|
||||
};
|
||||
@@ -1622,9 +1661,12 @@ enum CURL_NETRC_OPTION {
|
||||
|
||||
enum {
|
||||
CURL_SSLVERSION_DEFAULT,
|
||||
CURL_SSLVERSION_TLSv1,
|
||||
CURL_SSLVERSION_TLSv1, /* TLS 1.x */
|
||||
CURL_SSLVERSION_SSLv2,
|
||||
CURL_SSLVERSION_SSLv3,
|
||||
CURL_SSLVERSION_TLSv1_0,
|
||||
CURL_SSLVERSION_TLSv1_1,
|
||||
CURL_SSLVERSION_TLSv1_2,
|
||||
|
||||
CURL_SSLVERSION_LAST /* never use, keep last */
|
||||
};
|
||||
@@ -1943,6 +1985,28 @@ struct curl_certinfo {
|
||||
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_LONG 0x200000
|
||||
#define CURLINFO_DOUBLE 0x300000
|
||||
@@ -1994,9 +2058,10 @@ typedef enum {
|
||||
CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
|
||||
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
|
||||
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
|
||||
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
|
||||
/* Fill in new entries below here! */
|
||||
|
||||
CURLINFO_LASTONE = 42
|
||||
CURLINFO_LASTONE = 43
|
||||
} CURLINFO;
|
||||
|
||||
/* 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_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
|
||||
#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()
|
||||
|
||||
@@ -58,51 +58,52 @@
|
||||
/* ================================================================ */
|
||||
|
||||
#ifdef CURL_SIZEOF_LONG
|
||||
# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
|
||||
# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
|
||||
# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_OFF_T
|
||||
# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_CURL_OFF_T
|
||||
# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_CURL_OFF_TU
|
||||
# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_OFF_T
|
||||
# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SIZEOF_CURL_OFF_T
|
||||
# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SUFFIX_CURL_OFF_T
|
||||
# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SUFFIX_CURL_OFF_TU
|
||||
# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
|
||||
#endif
|
||||
|
||||
@@ -110,71 +111,87 @@
|
||||
/* 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 */
|
||||
/* 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
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file stdint.h must be included by the external interface. */
|
||||
#cmakedefine CURL_PULL_STDINT_H ${CURL_PULL_STDINT_H}
|
||||
#cmakedefine CURL_PULL_STDINT_H
|
||||
#ifdef CURL_PULL_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file inttypes.h must be included by the external interface. */
|
||||
#cmakedefine CURL_PULL_INTTYPES_H ${CURL_PULL_INTTYPES_H}
|
||||
#cmakedefine CURL_PULL_INTTYPES_H
|
||||
#ifdef CURL_PULL_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#cmakedefine CURL_SIZEOF_LONG ${CURL_SIZEOF_LONG}
|
||||
|
||||
/* Integral data type used for curl_socklen_t. */
|
||||
#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
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file sys/socket.h must be included by the external interface. */
|
||||
#cmakedefine CURL_PULL_SYS_SOCKET_H
|
||||
#ifdef CURL_PULL_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file sys/poll.h must be included by the external interface. */
|
||||
#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. */
|
||||
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. */
|
||||
#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. */
|
||||
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
|
||||
|
||||
/* 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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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 */
|
||||
|
||||
@@ -30,12 +30,12 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
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
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 31
|
||||
#define LIBCURL_VERSION_MINOR 34
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* 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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
* 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_BAD_SOCKET, /* the passed in socket argument did not match */
|
||||
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
||||
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
|
||||
attempted to get added - again */
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
|
||||
@@ -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
|
||||
* 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_STREAM_URI || \
|
||||
(option) == CURLOPT_RTSP_TRANSPORT || \
|
||||
(option) == CURLOPT_XOAUTH2_BEARER || \
|
||||
(option) == CURLOPT_DNS_SERVERS || \
|
||||
(option) == CURLOPT_DNS_INTERFACE || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP4 || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP6 || \
|
||||
(option) == CURLOPT_LOGIN_OPTIONS || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a curl_write_callback argument */
|
||||
|
||||
@@ -94,6 +94,10 @@ add_library(
|
||||
${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})
|
||||
|
||||
if(WIN32)
|
||||
@@ -108,14 +112,6 @@ setup_curl_dependencies(${LIB_NAME})
|
||||
set_target_properties(${LIB_NAME} PROPERTIES 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(NOT CURL_STATICLIB)
|
||||
# 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
|
||||
|
||||
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)
|
||||
|
||||
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
|
||||
|
||||
@@ -52,7 +52,7 @@ LDFLAGS = -q -lq -laa -tWD
|
||||
SRCDIR = .
|
||||
OBJDIR = .\BCC_objs
|
||||
INCDIRS = -I.;..\include
|
||||
LINKLIB = $(BCCDIR)\lib\cw32mt.lib
|
||||
LINKLIB = $(BCCDIR)\lib\cw32mt.lib $(BCCDIR)\lib\ws2_32.lib
|
||||
DEFINES = -DNDEBUG -DWIN32 -DBUILDING_LIBCURL
|
||||
|
||||
# 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
|
||||
!include Makefile.inc
|
||||
|
||||
OBJECTS = $(CSOURCES:.c=.obj)
|
||||
PREPROCESSED = $(CSOURCES:.c=.int)
|
||||
# Borland's command line librarian program TLIB version 4.5 is not capable
|
||||
# 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:
|
||||
@-$(RM) $(@R).int
|
||||
@@ -98,6 +114,21 @@ PREPROCESSED = $(CSOURCES:.c=.int)
|
||||
|
||||
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:
|
||||
cd $(OBJDIR)
|
||||
@-$(RM) $(OBJECTS)
|
||||
@@ -122,7 +153,10 @@ $(LIBCURL_LIB): $(OBJECTS)
|
||||
$(LIBCURL_DLL) $(LIBCURL_IMPLIB): $(OBJECTS) $(LINKLIB)
|
||||
@-$(RM) $(LIBCURL_DLL)
|
||||
@-$(RM) $(LIBCURL_IMPLIB)
|
||||
$(LD) $(LDFLAGS) -e$(LIBCURL_DLL) $**
|
||||
$(LD) $(LDFLAGS) -e$(LIBCURL_DLL) @&&!
|
||||
$(**: = ^
|
||||
)
|
||||
!
|
||||
$(IMPLIB) $(LIBCURL_IMPLIB) $(LIBCURL_DLL)
|
||||
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
@@ -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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
@@ -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 \
|
||||
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 \
|
||||
multihandle.h setup-vms.h pipeline.h
|
||||
multihandle.h setup-vms.h pipeline.h dotdot.h x509asn1.h gskit.h \
|
||||
http2.h sigpipe.h
|
||||
|
||||
@@ -106,6 +106,7 @@ WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK"
|
||||
CCNODBG = cl.exe /O2 /DNDEBUG
|
||||
CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /GZ
|
||||
CFLAGSSSL = /DUSE_SSLEAY /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
|
||||
CFLAGSWINSSL = /DUSE_SCHANNEL
|
||||
CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
|
||||
CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
|
||||
CFLAGS = /I. /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1
|
||||
@@ -114,7 +115,7 @@ LNKDLL = link.exe /DLL
|
||||
LNKLIB = link.exe /lib
|
||||
LFLAGS = /nologo /machine:$(MACHINE)
|
||||
SSLLIBS = libeay32.lib ssleay32.lib
|
||||
ZLIBLIBSDLL= zdll.lib
|
||||
ZLIBLIBSDLL = zdll.lib
|
||||
ZLIBLIBS = zlib.lib
|
||||
WINLIBS = ws2_32.lib wldap32.lib advapi32.lib
|
||||
CFLAGS = $(CFLAGS)
|
||||
@@ -189,6 +190,18 @@ CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
|
||||
CFGSET = TRUE
|
||||
!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
|
||||
|
||||
@@ -515,7 +528,6 @@ X_OBJS= \
|
||||
$(DIROBJ)\curl_ntlm_core.obj \
|
||||
$(DIROBJ)\curl_ntlm_msgs.obj \
|
||||
$(DIROBJ)\curl_ntlm_wb.obj \
|
||||
$(DIROBJ)\curl_rand.obj \
|
||||
$(DIROBJ)\curl_rtmp.obj \
|
||||
$(DIROBJ)\curl_sasl.obj \
|
||||
$(DIROBJ)\curl_schannel.obj \
|
||||
@@ -523,6 +535,7 @@ X_OBJS= \
|
||||
$(DIROBJ)\curl_threads.obj \
|
||||
$(DIROBJ)\cyassl.obj \
|
||||
$(DIROBJ)\dict.obj \
|
||||
$(DIROBJ)\dotdot.obj \
|
||||
$(DIROBJ)\easy.obj \
|
||||
$(DIROBJ)\escape.obj \
|
||||
$(DIROBJ)\file.obj \
|
||||
@@ -553,7 +566,6 @@ X_OBJS= \
|
||||
$(DIROBJ)\imap.obj \
|
||||
$(DIROBJ)\inet_ntop.obj \
|
||||
$(DIROBJ)\inet_pton.obj \
|
||||
$(DIROBJ)\krb4.obj \
|
||||
$(DIROBJ)\krb5.obj \
|
||||
$(DIROBJ)\ldap.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?
|
||||
131
lib/asyn-ares.c
131
lib/asyn-ares.c
@@ -315,6 +315,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct ResolverResults *res = (struct ResolverResults *)
|
||||
conn->async.os_specific;
|
||||
CURLcode rc = CURLE_OK;
|
||||
|
||||
*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
|
||||
them */
|
||||
res->temp_ai = NULL;
|
||||
destroy_async_data(&conn->async);
|
||||
if(!conn->async.dns) {
|
||||
failf(data, "Could not resolve %s: %s (%s)",
|
||||
conn->bits.proxy?"proxy":"host",
|
||||
conn->host.dispname,
|
||||
ares_strerror(conn->async.status));
|
||||
return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
|
||||
failf(data, "Could not resolve: %s (%s)",
|
||||
conn->async.hostname, ares_strerror(conn->async.status));
|
||||
rc = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
|
||||
CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
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)
|
||||
*entry = conn->async.dns;
|
||||
|
||||
if(!conn->async.dns) {
|
||||
/* 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;
|
||||
|
||||
if(rc)
|
||||
/* 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;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -614,8 +590,19 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
|
||||
char *servers)
|
||||
{
|
||||
CURLcode result = CURLE_NOT_BUILT_IN;
|
||||
int ares_result;
|
||||
|
||||
/* If server is NULL or empty, this would purge all DNS servers
|
||||
* from ares library, which will cause any and all queries to fail.
|
||||
* So, just return OK if none are configured and don't actually make
|
||||
* any changes to c-ares. This lets c-ares use it's defaults, which
|
||||
* it gets from the OS (for instance from /etc/resolv.conf on Linux).
|
||||
*/
|
||||
if(!(servers && servers[0]))
|
||||
return CURLE_OK;
|
||||
|
||||
#if (ARES_VERSION >= 0x010704)
|
||||
int ares_result = ares_set_servers_csv(data->state.resolver, servers);
|
||||
ares_result = ares_set_servers_csv(data->state.resolver, servers);
|
||||
switch(ares_result) {
|
||||
case ARES_SUCCESS:
|
||||
result = CURLE_OK;
|
||||
@@ -632,8 +619,76 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
|
||||
}
|
||||
#else /* too old c-ares version! */
|
||||
(void)data;
|
||||
(void)servers;
|
||||
(void)(ares_result);
|
||||
#endif
|
||||
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 */
|
||||
|
||||
@@ -265,7 +265,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
|
||||
static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
|
||||
{
|
||||
struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
|
||||
char service [NI_MAXSERV];
|
||||
char service[12];
|
||||
int rc;
|
||||
|
||||
snprintf(service, sizeof(service), "%d", tsd->port);
|
||||
@@ -559,7 +559,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
|
||||
struct in_addr in;
|
||||
Curl_addrinfo *res;
|
||||
int error;
|
||||
char sbuf[NI_MAXSERV];
|
||||
char sbuf[12];
|
||||
int pf = PF_INET;
|
||||
#ifdef CURLRES_IPV6
|
||||
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 */
|
||||
|
||||
@@ -164,7 +164,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
91
lib/base64.c
91
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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -40,29 +40,45 @@
|
||||
static const char table64[]=
|
||||
"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;
|
||||
unsigned long i, v, x = 0;
|
||||
|
||||
for(i = 0, s = src; i < 4; i++, s++) {
|
||||
v = 0;
|
||||
|
||||
if(*s == '=') {
|
||||
x = (x << 6);
|
||||
padding++;
|
||||
}
|
||||
else {
|
||||
p = table64;
|
||||
|
||||
while(*p && (*p != *s)) {
|
||||
v++;
|
||||
p++;
|
||||
}
|
||||
|
||||
if(*p == *s)
|
||||
x = (x << 6) + v;
|
||||
else if(*s == '=')
|
||||
x = (x << 6);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(padding < 1)
|
||||
dest[2] = curlx_ultouc(x & 0xFFUL);
|
||||
|
||||
x >>= 8;
|
||||
if(padding < 2)
|
||||
dest[1] = curlx_ultouc(x & 0xFFUL);
|
||||
|
||||
x >>= 8;
|
||||
dest[0] = curlx_ultouc(x & 0xFFUL);
|
||||
|
||||
return 3 - padding;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -82,58 +98,71 @@ static void decodeQuantum(unsigned char *dest, const char *src)
|
||||
CURLcode Curl_base64_decode(const char *src,
|
||||
unsigned char **outptr, size_t *outlen)
|
||||
{
|
||||
size_t srclen = 0;
|
||||
size_t length = 0;
|
||||
size_t equalsTerm = 0;
|
||||
size_t padding = 0;
|
||||
size_t i;
|
||||
size_t result;
|
||||
size_t numQuantums;
|
||||
unsigned char lastQuantum[3];
|
||||
size_t rawlen = 0;
|
||||
unsigned char *pos;
|
||||
unsigned char *newstr;
|
||||
|
||||
*outptr = NULL;
|
||||
*outlen = 0;
|
||||
srclen = strlen(src);
|
||||
|
||||
/* Check the length of the input string is valid */
|
||||
if(!srclen || srclen % 4)
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
/* Find the position of any = padding characters */
|
||||
while((src[length] != '=') && src[length])
|
||||
length++;
|
||||
|
||||
/* A maximum of two = padding characters is allowed */
|
||||
if(src[length] == '=') {
|
||||
equalsTerm++;
|
||||
if(src[length+equalsTerm] == '=')
|
||||
equalsTerm++;
|
||||
padding++;
|
||||
if(src[length + 1] == '=')
|
||||
padding++;
|
||||
}
|
||||
numQuantums = (length + equalsTerm) / 4;
|
||||
|
||||
/* Don't allocate a buffer if the decoded length is 0 */
|
||||
if(numQuantums == 0)
|
||||
return CURLE_OK;
|
||||
/* Check the = padding characters weren't part way through the input */
|
||||
if(length + padding != srclen)
|
||||
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
|
||||
(which may be partially thrown out) and the zero terminator. */
|
||||
newstr = malloc(rawlen+4);
|
||||
/* Calculate the size of the decoded string */
|
||||
rawlen = (numQuantums * 3) - padding;
|
||||
|
||||
/* Allocate our buffer including room for a zero terminator */
|
||||
newstr = malloc(rawlen + 1);
|
||||
if(!newstr)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
*outptr = newstr;
|
||||
pos = newstr;
|
||||
|
||||
/* Decode all but the last quantum (which may not decode to a
|
||||
multiple of 3 bytes) */
|
||||
for(i = 0; i < numQuantums - 1; i++) {
|
||||
decodeQuantum(newstr, src);
|
||||
newstr += 3; src += 4;
|
||||
/* Decode the quantums */
|
||||
for(i = 0; i < numQuantums; i++) {
|
||||
result = decodeQuantum(pos, src);
|
||||
if(!result) {
|
||||
Curl_safefree(newstr);
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* This final decode may actually read slightly past the end of the buffer
|
||||
if the input string is missing pad bytes. This will almost always be
|
||||
harmless. */
|
||||
decodeQuantum(lastQuantum, src);
|
||||
for(i = 0; i < 3 - equalsTerm; i++)
|
||||
newstr[i] = lastQuantum[i];
|
||||
pos += result;
|
||||
src += 4;
|
||||
}
|
||||
|
||||
newstr[i] = '\0'; /* zero terminate */
|
||||
/* Zero terminate */
|
||||
*pos = '\0';
|
||||
|
||||
*outlen = rawlen; /* return size of decoded data */
|
||||
/* Return the decoded data */
|
||||
*outptr = newstr;
|
||||
*outlen = rawlen;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -277,21 +277,27 @@
|
||||
/* Define if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H
|
||||
|
||||
|
||||
/* The following define is needed on OS400 to enable strcmpi(), stricmp() and
|
||||
strdup(). */
|
||||
#define __cplusplus__strings__
|
||||
|
||||
/* Define if you have the `strcasecmp' function. */
|
||||
#undef HAVE_STRCASECMP
|
||||
|
||||
/* Define if you have the `strcmpi' function. */
|
||||
#undef HAVE_STRCMPI
|
||||
#define HAVE_STRCMPI
|
||||
|
||||
/* Define if you have the `stricmp' function. */
|
||||
#define HAVE_STRICMP
|
||||
|
||||
/* Define if you have the `strdup' function. */
|
||||
#undef HAVE_STRDUP
|
||||
#define HAVE_STRDUP
|
||||
|
||||
|
||||
/* Define if you have the `strftime' function. */
|
||||
#define HAVE_STRFTIME
|
||||
|
||||
/* Define if you have the `stricmp' function. */
|
||||
#undef HAVE_STRICMP
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H
|
||||
|
||||
@@ -523,7 +529,10 @@
|
||||
#define SEND_TYPE_RETV int
|
||||
|
||||
/* 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. */
|
||||
#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB"
|
||||
|
||||
@@ -390,21 +390,6 @@
|
||||
# define SIZEOF_SIZE_T 4
|
||||
#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 */
|
||||
/* ---------------------------------------------------------------- */
|
||||
@@ -572,6 +557,25 @@
|
||||
# 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 */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
312
lib/connect.c
312
lib/connect.c
@@ -164,8 +164,7 @@ tcpkeepalive(struct SessionHandle *data,
|
||||
static CURLcode
|
||||
singleipconnect(struct connectdata *conn,
|
||||
const Curl_addrinfo *ai, /* start connecting to this */
|
||||
curl_socket_t *sock,
|
||||
bool *connected);
|
||||
curl_socket_t *sock);
|
||||
|
||||
/*
|
||||
* Curl_timeleft() returns the amount of milliseconds left allowed for the
|
||||
@@ -233,45 +232,6 @@ long Curl_timeleft(struct SessionHandle *data,
|
||||
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,
|
||||
curl_socket_t sockfd, int af)
|
||||
{
|
||||
@@ -573,42 +533,53 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
|
||||
more address exists or error */
|
||||
static CURLcode trynextip(struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *connected)
|
||||
int tempindex)
|
||||
{
|
||||
curl_socket_t sockfd;
|
||||
Curl_addrinfo *ai;
|
||||
CURLcode rc = CURLE_COULDNT_CONNECT;
|
||||
|
||||
/* First clean up after the failed socket.
|
||||
Don't close it yet to ensure that the next IP's socket gets a different
|
||||
file descriptor, which can prevent bugs when the curl_multi_socket_action
|
||||
interface is used with certain select() replacements such as kqueue. */
|
||||
curl_socket_t fd_to_close = conn->sock[sockindex];
|
||||
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||
*connected = FALSE;
|
||||
curl_socket_t fd_to_close = conn->tempsock[tempindex];
|
||||
conn->tempsock[tempindex] = CURL_SOCKET_BAD;
|
||||
|
||||
if(sockindex != FIRSTSOCKET) {
|
||||
Curl_closesocket(conn, fd_to_close);
|
||||
return CURLE_COULDNT_CONNECT; /* no next */
|
||||
if(sockindex == FIRSTSOCKET) {
|
||||
Curl_addrinfo *ai;
|
||||
int family;
|
||||
|
||||
if(conn->tempaddr[tempindex]) {
|
||||
/* find next address in the same protocol family */
|
||||
family = conn->tempaddr[tempindex]->ai_family;
|
||||
ai = conn->tempaddr[tempindex]->ai_next;
|
||||
}
|
||||
else {
|
||||
/* happy eyeballs - try the other protocol family */
|
||||
int firstfamily = conn->tempaddr[0]->ai_family;
|
||||
family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
|
||||
ai = conn->tempaddr[0]->ai_next;
|
||||
}
|
||||
|
||||
/* try the next address */
|
||||
ai = conn->ip_addr->ai_next;
|
||||
|
||||
while(ai) {
|
||||
CURLcode res = singleipconnect(conn, ai, &sockfd, connected);
|
||||
if(res)
|
||||
return res;
|
||||
if(sockfd != CURL_SOCKET_BAD) {
|
||||
/* store the new socket descriptor */
|
||||
conn->sock[sockindex] = sockfd;
|
||||
conn->ip_addr = ai;
|
||||
Curl_closesocket(conn, fd_to_close);
|
||||
return CURLE_OK;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(fd_to_close != CURL_SOCKET_BAD)
|
||||
Curl_closesocket(conn, fd_to_close);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
return;
|
||||
}
|
||||
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
||||
|
||||
if(!getaddressinfo((struct sockaddr*)&ssloc,
|
||||
conn->local_ip, &conn->local_port)) {
|
||||
@@ -732,11 +704,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode code = CURLE_OK;
|
||||
curl_socket_t sockfd = conn->sock[sockindex];
|
||||
long allow = DEFAULT_CONNECT_TIMEOUT;
|
||||
long allow;
|
||||
int error = 0;
|
||||
struct timeval now;
|
||||
enum chkconn_t chk;
|
||||
int result;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
|
||||
|
||||
@@ -759,25 +731,51 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
for(i=0; i<2; i++) {
|
||||
if(conn->tempsock[i] == CURL_SOCKET_BAD)
|
||||
continue;
|
||||
|
||||
#ifdef mpeix
|
||||
/* Call this function once now, and ignore the results. We do this to
|
||||
"clear" the error state on the socket so that we can later read it
|
||||
reliably. This is reported necessary on the MPE/iX operating system. */
|
||||
(void)verifyconnect(conn->tempsock[i], NULL);
|
||||
#endif
|
||||
|
||||
/* check socket for connect */
|
||||
chk = checkconnect(sockfd);
|
||||
if(CHKCONN_IDLE == chk) {
|
||||
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);
|
||||
goto next;
|
||||
error = ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* not an error, but also no connection yet */
|
||||
return code;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if(CHKCONN_CONNECTED == chk) {
|
||||
if(verifyconnect(sockfd, &error)) {
|
||||
}
|
||||
else if(result == CURL_CSELECT_OUT) {
|
||||
if(verifyconnect(conn->tempsock[i], &error)) {
|
||||
/* we are connected with TCP, awesome! */
|
||||
int other = i ^ 1;
|
||||
|
||||
/* use this socket from now on */
|
||||
conn->sock[sockindex] = conn->tempsock[i];
|
||||
conn->ip_addr = conn->tempaddr[i];
|
||||
conn->tempsock[i] = CURL_SOCKET_BAD;
|
||||
|
||||
/* close the other socket, if open */
|
||||
if(conn->tempsock[other] != CURL_SOCKET_BAD) {
|
||||
Curl_closesocket(conn, conn->tempsock[other]);
|
||||
conn->tempsock[other] = CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
/* see if we need to do any proxy magic first once we connected */
|
||||
code = Curl_connected_proxy(conn);
|
||||
code = Curl_connected_proxy(conn, sockindex);
|
||||
if(code)
|
||||
return code;
|
||||
|
||||
@@ -786,42 +784,51 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
*connected = TRUE;
|
||||
if(sockindex == FIRSTSOCKET)
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
|
||||
Curl_updateconninfo(conn, conn->sock[sockindex]);
|
||||
Curl_verboseconnect(conn);
|
||||
Curl_updateconninfo(conn, sockfd);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
/* nope, not connected for real */
|
||||
}
|
||||
else {
|
||||
/* nope, not connected */
|
||||
if(CHKCONN_FDSET_ERROR == chk) {
|
||||
(void)verifyconnect(sockfd, &error);
|
||||
infof(data, "%s\n",Curl_strerror(conn, error));
|
||||
}
|
||||
else
|
||||
infof(data, "Connection failed\n");
|
||||
}
|
||||
else if(result & CURL_CSELECT_ERR)
|
||||
(void)verifyconnect(conn->tempsock[i], &error);
|
||||
|
||||
/*
|
||||
* The connection failed here, we should attempt to connect to the "next
|
||||
* address" for the given host. But first remember the latest error.
|
||||
*/
|
||||
if(error) {
|
||||
char ipaddress[MAX_IPADR_LEN];
|
||||
data->state.os_errno = error;
|
||||
SET_SOCKERRNO(error);
|
||||
}
|
||||
next:
|
||||
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->ip_addr->ai_next == NULL ?
|
||||
conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
|
||||
allow : allow / 2;
|
||||
code = trynextip(conn, sockindex, connected);
|
||||
|
||||
code = trynextip(conn, sockindex, i);
|
||||
}
|
||||
}
|
||||
|
||||
if(code) {
|
||||
error = SOCKERRNO;
|
||||
data->state.os_errno = error;
|
||||
failf(data, "Failed connect to %s:%ld; %s",
|
||||
conn->host.name, conn->port, Curl_strerror(conn, error));
|
||||
/* no more addresses to try */
|
||||
|
||||
/* if the first address family runs out of addresses to try before
|
||||
the happy eyeball timeout, go ahead and try the next family now */
|
||||
if(conn->tempaddr[1] == NULL) {
|
||||
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;
|
||||
@@ -938,8 +945,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
|
||||
static CURLcode
|
||||
singleipconnect(struct connectdata *conn,
|
||||
const Curl_addrinfo *ai,
|
||||
curl_socket_t *sockp,
|
||||
bool *connected)
|
||||
curl_socket_t *sockp)
|
||||
{
|
||||
struct Curl_sockaddr_ex addr;
|
||||
int rc;
|
||||
@@ -948,9 +954,10 @@ singleipconnect(struct connectdata *conn,
|
||||
struct SessionHandle *data = conn->data;
|
||||
curl_socket_t sockfd;
|
||||
CURLcode res = CURLE_OK;
|
||||
char ipaddress[MAX_IPADR_LEN];
|
||||
long port;
|
||||
|
||||
*sockp = CURL_SOCKET_BAD;
|
||||
*connected = FALSE; /* default is not connected */
|
||||
|
||||
res = Curl_socket(conn, ai, &addr, &sockfd);
|
||||
if(res)
|
||||
@@ -961,7 +968,7 @@ singleipconnect(struct connectdata *conn,
|
||||
|
||||
/* store remote address and port used in this connection attempt */
|
||||
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 */
|
||||
error = ERRNO;
|
||||
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
|
||||
@@ -969,10 +976,7 @@ singleipconnect(struct connectdata *conn,
|
||||
Curl_closesocket(conn, sockfd);
|
||||
return CURLE_OK;
|
||||
}
|
||||
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
||||
infof(data, " Trying %s...\n", conn->ip_addr_str);
|
||||
|
||||
Curl_persistconninfo(conn);
|
||||
infof(data, " Trying %s...\n", ipaddress);
|
||||
|
||||
if(data->set.tcp_nodelay)
|
||||
tcpnodelay(conn, sockfd);
|
||||
@@ -1033,7 +1037,7 @@ singleipconnect(struct connectdata *conn,
|
||||
#endif
|
||||
|
||||
if(-1 == rc) {
|
||||
switch (error) {
|
||||
switch(error) {
|
||||
case EINPROGRESS:
|
||||
case EWOULDBLOCK:
|
||||
#if defined(EAGAIN)
|
||||
@@ -1045,25 +1049,25 @@ singleipconnect(struct connectdata *conn,
|
||||
case EAGAIN:
|
||||
#endif
|
||||
#endif
|
||||
*sockp = sockfd;
|
||||
return CURLE_OK;
|
||||
res = CURLE_OK;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown error, fallthrough and try another address! */
|
||||
failf(data, "Failed to connect to %s: %s",
|
||||
conn->ip_addr_str, Curl_strerror(conn,error));
|
||||
infof(data, "Immediate connect fail for %s: %s\n",
|
||||
ipaddress, Curl_strerror(conn,error));
|
||||
data->state.os_errno = error;
|
||||
|
||||
/* connect failed */
|
||||
Curl_closesocket(conn, sockfd);
|
||||
res = CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(!res)
|
||||
*sockp = sockfd;
|
||||
|
||||
return CURLE_OK;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1073,29 +1077,13 @@ singleipconnect(struct connectdata *conn,
|
||||
*/
|
||||
|
||||
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
const struct Curl_dns_entry *remotehost,
|
||||
curl_socket_t *sockconn, /* the connected socket */
|
||||
Curl_addrinfo **addr, /* the one we used */
|
||||
bool *connected) /* really connected? */
|
||||
const struct Curl_dns_entry *remotehost)
|
||||
{
|
||||
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();
|
||||
CURLcode res;
|
||||
|
||||
/*************************************************************
|
||||
* 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);
|
||||
long timeout_ms = Curl_timeleft(data, &before, TRUE);
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* a precaution, no need to continue if time already is up */
|
||||
@@ -1104,58 +1092,28 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
}
|
||||
|
||||
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
|
||||
* know for the given host. One by one until one IP succeeds.
|
||||
*/
|
||||
/* start connecting to first IP */
|
||||
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);
|
||||
|
||||
/*
|
||||
* Connecting with a Curl_addrinfo chain
|
||||
*/
|
||||
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)
|
||||
if(conn->tempsock[0] == CURL_SOCKET_BAD)
|
||||
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 */
|
||||
|
||||
return CURLE_OK;
|
||||
|
||||
@@ -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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -31,11 +31,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
bool *connected);
|
||||
|
||||
CURLcode Curl_connecthost(struct connectdata *conn,
|
||||
const struct Curl_dns_entry *host, /* connect to
|
||||
this */
|
||||
curl_socket_t *sockconn, /* not set if error */
|
||||
Curl_addrinfo **addr, /* the one we used */
|
||||
bool *connected); /* truly connected? */
|
||||
const struct Curl_dns_entry *host);
|
||||
|
||||
/* generic function that returns how much time there's left to run, according
|
||||
to the timeouts set */
|
||||
@@ -44,6 +40,8 @@ long Curl_timeleft(struct SessionHandle *data,
|
||||
bool duringconnect);
|
||||
|
||||
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
|
||||
#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between
|
||||
ipv4/ipv6 connection attempts */
|
||||
|
||||
/*
|
||||
* Used to extract socket and connectdata struct for the most recent
|
||||
|
||||
42
lib/cookie.c
42
lib/cookie.c
@@ -89,6 +89,7 @@ Example set of cookies:
|
||||
#include "strequal.h"
|
||||
#include "strtok.h"
|
||||
#include "sendf.h"
|
||||
#include "slist.h"
|
||||
#include "curl_memory.h"
|
||||
#include "share.h"
|
||||
#include "strtoofft.h"
|
||||
@@ -289,6 +290,34 @@ static void strstore(char **str, const char *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
|
||||
the same domain and path as this */
|
||||
|
||||
/* at first, remove expired cookies */
|
||||
remove_expired(c);
|
||||
|
||||
clist = c->cookies;
|
||||
replace_old = FALSE;
|
||||
while(clist) {
|
||||
@@ -930,6 +962,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
||||
if(!c || !c->cookies)
|
||||
return NULL; /* no cookie struct or no cookies in the struct */
|
||||
|
||||
/* at first, remove expired cookies */
|
||||
remove_expired(c);
|
||||
|
||||
co = c->cookies;
|
||||
|
||||
while(co) {
|
||||
@@ -1172,6 +1207,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
|
||||
destination file */
|
||||
return 0;
|
||||
|
||||
/* at first, remove expired cookies */
|
||||
remove_expired(c);
|
||||
|
||||
if(strequal("-", dumphere)) {
|
||||
/* use stdout */
|
||||
out = stdout;
|
||||
@@ -1232,9 +1270,9 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
|
||||
curl_slist_free_all(list);
|
||||
return NULL;
|
||||
}
|
||||
beg = curl_slist_append(list, line);
|
||||
free(line);
|
||||
beg = Curl_slist_append_nodup(list, line);
|
||||
if(!beg) {
|
||||
free(line);
|
||||
curl_slist_free_all(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -38,9 +38,58 @@
|
||||
#include <Security/SecureTransport.h>
|
||||
#include <CoreFoundation/CoreFoundation.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 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>
|
||||
#endif
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
@@ -61,16 +110,6 @@
|
||||
#define ioErr -36
|
||||
#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,
|
||||
* with some modifications: */
|
||||
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:
|
||||
return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
|
||||
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) */
|
||||
case 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:
|
||||
return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
|
||||
break;
|
||||
#endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */
|
||||
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
|
||||
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
|
||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||
/* TLS 1.2 (RFC 5246) */
|
||||
case TLS_RSA_WITH_NULL_MD5:
|
||||
return "TLS_RSA_WITH_NULL_MD5";
|
||||
@@ -624,12 +663,116 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
|
||||
case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
|
||||
return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
|
||||
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";
|
||||
}
|
||||
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_BUILD_MAC
|
||||
CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
|
||||
{
|
||||
int mib[2];
|
||||
@@ -658,7 +801,7 @@ CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
|
||||
*minor = atoi(os_version_minor);
|
||||
free(os_version);
|
||||
}
|
||||
#endif
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
|
||||
/* Apple provides a myriad of ways of getting information about a certificate
|
||||
into a string. Some aren't available under iOS or newer cats. So here's
|
||||
@@ -668,37 +811,36 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
|
||||
{
|
||||
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. */
|
||||
server_cert_summary = SecCertificateCopySubjectSummary(cert);
|
||||
#else
|
||||
#if defined(__MAC_10_7)
|
||||
#if CURL_BUILD_MAC_10_7
|
||||
/* Lion & later: Get the long description if we can. */
|
||||
if(SecCertificateCopyLongDescription != NULL)
|
||||
server_cert_summary =
|
||||
SecCertificateCopyLongDescription(NULL, cert, NULL);
|
||||
else
|
||||
#endif /* defined(__MAC_10_7) */
|
||||
#if defined(__MAC_10_6)
|
||||
#endif /* CURL_BUILD_MAC_10_7 */
|
||||
#if CURL_BUILD_MAC_10_6
|
||||
/* Snow Leopard: Get the certificate summary. */
|
||||
if(SecCertificateCopySubjectSummary != NULL)
|
||||
server_cert_summary = SecCertificateCopySubjectSummary(cert);
|
||||
else
|
||||
#endif /* defined(__MAC_10_6) */
|
||||
#endif /* CURL_BUILD_MAC_10_6 */
|
||||
/* Leopard is as far back as we go... */
|
||||
(void)SecCertificateCopyCommonName(cert, &server_cert_summary);
|
||||
#endif /* (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) */
|
||||
#endif /* CURL_BUILD_IOS */
|
||||
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,
|
||||
SecIdentityRef *out_c_a_k)
|
||||
{
|
||||
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;
|
||||
SecKeychainAttribute attr;
|
||||
SecKeychainSearchRef search = NULL;
|
||||
@@ -730,22 +872,20 @@ static OSStatus CopyIdentityWithLabelOldSchool(char *label,
|
||||
|
||||
if(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;
|
||||
}
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_6 */
|
||||
|
||||
static OSStatus CopyIdentityWithLabel(char *label,
|
||||
SecIdentityRef *out_cert_and_key)
|
||||
{
|
||||
OSStatus status = errSecItemNotFound;
|
||||
|
||||
#if defined(__MAC_10_6) || defined(__IPHONE_2_0)
|
||||
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard. If it
|
||||
exists, let's use that to find the certificate. */
|
||||
if(SecItemCopyMatching != NULL) {
|
||||
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
|
||||
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
|
||||
kSecClassIdentity was introduced in Lion. If both exist, let's use them
|
||||
to find the certificate. */
|
||||
if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
|
||||
CFTypeRef keys[4];
|
||||
CFTypeRef values[4];
|
||||
CFDictionaryRef query_dict;
|
||||
@@ -774,18 +914,83 @@ static OSStatus CopyIdentityWithLabel(char *label,
|
||||
CFRelease(query_dict);
|
||||
}
|
||||
else {
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
/* On Leopard, fall back to SecKeychainSearch. */
|
||||
#if CURL_SUPPORT_MAC_10_6
|
||||
/* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
|
||||
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))
|
||||
/* For developers building on Leopard, we have no choice but to fall back. */
|
||||
#elif CURL_SUPPORT_MAC_10_6
|
||||
/* For developers building on older cats, we have no choice but to fall back
|
||||
to SecKeychainSearch. */
|
||||
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
|
||||
#endif /* defined(__MAC_10_6) || defined(__IPHONE_2_0) */
|
||||
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
|
||||
return status;
|
||||
}
|
||||
|
||||
static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
|
||||
const char *cPassword,
|
||||
SecIdentityRef *out_cert_and_key)
|
||||
{
|
||||
OSStatus status = errSecItemNotFound;
|
||||
CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL,
|
||||
(const UInt8 *)cPath, strlen(cPath), false);
|
||||
CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
|
||||
cPassword, kCFStringEncodingUTF8) : NULL;
|
||||
CFDataRef pkcs_data = NULL;
|
||||
|
||||
/* We can import P12 files on iOS or OS X 10.7 or later: */
|
||||
/* These constants are documented as having first appeared in 10.6 but they
|
||||
raise linker errors when used on that cat for some reason. */
|
||||
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
|
||||
if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
|
||||
NULL, NULL, &status)) {
|
||||
const void *cKeys[] = {kSecImportExportPassphrase};
|
||||
const void *cValues[] = {password};
|
||||
CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
|
||||
password ? 1L : 0L, NULL, NULL);
|
||||
CFArrayRef items = NULL;
|
||||
|
||||
/* Here we go: */
|
||||
status = SecPKCS12Import(pkcs_data, options, &items);
|
||||
if(status == noErr) {
|
||||
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,
|
||||
int sockindex)
|
||||
{
|
||||
@@ -796,19 +1001,19 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
struct in6_addr addr;
|
||||
#else
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
#endif /* ENABLE_IPV6 */
|
||||
size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
|
||||
SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
|
||||
char *ssl_sessionid;
|
||||
size_t ssl_sessionid_len;
|
||||
OSStatus err = noErr;
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_BUILD_MAC
|
||||
int darwinver_maj = 0, darwinver_min = 0;
|
||||
|
||||
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(connssl->ssl_ctx)
|
||||
CFRelease(connssl->ssl_ctx);
|
||||
@@ -820,7 +1025,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* 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)
|
||||
(void)SSLDisposeContext(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);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
}
|
||||
#else
|
||||
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);
|
||||
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 */
|
||||
|
||||
/* 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) {
|
||||
switch(data->set.ssl.version) {
|
||||
case CURL_SSLVERSION_DEFAULT: default:
|
||||
@@ -853,17 +1058,33 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_0:
|
||||
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_2:
|
||||
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
|
||||
break;
|
||||
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);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocolAll,
|
||||
false);
|
||||
@@ -893,18 +1114,37 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
kTLSProtocol12,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_0:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kTLSProtocol1,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kTLSProtocol11,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_2:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kTLSProtocol12,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocol3,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocol2,
|
||||
true);
|
||||
if(err != noErr) {
|
||||
failf(data, "Your version of the OS does not support SSLv2");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
}
|
||||
#else
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
|
||||
@@ -919,14 +1159,25 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
case CURL_SSLVERSION_TLSv1_0:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kTLSProtocol1,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
failf(data, "Your version of the OS does not support TLSv1.1");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
case CURL_SSLVERSION_TLSv1_2:
|
||||
failf(data, "Your version of the OS does not support TLSv1.2");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocol2,
|
||||
true);
|
||||
if(err != noErr) {
|
||||
failf(data, "Your version of the OS does not support SSLv2");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
@@ -934,18 +1185,36 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
true);
|
||||
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]) {
|
||||
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]) {
|
||||
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: */
|
||||
/* User wants to authenticate with a client cert. Look for it:
|
||||
If we detect that this is a file on disk, then let's load it.
|
||||
Otherwise, assume that the user wants to use an identity loaded
|
||||
from the Keychain. */
|
||||
if(is_cert_file) {
|
||||
if(!data->set.str[STRING_CERT_TYPE])
|
||||
infof(data, "WARNING: SSL: Certificate type not set, assuming "
|
||||
"PKCS#12 format.\n");
|
||||
else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
|
||||
strlen(data->set.str[STRING_CERT_TYPE])) != 0)
|
||||
infof(data, "WARNING: SSL: The Security framework only supports "
|
||||
"loading identities that are in PKCS#12 format.\n");
|
||||
|
||||
err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
|
||||
data->set.str[STRING_KEY_PASSWD], &cert_and_key);
|
||||
}
|
||||
else
|
||||
err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
|
||||
|
||||
if(err == noErr) {
|
||||
SecCertificateRef cert = NULL;
|
||||
CFTypeRef certs_c[1];
|
||||
@@ -982,8 +1251,29 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
CFRelease(cert_and_key);
|
||||
}
|
||||
else {
|
||||
failf(data, "SSL: Can't find the certificate \"%s\" and its private key "
|
||||
"in the Keychain.", data->set.str[STRING_CERT]);
|
||||
switch(err) {
|
||||
case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
|
||||
failf(data, "SSL: Incorrect password for the certificate \"%s\" "
|
||||
"and its private key.", data->set.str[STRING_CERT]);
|
||||
break;
|
||||
case 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;
|
||||
}
|
||||
}
|
||||
@@ -992,7 +1282,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
* fail to connect if the verification fails, or if it should continue
|
||||
* anyway. In the latter case the result of the verification is checked with
|
||||
* SSL_get_verify_result() below. */
|
||||
#if 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
|
||||
a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
|
||||
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
|
||||
default.) */
|
||||
/* (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) {
|
||||
#else
|
||||
if(SSLSetSessionOption != NULL) {
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
err = SSLSetSessionOption(connssl->ssl_ctx,
|
||||
kSSLSessionOptionBreakOnServerAuth,
|
||||
data->set.ssl.verifypeer?false:true);
|
||||
@@ -1015,14 +1305,14 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
||||
data->set.ssl.verifypeer?true:false);
|
||||
if(err != noErr) {
|
||||
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
}
|
||||
#else
|
||||
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);
|
||||
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.
|
||||
* 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,
|
||||
strlen(conn->host.name));
|
||||
if(err != noErr) {
|
||||
infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d",
|
||||
infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
|
||||
err);
|
||||
}
|
||||
}
|
||||
@@ -1061,7 +1351,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
|
||||
&all_ciphers_count) == noErr) {
|
||||
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
|
||||
ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
switch(all_ciphers[i]) {
|
||||
/* Disable NULL ciphersuites: */
|
||||
case SSL_NULL_WITH_NULL_NULL:
|
||||
case SSL_RSA_WITH_NULL_MD5:
|
||||
case SSL_RSA_WITH_NULL_SHA:
|
||||
case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
|
||||
case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
|
||||
case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
|
||||
case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
|
||||
case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
|
||||
case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
|
||||
case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
|
||||
case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
|
||||
case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
|
||||
case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
|
||||
case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
|
||||
case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
|
||||
case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
|
||||
case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
|
||||
case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
|
||||
/* Disable anonymous ciphersuites: */
|
||||
case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
|
||||
case SSL_DH_anon_WITH_RC4_128_MD5:
|
||||
@@ -1136,6 +1436,14 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
Curl_safefree(all_ciphers);
|
||||
Curl_safefree(allowed_ciphers);
|
||||
|
||||
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
|
||||
/* We want to enable 1/n-1 when using a CBC cipher unless the user
|
||||
specifically doesn't want us doing that: */
|
||||
if(SSLSetSessionOption != NULL)
|
||||
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
|
||||
!data->set.ssl_enable_beast);
|
||||
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
|
||||
|
||||
/* Check if there's a cached ID we can/should use here! */
|
||||
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
|
||||
&ssl_sessionid_len)) {
|
||||
@@ -1303,7 +1611,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
infof(data, "TLS 1.0 connection using %s\n",
|
||||
TLSCipherNameForNumber(cipher));
|
||||
break;
|
||||
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
|
||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||
case kTLSProtocol11:
|
||||
infof(data, "TLS 1.1 connection using %s\n",
|
||||
TLSCipherNameForNumber(cipher));
|
||||
@@ -1330,20 +1638,22 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
CFStringRef server_cert_summary;
|
||||
char server_cert_summary_c[128];
|
||||
CFArrayRef server_certs;
|
||||
CFArrayRef server_certs = NULL;
|
||||
SecCertificateRef server_cert;
|
||||
OSStatus err;
|
||||
CFIndex i, count;
|
||||
SecTrustRef trust;
|
||||
SecTrustRef trust = NULL;
|
||||
|
||||
/* There is no step 3!
|
||||
* Well, okay, if verbose mode is on, let's print the details of the
|
||||
* server certificates. */
|
||||
#if defined(__MAC_10_7) || defined(__IPHONE_5_0)
|
||||
#if (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
|
||||
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
|
||||
#if CURL_BUILD_IOS
|
||||
#pragma unused(server_certs)
|
||||
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);
|
||||
for(i = 0L ; i < count ; i++) {
|
||||
server_cert = SecTrustGetCertificateAtIndex(trust, i);
|
||||
@@ -1369,7 +1679,9 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
if(SecTrustEvaluateAsync != NULL) {
|
||||
#pragma unused(server_certs)
|
||||
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);
|
||||
for(i = 0L ; i < count ; i++) {
|
||||
server_cert = SecTrustGetCertificateAtIndex(trust, i);
|
||||
@@ -1387,8 +1699,10 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
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);
|
||||
for(i = 0L ; i < count ; i++) {
|
||||
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
|
||||
@@ -1406,8 +1720,9 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
CFRelease(server_certs);
|
||||
}
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
}
|
||||
#endif /* (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) */
|
||||
#endif /* CURL_BUILD_IOS */
|
||||
#else
|
||||
#pragma unused(trust)
|
||||
err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
|
||||
@@ -1427,7 +1742,7 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
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;
|
||||
return CURLE_OK;
|
||||
@@ -1579,16 +1894,16 @@ void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
|
||||
|
||||
if(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)
|
||||
CFRelease(connssl->ssl_ctx);
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
else
|
||||
(void)SSLDisposeContext(connssl->ssl_ctx);
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
#else
|
||||
(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_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
|
||||
* 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 */
|
||||
size_t md5len);
|
||||
|
||||
/* this backend provides these functions: */
|
||||
#define have_curlssl_random 1
|
||||
#define have_curlssl_md5sum 1
|
||||
|
||||
/* API setup for SecureTransport */
|
||||
#define curlssl_init() (1)
|
||||
#define curlssl_cleanup() Curl_nop_stmt
|
||||
|
||||
@@ -87,6 +87,9 @@ extern curl_free_callback Curl_cfree;
|
||||
extern curl_realloc_callback Curl_crealloc;
|
||||
extern curl_strdup_callback Curl_cstrdup;
|
||||
extern curl_calloc_callback Curl_ccalloc;
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
extern curl_wcsdup_callback Curl_cwcsdup;
|
||||
#endif
|
||||
|
||||
#ifndef CURLDEBUG
|
||||
|
||||
@@ -110,6 +113,20 @@ extern curl_calloc_callback Curl_ccalloc;
|
||||
#undef free
|
||||
#define free(ptr) Curl_cfree(ptr)
|
||||
|
||||
#ifdef WIN32
|
||||
# ifdef UNICODE
|
||||
# undef wcsdup
|
||||
# define wcsdup(ptr) Curl_cwcsdup(ptr)
|
||||
# undef _wcsdup
|
||||
# define _wcsdup(ptr) Curl_cwcsdup(ptr)
|
||||
# undef _tcsdup
|
||||
# define _tcsdup(ptr) Curl_cwcsdup(ptr)
|
||||
# else
|
||||
# undef _tcsdup
|
||||
# define _tcsdup(ptr) Curl_cstrdup(ptr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* CURLDEBUG */
|
||||
|
||||
#else /* CURLX_NO_MEMORY_CALLBACKS */
|
||||
|
||||
@@ -77,10 +77,6 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
|
||||
|
||||
ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
|
||||
|
||||
/* skip initial whitespaces */
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
if(checkprefix("NTLM", header)) {
|
||||
header += strlen("NTLM");
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
||||
conn->response_header = NULL;
|
||||
break;
|
||||
case NTLMSTATE_TYPE2:
|
||||
input = aprintf("TT %s", conn->challenge_header);
|
||||
input = aprintf("TT %s\n", conn->challenge_header);
|
||||
if(!input)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
res = ntlm_wb_response(conn, input, ntlm->state);
|
||||
|
||||
304
lib/curl_sasl.c
304
lib/curl_sasl.c
@@ -22,6 +22,8 @@
|
||||
* RFC2831 DIGEST-MD5 authentication
|
||||
* RFC4422 Simple Authentication and Security Layer (SASL)
|
||||
* 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_md5.h"
|
||||
#include "curl_rand.h"
|
||||
#include "sslgen.h"
|
||||
#include "curl_hmac.h"
|
||||
#include "curl_ntlm_msgs.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
#ifdef USE_NSS
|
||||
#include "nssg.h" /* for Curl_nss_force_init() */
|
||||
#endif
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
@@ -49,7 +55,7 @@
|
||||
/* Retrieves the value for a corresponding key from the challenge string
|
||||
* returns TRUE if the key could be found, FALSE if it does not exists
|
||||
*/
|
||||
static bool sasl_digest_get_key_value(const unsigned char *chlg,
|
||||
static bool sasl_digest_get_key_value(const char *chlg,
|
||||
const char *key,
|
||||
char *value,
|
||||
size_t max_val_len,
|
||||
@@ -58,7 +64,7 @@ static bool sasl_digest_get_key_value(const unsigned char *chlg,
|
||||
char *find_pos;
|
||||
size_t i;
|
||||
|
||||
find_pos = strstr((const char *) chlg, key);
|
||||
find_pos = strstr(chlg, key);
|
||||
if(!find_pos)
|
||||
return FALSE;
|
||||
|
||||
@@ -94,18 +100,18 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
|
||||
const char *passwdp,
|
||||
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 plen;
|
||||
|
||||
ulen = strlen(userp);
|
||||
plen = strlen(passwdp);
|
||||
|
||||
if(2 * ulen + plen + 2 > sizeof(plainauth)) {
|
||||
plainauth = malloc(2 * ulen + plen + 2);
|
||||
if(!plainauth) {
|
||||
*outlen = 0;
|
||||
*outptr = NULL;
|
||||
|
||||
/* Plainauth too small */
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
Curl_safefree(plainauth);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -160,7 +168,37 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
#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()
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* chlg64 [in] - Pointer to the base64 encoded challenge buffer.
|
||||
* chlg [in] - The challenge.
|
||||
* userp [in] - The user name.
|
||||
* passdwp [in] - The user's password.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
@@ -179,55 +217,110 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *chlg,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t chlg64len = strlen(chlg64);
|
||||
unsigned char *chlg = (unsigned char *) NULL;
|
||||
size_t chlglen = 0;
|
||||
HMAC_context *ctxt;
|
||||
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(chlg64len && *chlg64 != '=') {
|
||||
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
if(chlg)
|
||||
chlglen = strlen(chlg);
|
||||
|
||||
/* Compute the digest using the password as the key */
|
||||
ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
|
||||
(const unsigned char *) passwdp,
|
||||
curlx_uztoui(strlen(passwdp)));
|
||||
|
||||
if(!ctxt) {
|
||||
Curl_safefree(chlg);
|
||||
if(!ctxt)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Update the digest with the given challenge */
|
||||
if(chlglen > 0)
|
||||
Curl_HMAC_update(ctxt, chlg, curlx_uztoui(chlglen));
|
||||
|
||||
Curl_safefree(chlg);
|
||||
Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
|
||||
curlx_uztoui(chlglen));
|
||||
|
||||
/* Finalise the digest */
|
||||
Curl_HMAC_final(ctxt, digest);
|
||||
|
||||
/* Prepare the response */
|
||||
snprintf(response, sizeof(response),
|
||||
/* Generate the response */
|
||||
response = aprintf(
|
||||
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
userp, digest[0], digest[1], digest[2], digest[3], digest[4],
|
||||
digest[5], digest[6], digest[7], digest[8], digest[9], digest[10],
|
||||
digest[11], digest[12], digest[13], digest[14], digest[15]);
|
||||
if(!response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the reply */
|
||||
return Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
/* Base64 encode the response */
|
||||
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:
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
* holding the result will be stored upon completion.
|
||||
* 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.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *nonce,
|
||||
const char *realm,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
#ifndef DEBUGBUILD
|
||||
static const char table16[] = "0123456789abcdef";
|
||||
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
unsigned char *chlg = (unsigned char *) NULL;
|
||||
size_t chlglen = 0;
|
||||
size_t i;
|
||||
MD5_context *ctxt;
|
||||
char *response = NULL;
|
||||
unsigned char digest[MD5_DIGEST_LEN];
|
||||
char HA1_hex[2 * MD5_DIGEST_LEN + 1];
|
||||
char HA2_hex[2 * MD5_DIGEST_LEN + 1];
|
||||
char resp_hash_hex[2 * MD5_DIGEST_LEN + 1];
|
||||
|
||||
char nonce[64];
|
||||
char realm[128];
|
||||
char alg[64];
|
||||
char nonceCount[] = "00000001";
|
||||
char cnonce[] = "12345678"; /* will be changed */
|
||||
char method[] = "AUTHENTICATE";
|
||||
char qop[] = "auth";
|
||||
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 */
|
||||
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 */
|
||||
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++)
|
||||
snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
|
||||
|
||||
snprintf(response, sizeof(response),
|
||||
"username=\"%s\",realm=\"%s\",nonce=\"%s\","
|
||||
/* Generate the response */
|
||||
response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
|
||||
"cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s",
|
||||
userp, realm, nonce,
|
||||
cnonce, nonceCount, uri, resp_hash_hex);
|
||||
if(!response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the reply */
|
||||
return Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
|
||||
Curl_safefree(response);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -430,8 +495,36 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
struct ntlmdata *ntlm,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr,
|
||||
outlen);
|
||||
return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr, 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:
|
||||
*
|
||||
* 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.
|
||||
* passdwp [in] - The user's password.
|
||||
* 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.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
const char *header,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
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,
|
||||
outptr, outlen);
|
||||
/*
|
||||
* Curl_sasl_create_xoauth2_message()
|
||||
*
|
||||
* This is used to generate an already encoded OAuth 2.0 message ready for
|
||||
* sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* user [in] - The user name.
|
||||
* bearer [in] - The bearer token.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
#endif /* USE_NTLM */
|
||||
|
||||
/*
|
||||
* Curl_sasl_cleanup()
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
|
||||
#include "pingpong.h"
|
||||
|
||||
/* Authentication mechanism values */
|
||||
#define SASL_AUTH_NONE 0
|
||||
#define SASL_AUTH_ANY ~0U
|
||||
|
||||
/* Authentication mechanism flags */
|
||||
#define SASL_MECH_LOGIN (1 << 0)
|
||||
#define SASL_MECH_PLAIN (1 << 1)
|
||||
@@ -32,10 +36,22 @@
|
||||
#define SASL_MECH_GSSAPI (1 << 4)
|
||||
#define SASL_MECH_EXTERNAL (1 << 5)
|
||||
#define SASL_MECH_NTLM (1 << 6)
|
||||
#define SASL_MECH_XOAUTH2 (1 << 7)
|
||||
|
||||
/* Authentication mechanism values */
|
||||
#define SASL_AUTH_NONE 0
|
||||
#define SASL_AUTH_ANY ~0
|
||||
/* 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 */
|
||||
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);
|
||||
|
||||
#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 */
|
||||
CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *chlg,
|
||||
const char *user,
|
||||
const char *passwdp,
|
||||
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 */
|
||||
CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *nonce,
|
||||
const char *realm,
|
||||
const char *user,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
@@ -74,10 +101,13 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
char **outptr,
|
||||
size_t *outlen);
|
||||
|
||||
/* This is used to decode an incoming NTLM type-2 message and generate a
|
||||
base64 encoded type-3 response */
|
||||
/* This is used to decode a base64 encoded NTLM type-2 message */
|
||||
CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
|
||||
const char *type2msg,
|
||||
struct ntlmdata *ntlm);
|
||||
|
||||
/* This is used to generate a base64 encoded NTLM type-3 message */
|
||||
CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
const char *header,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
@@ -85,6 +115,13 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
|
||||
#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
|
||||
functions */
|
||||
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_2_CLIENT;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_0:
|
||||
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_2:
|
||||
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
|
||||
break;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef HEADER_CURL_KRB4_H
|
||||
#define HEADER_CURL_KRB4_H
|
||||
#ifndef HEADER_CURL_SECURITY_H
|
||||
#define HEADER_CURL_SECURITY_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* 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
|
||||
* 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 *);
|
||||
};
|
||||
|
||||
|
||||
#define AUTH_OK 0
|
||||
#define AUTH_CONTINUE 1
|
||||
#define AUTH_ERROR 2
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
extern struct Curl_sec_client_mech Curl_krb4_client_mech;
|
||||
#endif
|
||||
#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 *,
|
||||
enum protection_level);
|
||||
void Curl_sec_end (struct connectdata *);
|
||||
CURLcode Curl_sec_login (struct connectdata *);
|
||||
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
|
||||
# include <tchar.h>
|
||||
# ifdef UNICODE
|
||||
typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -617,7 +620,7 @@ int netware_init(void);
|
||||
#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || \
|
||||
defined(USE_QSOSSL) || defined(USE_POLARSSL) || defined(USE_AXTLS) || \
|
||||
defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_DARWINSSL)
|
||||
defined(USE_DARWINSSL) || defined(USE_GSKIT)
|
||||
#define USE_SSL /* SSL support has been enabled */
|
||||
#endif
|
||||
|
||||
|
||||
@@ -440,7 +440,7 @@ typedef int sig_atomic_t;
|
||||
* (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 SET_ERRNO(x) (SetLastError((DWORD)(x)))
|
||||
#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
|
||||
* 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();
|
||||
break;
|
||||
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();
|
||||
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:
|
||||
req_method = SSLv3_client_method();
|
||||
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
|
||||
#define HEADER_CURL_RAND_H
|
||||
#ifndef HEADER_CURL_DOTDOT_H
|
||||
#define HEADER_CURL_DOTDOT_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* 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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -21,9 +21,5 @@
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
void Curl_srand(void);
|
||||
|
||||
unsigned int Curl_rand(void);
|
||||
|
||||
#endif /* HEADER_CURL_RAND_H */
|
||||
char *Curl_dedotdotify(char *input);
|
||||
#endif
|
||||
471
lib/easy.c
471
lib/easy.c
@@ -69,11 +69,11 @@
|
||||
#include "connect.h" /* for Curl_getconnectinfo */
|
||||
#include "slist.h"
|
||||
#include "amigaos.h"
|
||||
#include "curl_rand.h"
|
||||
#include "non-ascii.h"
|
||||
#include "warnless.h"
|
||||
#include "conncache.h"
|
||||
#include "multiif.h"
|
||||
#include "sigpipe.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#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_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
|
||||
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
|
||||
#endif
|
||||
#else
|
||||
/*
|
||||
* Symbian OS doesn't support initialization to code in writeable static data.
|
||||
@@ -229,6 +232,9 @@ CURLcode curl_global_init(long flags)
|
||||
Curl_crealloc = (curl_realloc_callback)realloc;
|
||||
Curl_cstrdup = (curl_strdup_callback)system_strdup;
|
||||
Curl_ccalloc = (curl_calloc_callback)calloc;
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
|
||||
#endif
|
||||
|
||||
if(flags & CURL_GLOBAL_SSL)
|
||||
if(!Curl_ssl_init()) {
|
||||
@@ -276,10 +282,6 @@ CURLcode curl_global_init(long flags)
|
||||
|
||||
init_flags = flags;
|
||||
|
||||
/* Preset pseudo-random number sequence. */
|
||||
|
||||
Curl_srand();
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -397,67 +399,275 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* curl_easy_perform() is the external interface that performs a blocking
|
||||
* transfer as previously setup.
|
||||
#ifdef CURLDEBUG
|
||||
|
||||
struct socketmonitor {
|
||||
struct socketmonitor *next; /* the next node in the list or NULL */
|
||||
struct pollfd socket; /* socket info of what to monitor */
|
||||
};
|
||||
|
||||
struct events {
|
||||
long ms; /* timeout, run the timeout function when reached */
|
||||
bool msbump; /* set TRUE when timeout is set by callback */
|
||||
int num_sockets; /* number of nodes in the monitor list */
|
||||
struct socketmonitor *list; /* list of sockets to monitor */
|
||||
int running_handles; /* store the returned number */
|
||||
};
|
||||
|
||||
/* events_timer
|
||||
*
|
||||
* 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.
|
||||
* Callback that gets called with a new value when the timeout should be
|
||||
* updated.
|
||||
*/
|
||||
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;
|
||||
int rc;
|
||||
struct SessionHandle *data = easy;
|
||||
CURLMcode mcode;
|
||||
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
|
||||
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) {
|
||||
int still_running;
|
||||
@@ -480,9 +690,7 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
if(curlx_tvdiff(after, before) <= 10) {
|
||||
without_fds++;
|
||||
if(without_fds > 2) {
|
||||
int sleep_ms = without_fds * 50;
|
||||
if(sleep_ms > 1000)
|
||||
sleep_ms = 1000;
|
||||
int sleep_ms = without_fds < 10 ? (1 << (without_fds-1)): 1000;
|
||||
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 */
|
||||
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) {
|
||||
code = msg->data.result;
|
||||
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
|
||||
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 */
|
||||
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
|
||||
* easy handle.
|
||||
@@ -522,27 +822,14 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
void curl_easy_cleanup(CURL *curl)
|
||||
{
|
||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
Curl_close(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
sigpipe_restore(&pipe_st);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -554,12 +841,16 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
|
||||
{
|
||||
va_list arg;
|
||||
void *paramp;
|
||||
CURLcode ret;
|
||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||
|
||||
va_start(arg, info);
|
||||
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_easy_initHandleData(outcurl);
|
||||
|
||||
outcurl->magic = CURLEASY_MAGIC_NUMBER;
|
||||
|
||||
/* we reach this point and thus we are OK */
|
||||
@@ -672,7 +961,7 @@ void curl_easy_reset(CURL *curl)
|
||||
|
||||
data->state.path = NULL;
|
||||
|
||||
Curl_safefree(data->state.proto.generic);
|
||||
Curl_free_request_state(data);
|
||||
|
||||
/* zero out UserDefined data: */
|
||||
Curl_freeset(data);
|
||||
@@ -682,9 +971,6 @@ void curl_easy_reset(CURL *curl)
|
||||
/* zero out Progress data: */
|
||||
memset(&data->progress, 0, sizeof(struct Progress));
|
||||
|
||||
/* init Handle data */
|
||||
Curl_easy_initHandleData(data);
|
||||
|
||||
data->progress.flags |= PGRS_HIDE;
|
||||
data->state.current_speed = -1; /* init to negative == impossible */
|
||||
}
|
||||
@@ -746,7 +1032,7 @@ CURLcode curl_easy_pause(CURL *curl, int action)
|
||||
do {
|
||||
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);
|
||||
if(result)
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -25,9 +25,9 @@
|
||||
/*
|
||||
* Prototypes for library-wide functions provided by easy.c
|
||||
*/
|
||||
void Curl_easy_addmulti(struct SessionHandle *data, void *multi);
|
||||
|
||||
void Curl_easy_initHandleData(struct SessionHandle *data);
|
||||
#ifdef CURLDEBUG
|
||||
CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy);
|
||||
#endif
|
||||
|
||||
#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
|
||||
* 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_disconnect(struct connectdata *conn,
|
||||
bool dead_connection);
|
||||
|
||||
static CURLcode file_setup_connection(struct connectdata *conn);
|
||||
|
||||
/*
|
||||
* FILE scheme handler.
|
||||
@@ -98,7 +98,7 @@ static CURLcode file_disconnect(struct connectdata *conn,
|
||||
|
||||
const struct Curl_handler Curl_handler_file = {
|
||||
"FILE", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
file_setup_connection, /* setup_connection */
|
||||
file_do, /* do_it */
|
||||
file_done, /* done */
|
||||
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
|
||||
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;
|
||||
char *real_path;
|
||||
struct FILEPROTO *file;
|
||||
struct FILEPROTO *file = data->req.protop;
|
||||
int fd;
|
||||
#ifdef DOS_FILESYSTEM
|
||||
int i;
|
||||
char *actual_path;
|
||||
#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);
|
||||
if(!real_path)
|
||||
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
|
||||
/* If the first character is a slash, and there's
|
||||
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,
|
||||
CURLcode status, bool premature)
|
||||
{
|
||||
struct FILEPROTO *file = conn->data->state.proto.file;
|
||||
struct FILEPROTO *file = conn->data->req.protop;
|
||||
(void)status; /* not used */
|
||||
(void)premature; /* not used */
|
||||
|
||||
@@ -280,7 +268,7 @@ static CURLcode file_done(struct connectdata *conn,
|
||||
static CURLcode file_disconnect(struct connectdata *conn,
|
||||
bool dead_connection)
|
||||
{
|
||||
struct FILEPROTO *file = conn->data->state.proto.file;
|
||||
struct FILEPROTO *file = conn->data->req.protop;
|
||||
(void)dead_connection; /* not used */
|
||||
|
||||
if(file) {
|
||||
@@ -302,7 +290,7 @@ static CURLcode file_disconnect(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);
|
||||
int fd;
|
||||
int mode;
|
||||
@@ -440,6 +428,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
curl_off_t bytecount = 0;
|
||||
int fd;
|
||||
struct timeval now = Curl_tvnow();
|
||||
struct FILEPROTO *file;
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
|
||||
@@ -449,8 +438,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
if(data->set.upload)
|
||||
return file_upload(conn);
|
||||
|
||||
file = conn->data->req.protop;
|
||||
|
||||
/* 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 */
|
||||
if(-1 != fstat(fd, &statbuf)) {
|
||||
|
||||
145
lib/formdata.c
145
lib/formdata.c
@@ -24,9 +24,6 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
/* Length of the random boundary string. */
|
||||
#define BOUNDARY_LENGTH 40
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
|
||||
|
||||
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
|
||||
@@ -35,7 +32,7 @@
|
||||
|
||||
#include "urldata.h" /* for struct SessionHandle */
|
||||
#include "formdata.h"
|
||||
#include "curl_rand.h"
|
||||
#include "sslgen.h"
|
||||
#include "strequal.h"
|
||||
#include "curl_memory.h"
|
||||
#include "sendf.h"
|
||||
@@ -56,7 +53,7 @@ static char *Curl_basename(char *path);
|
||||
#endif
|
||||
|
||||
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
|
||||
extensions. */
|
||||
@@ -171,7 +168,7 @@ static FormInfo * AddFormInfo(char *value,
|
||||
* 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 *contenttype = NULL;
|
||||
@@ -181,7 +178,7 @@ static const char * ContentTypeForFilename (const char *filename,
|
||||
* extensions and pick the first we match!
|
||||
*/
|
||||
struct ContentType {
|
||||
char extension[6];
|
||||
const char *extension;
|
||||
const char *type;
|
||||
};
|
||||
static const struct ContentType ctts[]={
|
||||
@@ -429,7 +426,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
||||
|
||||
/* Get contents from a given file name */
|
||||
case CURLFORM_FILECONTENT:
|
||||
if(current_form->flags != 0)
|
||||
if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
|
||||
return_value = CURL_FORMADD_OPTION_TWICE;
|
||||
else {
|
||||
const char *filename = array_state?
|
||||
@@ -670,9 +667,11 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
||||
if(((form->flags & HTTPPOST_FILENAME) ||
|
||||
(form->flags & HTTPPOST_BUFFER)) &&
|
||||
!form->contenttype ) {
|
||||
char *f = form->flags & HTTPPOST_BUFFER?
|
||||
form->showfilename : form->value;
|
||||
|
||||
/* our contenttype is missing */
|
||||
form->contenttype
|
||||
= strdup(ContentTypeForFilename(form->value, prevtype));
|
||||
form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
|
||||
if(!form->contenttype) {
|
||||
return_value = CURL_FORMADD_MEMORY;
|
||||
break;
|
||||
@@ -777,6 +776,70 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
||||
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.
|
||||
*
|
||||
@@ -832,7 +895,7 @@ static CURLcode AddFormData(struct FormData **formp,
|
||||
if(!strequal("-", newform->line)) {
|
||||
struct_stat file;
|
||||
if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
|
||||
*size += file.st_size;
|
||||
*size += filesize(newform->line, file);
|
||||
else
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
@@ -1101,7 +1164,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
|
||||
if(!post)
|
||||
return result; /* no input => no output! */
|
||||
|
||||
boundary = formboundary();
|
||||
boundary = formboundary(data);
|
||||
if(!boundary)
|
||||
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 */
|
||||
|
||||
Curl_safefree(fileboundary);
|
||||
fileboundary = formboundary();
|
||||
fileboundary = formboundary(data);
|
||||
if(!fileboundary) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
@@ -1343,6 +1406,36 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata )
|
||||
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()
|
||||
*
|
||||
@@ -1365,7 +1458,7 @@ static size_t readfromfile(struct Form *form, char *buffer,
|
||||
else {
|
||||
if(!form->fp) {
|
||||
/* 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)
|
||||
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
|
||||
* one.
|
||||
*/
|
||||
static char *formboundary(void)
|
||||
static char *formboundary(struct SessionHandle *data)
|
||||
{
|
||||
char *retstring;
|
||||
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)
|
||||
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
|
||||
combinations */
|
||||
retstring[BOUNDARY_LENGTH]=0; /* zero terminate */
|
||||
|
||||
return retstring;
|
||||
return aprintf("------------------------%08x%08x",
|
||||
Curl_rand(data), Curl_rand(data));
|
||||
}
|
||||
|
||||
#else /* CURL_DISABLE_HTTP */
|
||||
|
||||
@@ -147,6 +147,12 @@ struct ftp_conn {
|
||||
curl_off_t known_filesize; /* file size is different from -1, if wildcard
|
||||
LIST parsing was done and wc_statemach set
|
||||
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 */
|
||||
|
||||
@@ -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
|
||||
* 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;
|
||||
|
||||
info->httpcode = 0;
|
||||
info->httpversion=0;
|
||||
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
|
||||
info->timecond=0;
|
||||
info->httpversion = 0;
|
||||
info->filetime = -1; /* -1 is an illegal time and thus means unknown */
|
||||
info->timecond = FALSE;
|
||||
|
||||
if(info->contenttype)
|
||||
free(info->contenttype);
|
||||
@@ -186,7 +186,7 @@ static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
|
||||
break;
|
||||
case CURLINFO_CONDITION_UNMET:
|
||||
/* return if the condition prevented the document to get transferred */
|
||||
*param_longp = data->info.timecond;
|
||||
*param_longp = data->info.timecond ? 1L : 0L;
|
||||
break;
|
||||
case CURLINFO_RTSP_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;
|
||||
*param_slistp = ptr.to_slist;
|
||||
break;
|
||||
case CURLINFO_TLS_SESSION:
|
||||
{
|
||||
struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
|
||||
param_slistp;
|
||||
struct curl_tlssessioninfo *tsi = &data->tsi;
|
||||
struct connectdata *conn = data->easy_conn;
|
||||
unsigned int sockindex = 0;
|
||||
|
||||
*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:
|
||||
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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -633,10 +633,8 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
else
|
||||
infof(data, "\t server certificate verification OK\n");
|
||||
}
|
||||
else {
|
||||
else
|
||||
infof(data, "\t server certificate verification SKIPPED\n");
|
||||
goto after_server_cert_verification;
|
||||
}
|
||||
|
||||
/* initialize an X.509 certificate structure. */
|
||||
gnutls_x509_crt_init(&x509_cert);
|
||||
@@ -766,8 +764,6 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
|
||||
after_server_cert_verification:
|
||||
|
||||
/* compression algorithm (if any) */
|
||||
ptr = gnutls_compression_get_name(gnutls_compression_get(session));
|
||||
/* 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
|
||||
* 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 */
|
||||
size_t md5len);
|
||||
|
||||
/* this backend provides these functions: */
|
||||
#define have_curlssl_random 1
|
||||
#define have_curlssl_md5sum 1
|
||||
|
||||
/* API setup for GnuTLS */
|
||||
#define curlssl_init Curl_gtls_init
|
||||
#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
|
||||
* 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)
|
||||
func(he->ptr);
|
||||
else
|
||||
fprintf(stderr, " [%p]", he->ptr);
|
||||
fprintf(stderr, " [%p]", (void *)he->ptr);
|
||||
|
||||
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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -22,8 +22,9 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_SSLEAY) || defined(USE_AXTLS)
|
||||
/* these two backends use functions from this file */
|
||||
#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \
|
||||
defined(USE_GSKIT) || defined(USE_NSS)
|
||||
/* these backends use functions from this file */
|
||||
|
||||
#include "hostcheck.h"
|
||||
#include "rawstr.h"
|
||||
@@ -93,4 +94,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
|
||||
if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
|
||||
/* cache forever means never prune, and NULL hostcache means
|
||||
we can't do it */
|
||||
if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache ||
|
||||
dns->inuse)
|
||||
/* 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;
|
||||
|
||||
time(&user.now);
|
||||
@@ -424,9 +429,13 @@ int Curl_resolv(struct connectdata *conn,
|
||||
/* free the allocated entry_id again */
|
||||
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 */
|
||||
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 */
|
||||
}
|
||||
|
||||
if(dns) {
|
||||
dns->inuse++; /* we use it! */
|
||||
@@ -681,12 +690,14 @@ clean_up:
|
||||
* Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
|
||||
* made, the struct may be destroyed due to pruning. It is important that only
|
||||
* one unlock is made for each Curl_resolv() call.
|
||||
*
|
||||
* May be called with 'data' == NULL for global cache.
|
||||
*/
|
||||
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
|
||||
{
|
||||
DEBUGASSERT(dns && (dns->inuse>0));
|
||||
|
||||
if(data->share)
|
||||
if(data && data->share)
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||
|
||||
dns->inuse--;
|
||||
@@ -697,7 +708,7 @@ void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
|
||||
free(dns);
|
||||
}
|
||||
|
||||
if(data->share)
|
||||
if(data && data->share)
|
||||
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 */
|
||||
}
|
||||
|
||||
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
|
||||
* still present in the cache with the inuse counter set to 1. Detect them
|
||||
* 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)
|
||||
{
|
||||
|
||||
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
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
void Curl_hostcache_clean(struct SessionHandle *data);
|
||||
void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash);
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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)
|
||||
else {
|
||||
struct addrinfo hints;
|
||||
char sbuf[NI_MAXSERV];
|
||||
char sbuf[12];
|
||||
char *sbufptr = NULL;
|
||||
|
||||
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
|
||||
* 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;
|
||||
Curl_addrinfo *res;
|
||||
int error;
|
||||
char sbuf[NI_MAXSERV];
|
||||
char sbuf[12];
|
||||
char *sbufptr = NULL;
|
||||
char addrbuf[128];
|
||||
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
|
||||
* 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 */
|
||||
|
||||
169
lib/http.c
169
lib/http.c
@@ -75,6 +75,7 @@
|
||||
#include "non-ascii.h"
|
||||
#include "bundles.h"
|
||||
#include "pipeline.h"
|
||||
#include "http2.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -105,7 +106,7 @@ static int https_getsock(struct connectdata *conn,
|
||||
*/
|
||||
const struct Curl_handler Curl_handler_http = {
|
||||
"HTTP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -129,7 +130,7 @@ const struct Curl_handler Curl_handler_http = {
|
||||
*/
|
||||
const struct Curl_handler Curl_handler_https = {
|
||||
"HTTPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -149,6 +150,19 @@ const struct Curl_handler Curl_handler_https = {
|
||||
#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
|
||||
* 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
|
||||
* 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 *end;
|
||||
char *value;
|
||||
size_t len;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(header);
|
||||
|
||||
/* Find the end of the header name */
|
||||
while(*h && (*h != ':'))
|
||||
++h;
|
||||
while(*header && (*header != ':'))
|
||||
++header;
|
||||
|
||||
if(*h)
|
||||
if(*header)
|
||||
/* Skip over colon */
|
||||
++h;
|
||||
++header;
|
||||
|
||||
/* Find the first non-space letter */
|
||||
start = h;
|
||||
start = header;
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
|
||||
@@ -210,7 +224,7 @@ static char *copy_header_value(const char *h)
|
||||
end--;
|
||||
|
||||
/* get length of the type */
|
||||
len = end-start+1;
|
||||
len = end - start + 1;
|
||||
|
||||
value = malloc(len + 1);
|
||||
if(!value)
|
||||
@@ -330,7 +344,7 @@ static bool pickoneauth(struct auth *pick)
|
||||
static CURLcode http_perhapsrewind(struct connectdata *conn)
|
||||
{
|
||||
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 expectsend = -1; /* default is unknown */
|
||||
|
||||
@@ -685,9 +699,8 @@ Curl_http_output_auth(struct connectdata *conn,
|
||||
* proxy CONNECT loop.
|
||||
*/
|
||||
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
int httpcode,
|
||||
const char *header) /* the first non-space */
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
||||
const char *auth) /* the first non-space */
|
||||
{
|
||||
/*
|
||||
* This resource requires authentication
|
||||
@@ -695,24 +708,17 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
unsigned long *availp;
|
||||
const char *start;
|
||||
struct auth *authp;
|
||||
|
||||
if(httpcode == 407) {
|
||||
start = header+strlen("Proxy-authenticate:");
|
||||
if(proxy) {
|
||||
availp = &data->info.proxyauthavail;
|
||||
authp = &data->state.authproxy;
|
||||
}
|
||||
else {
|
||||
start = header+strlen("WWW-Authenticate:");
|
||||
availp = &data->info.httpauthavail;
|
||||
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
|
||||
* 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
|
||||
if(checkprefix("GSS-Negotiate", start) ||
|
||||
checkprefix("Negotiate", start)) {
|
||||
if(checkprefix("GSS-Negotiate", auth) ||
|
||||
checkprefix("Negotiate", auth)) {
|
||||
int neg;
|
||||
*availp |= CURLAUTH_GSSNEGOTIATE;
|
||||
authp->avail |= CURLAUTH_GSSNEGOTIATE;
|
||||
@@ -746,7 +752,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
data->state.authproblem = TRUE;
|
||||
}
|
||||
else {
|
||||
neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
|
||||
neg = Curl_input_negotiate(conn, proxy, auth);
|
||||
if(neg == 0) {
|
||||
DEBUGASSERT(!data->req.newurl);
|
||||
data->req.newurl = strdup(data->change.url);
|
||||
@@ -765,14 +771,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
#endif
|
||||
#ifdef USE_NTLM
|
||||
/* NTLM support requires the SSL crypto libs */
|
||||
if(checkprefix("NTLM", start)) {
|
||||
if(checkprefix("NTLM", auth)) {
|
||||
*availp |= CURLAUTH_NTLM;
|
||||
authp->avail |= CURLAUTH_NTLM;
|
||||
if(authp->picked == CURLAUTH_NTLM ||
|
||||
authp->picked == CURLAUTH_NTLM_WB) {
|
||||
/* NTLM authentication is picked and activated */
|
||||
CURLcode ntlm =
|
||||
Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start);
|
||||
Curl_input_ntlm(conn, proxy, auth);
|
||||
if(CURLE_OK == ntlm) {
|
||||
data->state.authproblem = FALSE;
|
||||
#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
|
||||
* ntlm_auth for generating the type 3 message later */
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
if(checkprefix("NTLM", start)) {
|
||||
start += strlen("NTLM");
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
if(*start)
|
||||
if((conn->challenge_header = strdup(start)) == NULL)
|
||||
while(*auth && ISSPACE(*auth))
|
||||
auth++;
|
||||
if(checkprefix("NTLM", auth)) {
|
||||
auth += strlen("NTLM");
|
||||
while(*auth && ISSPACE(*auth))
|
||||
auth++;
|
||||
if(*auth)
|
||||
if((conn->challenge_header = strdup(auth)) == NULL)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -806,7 +812,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if(checkprefix("Digest", start)) {
|
||||
if(checkprefix("Digest", auth)) {
|
||||
if((authp->avail & CURLAUTH_DIGEST) != 0) {
|
||||
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
|
||||
* incoming data from this header in case we are gonna use
|
||||
* Digest. */
|
||||
dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start);
|
||||
dig = Curl_input_digest(conn, proxy, auth);
|
||||
|
||||
if(CURLDIGEST_FINE != dig) {
|
||||
infof(data, "Authentication problem. Ignoring this.\n");
|
||||
@@ -829,7 +835,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(checkprefix("Basic", start)) {
|
||||
if(checkprefix("Basic", auth)) {
|
||||
*availp |= CURLAUTH_BASIC;
|
||||
authp->avail |= 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 */
|
||||
while(*start && *start != ',') /* read up to the next comma */
|
||||
start++;
|
||||
if(*start == ',') /* if we're on a comma, skip it */
|
||||
start++;
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
while(*auth && *auth != ',') /* read up to the next comma */
|
||||
auth++;
|
||||
if(*auth == ',') /* if we're on a comma, skip it */
|
||||
auth++;
|
||||
while(*auth && ISSPACE(*auth))
|
||||
auth++;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -948,7 +954,7 @@ static size_t readmoredata(char *buffer,
|
||||
void *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;
|
||||
|
||||
if(0 == http->postsize)
|
||||
@@ -1019,7 +1025,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
CURLcode res;
|
||||
char *ptr;
|
||||
size_t size;
|
||||
struct HTTP *http = conn->data->state.proto.http;
|
||||
struct HTTP *http = conn->data->req.protop;
|
||||
size_t sendsize;
|
||||
curl_socket_t sockfd;
|
||||
size_t headersize;
|
||||
@@ -1402,7 +1408,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
CURLcode status, bool premature)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct HTTP *http =data->state.proto.http;
|
||||
struct HTTP *http =data->req.protop;
|
||||
|
||||
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
|
||||
entire operation is complete */
|
||||
!conn->bits.retry &&
|
||||
!data->set.connect_only &&
|
||||
((http->readbytecount +
|
||||
data->req.headerbytecount -
|
||||
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
|
||||
connected to only supports 1.0, or if any server previously contacted to
|
||||
handle this request only supports 1.0. */
|
||||
static bool use_http_1_1(const struct SessionHandle *data,
|
||||
/*
|
||||
* Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
|
||||
* to avoid it include:
|
||||
*
|
||||
* - if the user specifically requested HTTP 1.0
|
||||
* - if the server we are connected to only supports 1.0
|
||||
* - if any server previously contacted to handle this request only supports
|
||||
* 1.0.
|
||||
*/
|
||||
static bool use_http_1_1plus(const struct SessionHandle *data,
|
||||
const struct connectdata *conn)
|
||||
{
|
||||
return ((data->set.httpversion == CURL_HTTP_VERSION_1_1) ||
|
||||
return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
|
||||
((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
|
||||
((conn->httpversion == 11) ||
|
||||
((conn->httpversion != 10) &&
|
||||
@@ -1479,7 +1491,7 @@ static CURLcode expect100(struct SessionHandle *data,
|
||||
const char *ptr;
|
||||
data->state.expect100header = FALSE; /* default to false unless it is set
|
||||
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:
|
||||
100-continue to the headers which actually speeds up post operations
|
||||
(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. */
|
||||
*done = TRUE;
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
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;
|
||||
http = data->req.protop;
|
||||
|
||||
if(!data->state.this_is_a_follow) {
|
||||
/* 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)
|
||||
/* 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 */
|
||||
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
|
||||
redirected request is being out on thin ice. Except if the host name
|
||||
is the same as the first one! */
|
||||
char *cookiehost = copy_header_value(ptr);
|
||||
char *cookiehost = Curl_copy_header_value(ptr);
|
||||
if(!cookiehost)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
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
|
||||
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 */
|
||||
req_buffer = Curl_add_buffer_init();
|
||||
@@ -2173,6 +2172,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
if(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(data->cookies || addcookies) {
|
||||
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 */
|
||||
else if(checkprefix("Content-Type:", k->p)) {
|
||||
char *contenttype = copy_header_value(k->p);
|
||||
char *contenttype = Curl_copy_header_value(k->p);
|
||||
if(!contenttype)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!*contenttype)
|
||||
@@ -3243,7 +3251,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
}
|
||||
}
|
||||
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 */
|
||||
if(conn->bundle && conn->bundle->server_supports_pipelining) {
|
||||
@@ -3439,7 +3447,16 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
(401 == k->httpcode)) ||
|
||||
(checkprefix("Proxy-authenticate:", k->p) &&
|
||||
(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)
|
||||
return result;
|
||||
}
|
||||
@@ -3447,7 +3464,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
checkprefix("Location:", k->p) &&
|
||||
!data->req.location) {
|
||||
/* 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)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -21,19 +21,26 @@
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#endif
|
||||
|
||||
extern const struct Curl_handler Curl_handler_http;
|
||||
|
||||
#ifdef USE_SSL
|
||||
extern const struct Curl_handler Curl_handler_https;
|
||||
#endif
|
||||
|
||||
/* Header specific functions */
|
||||
bool Curl_compareheader(const char *headerline, /* line to check */
|
||||
const char *header, /* header keyword _with_ colon */
|
||||
const char *content); /* content string to find */
|
||||
|
||||
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_done(struct connectdata *, CURLcode, bool premature);
|
||||
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 */
|
||||
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 */
|
||||
void Curl_http_auth_stage(struct SessionHandle *data, int stage);
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
int httpcode, const char *header);
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
||||
const char *auth);
|
||||
CURLcode Curl_http_auth_act(struct connectdata *conn);
|
||||
CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
|
||||
|
||||
@@ -141,6 +149,14 @@ struct HTTP {
|
||||
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,
|
||||
struct connectdata *conn,
|
||||
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 ___| | | | _ \| |
|
||||
@@ -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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -22,40 +24,19 @@
|
||||
|
||||
#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 */
|
||||
#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();
|
||||
}
|
||||
#endif /* HEADER_CURL_HTTP2_H */
|
||||
|
||||
@@ -25,14 +25,13 @@
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "rawstr.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_md5.h"
|
||||
#include "http_digest.h"
|
||||
#include "strtok.h"
|
||||
#include "url.h" /* for Curl_safefree() */
|
||||
#include "curl_memory.h"
|
||||
#include "sslgen.h" /* for Curl_rand() */
|
||||
#include "non-ascii.h" /* included for Curl_convert_... prototypes */
|
||||
#include "warnless.h"
|
||||
|
||||
@@ -142,10 +141,6 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
||||
d = &data->state.digest;
|
||||
}
|
||||
|
||||
/* skip initial whitespaces */
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
if(checkprefix("Digest", header)) {
|
||||
header += strlen("Digest");
|
||||
|
||||
@@ -283,7 +278,7 @@ static char *string_quoted(const char *source)
|
||||
++s;
|
||||
}
|
||||
|
||||
dest = (char *)malloc(n);
|
||||
dest = malloc(n);
|
||||
if(dest) {
|
||||
s = source;
|
||||
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
|
||||
this sorted out, I must urge you dear friend to read up on the RFC2617
|
||||
section 3.2.2, */
|
||||
size_t urilen;
|
||||
unsigned char md5buf[16]; /* 16 bytes/128 bits */
|
||||
unsigned char request_digest[33];
|
||||
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 */
|
||||
char cnoncebuf[33];
|
||||
char *cnonce = NULL;
|
||||
size_t cnonce_sz = 0;
|
||||
char *tmp = NULL;
|
||||
struct timeval now;
|
||||
|
||||
char **allocuserpwd;
|
||||
size_t userlen;
|
||||
const char *userp;
|
||||
@@ -354,10 +348,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
authp = &data->state.authhost;
|
||||
}
|
||||
|
||||
if(*allocuserpwd) {
|
||||
Curl_safefree(*allocuserpwd);
|
||||
*allocuserpwd = NULL;
|
||||
}
|
||||
|
||||
/* not set means empty */
|
||||
if(!userp)
|
||||
@@ -376,10 +367,11 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
d->nc = 1;
|
||||
|
||||
if(!d->cnonce) {
|
||||
/* Generate a cnonce */
|
||||
now = Curl_tvnow();
|
||||
snprintf(cnoncebuf, sizeof(cnoncebuf), "%32ld",
|
||||
(long)now.tv_sec + now.tv_usec);
|
||||
struct timeval now = Curl_tvnow();
|
||||
snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
|
||||
Curl_rand(data), Curl_rand(data),
|
||||
(unsigned int)now.tv_sec,
|
||||
(unsigned int)now.tv_usec);
|
||||
|
||||
rc = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
|
||||
&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_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
|
||||
ha1 = malloc(33); /* 32 digits and 1 zero byte */
|
||||
if(!ha1)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_safefree(md5this);
|
||||
md5_to_ascii(md5buf, ha1);
|
||||
|
||||
if(d->algo == CURLDIGESTALGO_MD5SESS) {
|
||||
@@ -421,7 +408,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, (unsigned char *)tmp);
|
||||
free(tmp); /* free this again */
|
||||
Curl_safefree(tmp);
|
||||
md5_to_ascii(md5buf, ha1);
|
||||
}
|
||||
|
||||
@@ -450,31 +437,29 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
Further details on Digest implementation differences:
|
||||
http://www.fngtps.com/2006/09/http-authentication
|
||||
*/
|
||||
if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
|
||||
md5this = (unsigned char *)aprintf("%s:%.*s", request,
|
||||
curlx_sztosi(tmp - (char *)uripath),
|
||||
uripath);
|
||||
}
|
||||
|
||||
if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL))
|
||||
urilen = tmp - (char *)uripath;
|
||||
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")) {
|
||||
/* We don't support auth-int for PUT or POST at the moment.
|
||||
TODO: replace md5 of empty string with entity-body for PUT/POST */
|
||||
unsigned char *md5this2 = (unsigned char *)
|
||||
aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e");
|
||||
free(md5this);
|
||||
Curl_safefree(md5this);
|
||||
md5this = md5this2;
|
||||
}
|
||||
|
||||
if(!md5this) {
|
||||
free(ha1);
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
Curl_safefree(md5this);
|
||||
md5_to_ascii(md5buf, ha2);
|
||||
|
||||
if(d->qop) {
|
||||
@@ -492,13 +477,12 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
d->nonce,
|
||||
ha2);
|
||||
}
|
||||
free(ha1);
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
Curl_safefree(md5this);
|
||||
md5_to_ascii(md5buf, request_digest);
|
||||
|
||||
/* for test case 64 (snooped from a Mozilla 1.3a request)
|
||||
@@ -515,7 +499,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
chracters.
|
||||
*/
|
||||
userp_quoted = string_quoted(userp);
|
||||
if(!*userp_quoted)
|
||||
if(!userp_quoted)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(d->qop) {
|
||||
@@ -524,7 +508,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
"username=\"%s\", "
|
||||
"realm=\"%s\", "
|
||||
"nonce=\"%s\", "
|
||||
"uri=\"%s\", "
|
||||
"uri=\"%.*s\", "
|
||||
"cnonce=\"%s\", "
|
||||
"nc=%08x, "
|
||||
"qop=%s, "
|
||||
@@ -533,7 +517,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
userp_quoted,
|
||||
d->realm,
|
||||
d->nonce,
|
||||
uripath, /* this is the PATH part of the URL */
|
||||
urilen, uripath, /* this is the PATH part of the URL */
|
||||
d->cnonce,
|
||||
d->nc,
|
||||
d->qop,
|
||||
@@ -550,16 +534,16 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
"username=\"%s\", "
|
||||
"realm=\"%s\", "
|
||||
"nonce=\"%s\", "
|
||||
"uri=\"%s\", "
|
||||
"uri=\"%.*s\", "
|
||||
"response=\"%s\"",
|
||||
proxy?"Proxy-":"",
|
||||
userp_quoted,
|
||||
d->realm,
|
||||
d->nonce,
|
||||
uripath, /* this is the PATH part of the URL */
|
||||
urilen, uripath, /* this is the PATH part of the URL */
|
||||
request_digest);
|
||||
}
|
||||
free(userp_quoted);
|
||||
Curl_safefree(userp_quoted);
|
||||
if(!*allocuserpwd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@@ -595,29 +579,12 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
|
||||
static void digest_cleanup_one(struct digestdata *d)
|
||||
{
|
||||
if(d->nonce)
|
||||
free(d->nonce);
|
||||
d->nonce = NULL;
|
||||
|
||||
if(d->cnonce)
|
||||
free(d->cnonce);
|
||||
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;
|
||||
Curl_safefree(d->nonce);
|
||||
Curl_safefree(d->cnonce);
|
||||
Curl_safefree(d->realm);
|
||||
Curl_safefree(d->opaque);
|
||||
Curl_safefree(d->qop);
|
||||
Curl_safefree(d->algorithm);
|
||||
|
||||
d->nc = 0;
|
||||
d->algo = CURLDIGESTALGO_MD5; /* default algorithm */
|
||||
|
||||
@@ -145,8 +145,6 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||
const char* protocol;
|
||||
CURLcode error;
|
||||
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
if(checkprefix("GSS-Negotiate", header)) {
|
||||
protocol = "GSS-Negotiate";
|
||||
gss = TRUE;
|
||||
|
||||
@@ -98,9 +98,6 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||
const char* protocol;
|
||||
CURLcode error;
|
||||
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
if(checkprefix("GSS-Negotiate", header)) {
|
||||
protocol = "GSS-Negotiate";
|
||||
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
|
||||
* 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));
|
||||
conn->data->state.proto.http = &http_proxy;
|
||||
conn->data->req.protop = &http_proxy;
|
||||
conn->bits.close = FALSE;
|
||||
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
|
||||
conn->host.name, conn->remote_port);
|
||||
conn->data->state.proto.generic = prot_save;
|
||||
conn->data->req.protop = prot_save;
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
#else
|
||||
@@ -452,8 +452,16 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
(401 == k->httpcode)) ||
|
||||
(checkprefix("Proxy-authenticate:", line_start) &&
|
||||
(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)
|
||||
return result;
|
||||
}
|
||||
|
||||
426
lib/imap.c
426
lib/imap.c
@@ -26,6 +26,8 @@
|
||||
* RFC4616 PLAIN authentication
|
||||
* RFC4959 IMAP Extension for SASL Initial Client Response
|
||||
* 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 "rawstr.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "warnless.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -162,7 +165,7 @@ const struct Curl_handler Curl_handler_imaps = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_imap_proxy = {
|
||||
"IMAP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
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 = {
|
||||
"IMAPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
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,
|
||||
int *resp)
|
||||
{
|
||||
struct IMAP *imap = conn->data->state.proto.imap;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
const char *id = imapc->resptag;
|
||||
size_t id_len = strlen(id);
|
||||
@@ -306,7 +309,12 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
(strcmp(imap->custom, "STORE") ||
|
||||
!imap_matchresp(line, len, "FETCH")) &&
|
||||
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;
|
||||
break;
|
||||
|
||||
@@ -329,7 +337,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
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)) ||
|
||||
(len >= 2 && !memcmp("+ ", line, 2))) {
|
||||
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_NTLM:
|
||||
case IMAP_AUTHENTICATE_NTLM_TYPE2MSG:
|
||||
case IMAP_AUTHENTICATE_XOAUTH2:
|
||||
case IMAP_AUTHENTICATE_FINAL:
|
||||
case IMAP_APPEND:
|
||||
*resp = '+';
|
||||
@@ -359,6 +371,35 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
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()
|
||||
@@ -384,6 +425,8 @@ static void state(struct connectdata *conn, imapstate newstate)
|
||||
"AUTHENTICATE_DIGESTMD5_RESP",
|
||||
"AUTHENTICATE_NTLM",
|
||||
"AUTHENTICATE_NTLM_TYPE2MSG",
|
||||
"AUTHENTICATE_XOAUTH2",
|
||||
"AUTHENTICATE_CANCEL",
|
||||
"AUTHENTICATE_FINAL",
|
||||
"LOGIN",
|
||||
"LIST",
|
||||
@@ -398,7 +441,7 @@ static void state(struct connectdata *conn, imapstate newstate)
|
||||
|
||||
if(imapc->state != newstate)
|
||||
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
|
||||
|
||||
imapc->state = newstate;
|
||||
@@ -541,18 +584,18 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Calculate the supported authentication mechanism by decreasing order of
|
||||
security */
|
||||
/* Calculate the supported authentication mechanism, by decreasing order of
|
||||
security, as well as the initial response where appropriate */
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if((imapc->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||
(imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||
mech = "DIGEST-MD5";
|
||||
mech = SASL_MECH_STRING_DIGEST_MD5;
|
||||
state1 = IMAP_AUTHENTICATE_DIGESTMD5;
|
||||
imapc->authused = SASL_MECH_DIGEST_MD5;
|
||||
}
|
||||
else if((imapc->authmechs & SASL_MECH_CRAM_MD5) &&
|
||||
(imapc->prefmech & SASL_MECH_CRAM_MD5)) {
|
||||
mech = "CRAM-MD5";
|
||||
mech = SASL_MECH_STRING_CRAM_MD5;
|
||||
state1 = IMAP_AUTHENTICATE_CRAMMD5;
|
||||
imapc->authused = SASL_MECH_CRAM_MD5;
|
||||
}
|
||||
@@ -561,7 +604,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
#ifdef USE_NTLM
|
||||
if((imapc->authmechs & SASL_MECH_NTLM) &&
|
||||
(imapc->prefmech & SASL_MECH_NTLM)) {
|
||||
mech = "NTLM";
|
||||
mech = SASL_MECH_STRING_NTLM;
|
||||
state1 = IMAP_AUTHENTICATE_NTLM;
|
||||
state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG;
|
||||
imapc->authused = SASL_MECH_NTLM;
|
||||
@@ -573,9 +616,22 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
else
|
||||
#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)) {
|
||||
mech = "LOGIN";
|
||||
mech = SASL_MECH_STRING_LOGIN;
|
||||
state1 = IMAP_AUTHENTICATE_LOGIN;
|
||||
state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD;
|
||||
imapc->authused = SASL_MECH_LOGIN;
|
||||
@@ -586,7 +642,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
else if((imapc->authmechs & SASL_MECH_PLAIN) &&
|
||||
(imapc->prefmech & SASL_MECH_PLAIN)) {
|
||||
mech = "PLAIN";
|
||||
mech = SASL_MECH_STRING_PLAIN;
|
||||
state1 = IMAP_AUTHENTICATE_PLAIN;
|
||||
state2 = IMAP_AUTHENTICATE_FINAL;
|
||||
imapc->authused = SASL_MECH_PLAIN;
|
||||
@@ -597,7 +653,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
if(mech) {
|
||||
if(mech && (imapc->preftype & IMAP_TYPE_SASL)) {
|
||||
/* Perform SASL based authentication */
|
||||
if(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);
|
||||
}
|
||||
else if(!imapc->login_disabled)
|
||||
else if((!imapc->login_disabled) &&
|
||||
(imapc->preftype & IMAP_TYPE_CLEARTEXT))
|
||||
/* Perform clear text authentication */
|
||||
result = imap_perform_login(conn);
|
||||
else {
|
||||
@@ -637,7 +694,7 @@ static CURLcode imap_perform_list(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
char *mailbox;
|
||||
|
||||
if(imap->custom)
|
||||
@@ -672,7 +729,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
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;
|
||||
char *mailbox;
|
||||
|
||||
@@ -711,7 +768,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
|
||||
static CURLcode imap_perform_fetch(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct IMAP *imap = conn->data->state.proto.imap;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
|
||||
/* Check we have a UID */
|
||||
if(!imap->uid) {
|
||||
@@ -739,7 +796,7 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
|
||||
static CURLcode imap_perform_append(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct IMAP *imap = conn->data->state.proto.imap;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
char *mailbox;
|
||||
|
||||
/* Check we have a mailbox */
|
||||
@@ -863,20 +920,22 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
|
||||
wordlen -= 5;
|
||||
|
||||
/* 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;
|
||||
if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_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;
|
||||
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;
|
||||
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_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;
|
||||
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
|
||||
imapc->authmechs |= SASL_MECH_NTLM;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
|
||||
imapc->authmechs |= SASL_MECH_XOAUTH2;
|
||||
}
|
||||
|
||||
line += wordlen;
|
||||
@@ -949,19 +1008,16 @@ static CURLcode imap_state_auth_plain_resp(struct connectdata *conn,
|
||||
/* Create the authorisation message */
|
||||
result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
|
||||
&plainauth, &len);
|
||||
|
||||
if(!result && plainauth) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(plainauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(plainauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -986,19 +1042,16 @@ static CURLcode imap_state_auth_login_resp(struct connectdata *conn,
|
||||
/* Create the user message */
|
||||
result = Curl_sasl_create_login_message(data, conn->user,
|
||||
&authuser, &len);
|
||||
|
||||
if(!result && authuser) {
|
||||
/* Send the user */
|
||||
if(!result) {
|
||||
if(authuser) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authuser);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_LOGIN_PASSWD);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(authuser);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1023,19 +1076,16 @@ static CURLcode imap_state_auth_login_password_resp(struct connectdata *conn,
|
||||
/* Create the password message */
|
||||
result = Curl_sasl_create_login_message(data, conn->passwd,
|
||||
&authpasswd, &len);
|
||||
|
||||
if(!result && authpasswd) {
|
||||
/* Send the password */
|
||||
if(!result) {
|
||||
if(authpasswd) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authpasswd);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(authpasswd);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1048,9 +1098,10 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *chlg64 = data->state.buffer;
|
||||
size_t len = 0;
|
||||
char *chlg = NULL;
|
||||
char *chlg64 = NULL;
|
||||
char *rplyb64 = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
(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;
|
||||
}
|
||||
|
||||
/* Get the challenge */
|
||||
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
|
||||
;
|
||||
/* Get the challenge message */
|
||||
imap_get_message(data->state.buffer, &chlg64);
|
||||
|
||||
/* Terminate the challenge */
|
||||
if(*chlg64 != '=') {
|
||||
for(len = strlen(chlg64); len--;)
|
||||
if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' &&
|
||||
chlg64[len] != '\t')
|
||||
break;
|
||||
/* Decode the challenge message */
|
||||
result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
|
||||
if(result) {
|
||||
/* Send the cancellation */
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
|
||||
|
||||
if(++len) {
|
||||
chlg64[len] = '\0';
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_CANCEL);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* 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);
|
||||
|
||||
if(!result && rplyb64) {
|
||||
/* Send the response */
|
||||
if(!result) {
|
||||
if(rplyb64) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
|
||||
Curl_safefree(rplyb64);
|
||||
}
|
||||
|
||||
Curl_safefree(chlg);
|
||||
Curl_safefree(rplyb64);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1101,9 +1148,13 @@ static CURLcode imap_state_auth_digest_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *chlg64 = data->state.buffer;
|
||||
size_t len = 0;
|
||||
char *chlg64 = NULL;
|
||||
char *rplyb64 = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
char nonce[64];
|
||||
char realm[128];
|
||||
char algorithm[64];
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@@ -1112,26 +1163,35 @@ static CURLcode imap_state_auth_digest_resp(struct connectdata *conn,
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
/* Get the challenge */
|
||||
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
|
||||
;
|
||||
/* Get the challenge message */
|
||||
imap_get_message(data->state.buffer, &chlg64);
|
||||
|
||||
/* Decode the challange message */
|
||||
result = Curl_sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
|
||||
realm, sizeof(realm),
|
||||
algorithm, sizeof(algorithm));
|
||||
if(result || strcmp(algorithm, "md5-sess") != 0) {
|
||||
/* Send the cancellation */
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_CANCEL);
|
||||
}
|
||||
else {
|
||||
/* Create the response message */
|
||||
result = Curl_sasl_create_digest_md5_message(data, chlg64, conn->user,
|
||||
conn->passwd, "imap",
|
||||
&rplyb64, &len);
|
||||
|
||||
result = Curl_sasl_create_digest_md5_message(data, nonce, realm,
|
||||
conn->user, conn->passwd,
|
||||
"imap", &rplyb64, &len);
|
||||
if(!result && rplyb64) {
|
||||
/* Send the response */
|
||||
if(!result) {
|
||||
if(rplyb64) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_DIGESTMD5_RESP);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(rplyb64);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1152,7 +1212,7 @@ static CURLcode imap_state_auth_digest_resp_resp(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* Send an empty response */
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "");
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "");
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
@@ -1184,19 +1244,16 @@ static CURLcode imap_state_auth_ntlm_resp(struct connectdata *conn,
|
||||
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
||||
&conn->ntlm,
|
||||
&type1msg, &len);
|
||||
|
||||
if(!result && type1msg) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(type1msg) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type1msg);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_NTLM_TYPE2MSG);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(type1msg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1208,8 +1265,9 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
size_t len = 0;
|
||||
char *type2msg = NULL;
|
||||
char *type3msg = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
(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;
|
||||
}
|
||||
else {
|
||||
/* Create the type-3 message */
|
||||
result = Curl_sasl_create_ntlm_type3_message(data,
|
||||
data->state.buffer + 2,
|
||||
conn->user, conn->passwd,
|
||||
&conn->ntlm,
|
||||
&type3msg, &len);
|
||||
/* Get the challenge message */
|
||||
imap_get_message(data->state.buffer, &type2msg);
|
||||
|
||||
/* Decode the type-2 message */
|
||||
result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
|
||||
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 */
|
||||
if(!result) {
|
||||
if(type3msg) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type3msg);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(type3msg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#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,
|
||||
int imapcode,
|
||||
imapstate instate)
|
||||
@@ -1315,7 +1432,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
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;
|
||||
const char *line = data->state.buffer;
|
||||
char tmp[20];
|
||||
@@ -1406,10 +1523,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
|
||||
return result;
|
||||
|
||||
data->req.bytecount += chunk;
|
||||
size -= chunk;
|
||||
|
||||
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?*/
|
||||
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! */
|
||||
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||
else {
|
||||
@@ -1591,6 +1708,14 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
|
||||
break;
|
||||
#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:
|
||||
result = imap_state_auth_final_resp(conn, imapcode, imapc->state);
|
||||
break;
|
||||
@@ -1641,11 +1766,13 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
|
||||
CURLcode result = CURLE_OK;
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone)
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
|
||||
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
|
||||
else
|
||||
result = Curl_pp_statemach(&imapc->pp, FALSE);
|
||||
if(result || !imapc->ssldone)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Curl_pp_statemach(&imapc->pp, FALSE);
|
||||
*done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
|
||||
|
||||
return result;
|
||||
@@ -1668,13 +1795,11 @@ static CURLcode imap_init(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap;
|
||||
|
||||
if(!imap) {
|
||||
imap = data->state.proto.imap = calloc(sizeof(struct IMAP), 1);
|
||||
imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
|
||||
if(!imap)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1694,8 +1819,7 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
* connection phase.
|
||||
*
|
||||
* The variable 'done' points to will be TRUE if the protocol-layer connect
|
||||
* phase is done when this function returns, or FALSE is not. When called as
|
||||
* a part of the easy interface, it will always be TRUE.
|
||||
* phase is done when this function returns, or FALSE if not.
|
||||
*/
|
||||
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 */
|
||||
|
||||
/* 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 */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
@@ -1723,7 +1838,8 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
|
||||
pp->endofresp = imap_endofresp;
|
||||
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;
|
||||
|
||||
/* Initialise the pingpong layer */
|
||||
@@ -1759,7 +1875,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
|
||||
(void)premature;
|
||||
|
||||
@@ -1781,7 +1897,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
state(conn, IMAP_FETCH_FINAL);
|
||||
else {
|
||||
/* 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)
|
||||
state(conn, IMAP_APPEND_FINAL);
|
||||
}
|
||||
@@ -1824,7 +1940,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
|
||||
/* This is IMAP and no proxy */
|
||||
CURLcode result = CURLE_OK;
|
||||
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;
|
||||
bool selected = FALSE;
|
||||
|
||||
@@ -1891,15 +2007,6 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
|
||||
|
||||
*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 */
|
||||
result = imap_parse_url_path(conn);
|
||||
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
|
||||
point! */
|
||||
if(!dead_connection && imapc->pp.conn)
|
||||
if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
|
||||
if(!imap_perform_logout(conn))
|
||||
(void)imap_block_statemach(conn); /* ignore errors on LOGOUT */
|
||||
|
||||
@@ -1952,7 +2059,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
/* Call this when the DO phase has completed */
|
||||
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;
|
||||
|
||||
@@ -2018,6 +2125,11 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
/* Initialise the IMAP layer */
|
||||
CURLcode result = imap_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
|
||||
/* Unless we have asked to tunnel IMAP operations through the proxy, we
|
||||
switch and use HTTP operations only */
|
||||
@@ -2033,10 +2145,8 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* We explicitly mark this connection as persistent here as we're doing
|
||||
IMAP over HTTP and thus we accidentally avoid setting this value
|
||||
otherwise */
|
||||
conn->bits.close = FALSE;
|
||||
/* set it up as an HTTP connection instead */
|
||||
return conn->handler->setup_connection(conn);
|
||||
#else
|
||||
failf(data, "IMAP over http proxy requires HTTP support built-in!");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
@@ -2062,14 +2172,15 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
char *taggedfmt;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
DEBUGASSERT(fmt);
|
||||
|
||||
/* Calculate the next command ID wrapping at 3 digits */
|
||||
imapc->cmdid = (imapc->cmdid + 1) % 1000;
|
||||
|
||||
/* Calculate the tag based on the connection ID and command ID */
|
||||
snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
|
||||
'A' + (conn->connection_id % 26), imapc->cmdid);
|
||||
'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
|
||||
|
||||
/* Prefix the format with the tag */
|
||||
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;
|
||||
|
||||
/* Send the data with the tag */
|
||||
va_start(ap, fmt);
|
||||
result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
Curl_safefree(taggedfmt);
|
||||
va_end(ap);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -2221,23 +2333,43 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
|
||||
if(strnequal(key, "AUTH", 4)) {
|
||||
const char *value = ptr + 1;
|
||||
|
||||
if(strequal(value, "*"))
|
||||
if(strequal(value, "*")) {
|
||||
imapc->preftype = IMAP_TYPE_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;
|
||||
else if(strequal(value, "PLAIN"))
|
||||
}
|
||||
else if(strequal(value, SASL_MECH_STRING_PLAIN)) {
|
||||
imapc->preftype = IMAP_TYPE_SASL;
|
||||
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;
|
||||
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;
|
||||
else if(strequal(value, "GSSAPI"))
|
||||
}
|
||||
else if(strequal(value, SASL_MECH_STRING_GSSAPI)) {
|
||||
imapc->preftype = IMAP_TYPE_SASL;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
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() */
|
||||
CURLcode result = CURLE_OK;
|
||||
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 *ptr = begin;
|
||||
|
||||
@@ -2365,7 +2497,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
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];
|
||||
|
||||
if(custom) {
|
||||
|
||||
11
lib/imap.h
11
lib/imap.h
@@ -43,6 +43,8 @@ typedef enum {
|
||||
IMAP_AUTHENTICATE_DIGESTMD5_RESP,
|
||||
IMAP_AUTHENTICATE_NTLM,
|
||||
IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
|
||||
IMAP_AUTHENTICATE_XOAUTH2,
|
||||
IMAP_AUTHENTICATE_CANCEL,
|
||||
IMAP_AUTHENTICATE_FINAL,
|
||||
IMAP_LOGIN,
|
||||
IMAP_LIST,
|
||||
@@ -76,6 +78,7 @@ struct imap_conn {
|
||||
imapstate state; /* Always use imap.c:state() to change state! */
|
||||
bool ssldone; /* Is connect() over SSL done? */
|
||||
unsigned int authmechs; /* Accepted authentication mechanisms */
|
||||
unsigned int preftype; /* Preferred authentication type */
|
||||
unsigned int prefmech; /* Preferred authentication mechanism */
|
||||
unsigned int authused; /* Auth mechanism used for the connection */
|
||||
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_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 */
|
||||
|
||||
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
|
||||
*
|
||||
* 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).
|
||||
* Copyright (c) 2004 - 2012 Daniel Stenberg
|
||||
* All rights reserved.
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "ftp.h"
|
||||
#include "curl_gssapi.h"
|
||||
#include "sendf.h"
|
||||
#include "krb4.h"
|
||||
#include "curl_sec.h"
|
||||
#include "curl_memory.h"
|
||||
#include "warnless.h"
|
||||
|
||||
|
||||
53
lib/ldap.c
53
lib/ldap.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
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -84,6 +84,9 @@ typedef struct {
|
||||
int lud_scope;
|
||||
char *lud_filter;
|
||||
char **lud_exts;
|
||||
size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the
|
||||
"real" struct so can only be used in code
|
||||
without HAVE_LDAP_URL_PARSE defined */
|
||||
} CURL_LDAPURLDesc;
|
||||
|
||||
#undef LDAPURLDesc
|
||||
@@ -260,7 +263,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
}
|
||||
server = ldapssl_init(conn->host.name, (int)conn->port, 1);
|
||||
if(server == NULL) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%hu",
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.name, conn->port);
|
||||
status = CURLE_COULDNT_CONNECT;
|
||||
goto quit;
|
||||
@@ -301,7 +304,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
}
|
||||
server = ldap_init(conn->host.name, (int)conn->port);
|
||||
if(server == NULL) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%hu",
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.name, conn->port);
|
||||
status = CURLE_COULDNT_CONNECT;
|
||||
goto quit;
|
||||
@@ -337,7 +340,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
else {
|
||||
server = ldap_init(conn->host.name, (int)conn->port);
|
||||
if(server == NULL) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%hu",
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.name, conn->port);
|
||||
status = CURLE_COULDNT_CONNECT;
|
||||
goto quit;
|
||||
@@ -539,19 +542,15 @@ static bool unescape_elements (void *data, LDAPURLDesc *ludp)
|
||||
if(ludp->lud_filter) {
|
||||
ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL);
|
||||
if(!ludp->lud_filter)
|
||||
return (FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for(i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) {
|
||||
ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i], 0, NULL);
|
||||
ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i],
|
||||
0, NULL);
|
||||
if(!ludp->lud_attrs[i])
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
for(i = 0; ludp->lud_exts && ludp->lud_exts[i]; i++) {
|
||||
ludp->lud_exts[i] = curl_easy_unescape(data, ludp->lud_exts[i], 0, NULL);
|
||||
if(!ludp->lud_exts[i])
|
||||
return (FALSE);
|
||||
return FALSE;
|
||||
ludp->lud_attrs_dups++;
|
||||
}
|
||||
|
||||
if(ludp->lud_dn) {
|
||||
@@ -637,8 +636,9 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
|
||||
|
||||
if(*p && *p != '?') {
|
||||
ludp->lud_scope = str2scope(p);
|
||||
if(ludp->lud_scope == -1)
|
||||
if(ludp->lud_scope == -1) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
LDAP_TRACE (("scope %d\n", ludp->lud_scope));
|
||||
}
|
||||
|
||||
@@ -651,25 +651,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
|
||||
q = strchr(p, '?');
|
||||
if(q)
|
||||
*q++ = '\0';
|
||||
if(!*p)
|
||||
if(!*p) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
ludp->lud_filter = p;
|
||||
LDAP_TRACE (("filter '%s'\n", ludp->lud_filter));
|
||||
|
||||
p = q;
|
||||
if(!p)
|
||||
goto success;
|
||||
|
||||
/* parse extensions
|
||||
*/
|
||||
ludp->lud_exts = split_str(p);
|
||||
if(!ludp->lud_exts)
|
||||
return LDAP_NO_MEMORY;
|
||||
|
||||
for(i = 0; ludp->lud_exts[i]; i++)
|
||||
LDAP_TRACE (("exts[%d] '%s'\n", i, ludp->lud_exts[i]));
|
||||
|
||||
success:
|
||||
if(!unescape_elements(conn->data, ludp))
|
||||
return LDAP_NO_MEMORY;
|
||||
@@ -697,7 +685,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
|
||||
|
||||
static void _ldap_free_urldesc (LDAPURLDesc *ludp)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
if(!ludp)
|
||||
return;
|
||||
@@ -709,16 +697,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp)
|
||||
free(ludp->lud_filter);
|
||||
|
||||
if(ludp->lud_attrs) {
|
||||
for(i = 0; ludp->lud_attrs[i]; i++)
|
||||
for(i = 0; i < ludp->lud_attrs_dups; i++)
|
||||
free(ludp->lud_attrs[i]);
|
||||
free(ludp->lud_attrs);
|
||||
}
|
||||
|
||||
if(ludp->lud_exts) {
|
||||
for(i = 0; ludp->lud_exts[i]; i++)
|
||||
free(ludp->lud_exts[i]);
|
||||
free(ludp->lud_exts);
|
||||
}
|
||||
free (ludp);
|
||||
}
|
||||
#endif /* !HAVE_LDAP_URL_PARSE */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user